/*===================================================================== | FUNCTIONS | ====================================================================*/ static void _blast(int handle, int length) { double elapsed; ulong start = _timeMillis(); // Queue the read sequence CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_ss(handle, 0x1); int delay = 0; int j; for (j = 0; j < length; ++j) { CheetahApi.ch_spi_queue_byte(handle, 1, (byte)(j & 0xff)); delay = CheetahApi.ch_spi_queue_delay_ns(handle, BYTE_DELAY); } Console.Write("Queued delay of {0:d} ns between bytes.\n", delay); Console.Out.Flush(); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_oe(handle, 0); elapsed = ((double)(_timeMillis() - start)) / 1000; Console.Write("Took {0:f2} seconds to queue the batch.\n", elapsed); Console.Out.Flush(); // Perform the shift int batch = CheetahApi.ch_spi_batch_length(handle); byte[] data_in = new byte[batch]; start = _timeMillis(); int count = CheetahApi.ch_spi_batch_shift(handle, batch, data_in); elapsed = ((double)(_timeMillis() - start)) / 1000; Console.Write("Took {0:f2} seconds to shift the batch.\n", elapsed); Console.Out.Flush(); if (count != batch) { Console.Write("Expected {0:d} bytes but only received {1:d} " + "bytes\n", batch, count); } if (SHOW_DATA) { // Output the data to the screen Console.Write("\nData:"); int i; for (i = 0; i < length; ++i) { if ((i & 0x07) == 0) { Console.Write("\n{0:x4}: ", i); } Console.Write("{0:x2}/{1:x2} ", (i & 0xff), data_in[i]); } Console.Write("\n"); Console.Out.Flush(); } }
/*===================================================================== | FUNCTIONS | ====================================================================*/ static void _writeMemory(int handle, ushort addr, ushort length, int zero) { short i, j, n; int batch, count; byte[] data_out = new byte[3 + PAGE_SIZE]; byte[] noresult = new byte[1]; // Write to the SPI EEPROM // // The AT25080A EEPROM has 32 byte pages. Data can be written // in pages, to reduce the number of overall SPI transactions // executed through the Cheetah adapter. n = 0; while (n < length) { CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Send PAGE_WRITE_BATCH_SIZE number of pages to the Cheetah per // batch shift for (i = 0; i < PAGE_WRITE_BATCH_SIZE; i++) { if (n >= length) { break; } // Send write enable command CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0x06); CheetahApi.ch_spi_queue_ss(handle, 0); // Assemble the write command and address Console.Write("addr = 0x{0:x4}; ", addr); data_out[0] = (byte)0x02; data_out[1] = (byte)((addr >> 8) & 0xff); data_out[2] = (byte)((addr >> 0) & 0xff); // Assemble the data j = 3; do { data_out[j++] = (zero != 0) ? (byte)0 : (byte)n; ++addr; ++n; } while ((n < length) && ((addr & (PAGE_SIZE - 1)) != 0)); Console.Write("num bytes = {0:d}\n", j - 3); Console.Out.Flush(); // Queue the write transaction CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_array(handle, j, data_out); CheetahApi.ch_spi_queue_ss(handle, 0); // Put in a wait for the write cycle time CheetahApi.ch_spi_queue_delay_ns(handle, PAGE_WRITE_DELAY_NS); } // Shift the page writes // Don't need the results back from the shift Console.Write("Shifting data\n"); Console.Out.Flush(); batch = CheetahApi.ch_spi_batch_length(handle); count = CheetahApi.ch_spi_batch_shift(handle, 0, noresult); if (count != batch) { Console.Write("Expected {0:d} bytes but only received " + "{1:d} bytes\n", batch, count); return; } Console.Write("Shift complete\n"); Console.Out.Flush(); } }
static int _write(int handle, int addr, string binfile) { ulong start = _timeMicroseconds(); //Read bin file BinaryReader br; try { br = new BinaryReader(new FileStream(binfile, FileMode.Open)); } catch (IOException e) { Console.WriteLine(e.Message + "\n Cannot open file."); return(-1); } int data_length = Convert.ToInt32(br.BaseStream.Length); int data_pad_length = 1024 - data_length % 1024; byte[] bin_data = new byte[data_length]; bin_data = br.ReadBytes(data_length); byte[] data = new byte[data_length + data_pad_length]; byte[] data_in = new byte[data_length + data_pad_length];; int addr_back = addr; bin_data.CopyTo(data, 0); if (data_pad_length != 0) { for (int i = 0; i < data_pad_length; i++) { data[data_length + i] = (byte)(255); } } br.Close(); //Upate data_length to data_length + data_pad_length data_length = data_length + data_pad_length; // Buffer for outgoing data. byte[] data_page = new byte[4 + PAGE_SIZE]; byte[] noresult = new byte[1]; byte[] data_back = new byte[5]; //Erase first _erase(handle, addr / 4, (data.Length / (4 * 1024)) + 1); // Reset the state of the bus. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_oe(handle, 1); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // Convert address and length from KB to bytes addr *= 1024; // Set the starting counter based on the address. int val = addr / 4; int pages = 0; int retry = 0; while (data_length != 0) { // Start the write sequence. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Send PAGE_WRITE_BATCH_SIZE number of pages to the Cheetah per // batch shift. Here we only program one page each batch for (int i = 0; i < PAGE_WRITE_BATCH_SIZE; i++) { // Check if we've reached the end. if (data_length == 0) { break; } CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0x06); CheetahApi.ch_spi_queue_ss(handle, 0); //while (((data_back[0]>>1 & 0x01) != 1) && (retry++ < 100) ) { // // Queue the write enable instruction for the flash. // //Write enable command 0x06 // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x06); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // CheetahApi.ch_spi_queue_clear(handle); // //Send RDSR Command check WEL bit = 1? // //Shift out RDSR Command First 0x05 // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x05); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle, 0,noresult); // CheetahApi.ch_spi_queue_clear(handle); // //Read One Byte Data Back // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x00); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle,1, data_back); // CheetahApi.ch_spi_queue_clear(handle); //} //if (retry >= 100) //{ // Console.Write("Write Enable Failed.\n"); // Console.Out.Flush(); // return 1; //} // Queue the write instruction for the flash. // Page write command 0x02 + ADDR[3] + BYTE[256] CheetahApi.ch_spi_queue_ss(handle, 0x1); data_page[0] = 0x02; data_page[1] = (byte)((addr >> 16) & 0xff); data_page[2] = (byte)((addr >> 8) & 0xff); data_page[3] = (byte)((addr >> 0) & 0xff); Console.Write("addr = 0x{0:x6}; num bytes = {1:d}\n", addr, PAGE_SIZE); Console.Out.Flush(); // Set the data to be written to the flash to incrementing // 32-bit values starting from 0. int j = 0; while (j < PAGE_SIZE) { data_page[4 + j] = data[j + pages * 256]; j += 1; } CheetahApi.ch_spi_queue_array(handle, 4 + PAGE_SIZE, data_page); CheetahApi.ch_spi_queue_ss(handle, 0); // Give the flash time to commit the written values. // Using ch_spi_queue_delay_ns is much more accurate than // using ch_sleep_ms. CheetahApi.ch_spi_queue_delay_ns(handle, PAGE_PROGRAM_CYCLE_TIME_NS); addr += PAGE_SIZE; data_length -= PAGE_SIZE; pages += 1; } // Shift out the write command. (Don't need the data back.) Console.Write("Shifting data\n"); Console.Out.Flush(); int batch = CheetahApi.ch_spi_batch_length(handle); int count = CheetahApi.ch_spi_batch_shift(handle, 0, noresult); if (count != batch) { Console.Write("Expected {0:d} bytes but only received " + "{1:d} bytes\n", batch, count); return(1); } ////Wait Programming Page Finished. Check WIP = 0? //retry = 0; //data_back[0] = (byte)(0xff); //while (((data_back[0] & 0x01) != 0) && (retry++ < 100)) //{ // CheetahApi.ch_spi_queue_clear(handle); // //Send RDSR Command check WIP bit = 0? // //Shift out RDSR Command First 0x05 // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x05); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_length(handle); // CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // CheetahApi.ch_spi_queue_clear(handle); // //Read One Byte Data Back // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x00); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle, 1, data_back); // CheetahApi.ch_spi_queue_clear(handle); //} //if (retry >= 100) //{ // Console.Write("Write Enable Failed.\n"); // Console.Out.Flush(); // return 1; //} Console.Write("Shift complete\n"); Console.Out.Flush(); // //Check Programming Result // //Send RDSCUR Command 2B // //Read Security Register bit 5 // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x2b); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // CheetahApi.ch_spi_queue_clear(handle); // //Read One Byte Data Back // data_back[0] = (byte)(0xff); // CheetahApi.ch_spi_queue_ss(handle, 0x1); // CheetahApi.ch_spi_queue_byte(handle, 1, 0x00); // CheetahApi.ch_spi_queue_ss(handle, 0); // CheetahApi.ch_spi_batch_shift(handle, 1, data_back); // CheetahApi.ch_spi_queue_clear(handle); // //Check P_FAIL bit = 0? 0-> PP pass ,1-> PP fail // if ((data_back[0]>>5 & 0x01) != 0) // { // Console.Write("PP Failed...,PFAIL Flag == 1.\n"); // Console.Out.Flush(); // return 1; // } } // Reset the state of the bus. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 0); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); ulong end = _timeMicroseconds(); Console.Write("Flashing take {0 :f3} seconds\n", (double)(end - start) / 1000000); Console.Out.Flush(); //verify the programming data is correct... _read(handle, addr_back, data.Length / 1024, out data_in); bool compare_result = false; for (int k = 0; k < data.Length; k++) { if (data[k] != data_in[k]) { compare_result = true; break; } } end = _timeMicroseconds(); Console.Write("Totally take {0 :f3} seconds\n", (double)(end - start) / 1000000); if (!compare_result) { Console.Write("Flashing Successfull...\n"); Console.Out.Flush(); return(0); } else { Console.Write("Flashing Failed...\n"); Console.Out.Flush(); return(-1); } }
/*===================================================================== | FUNCTIONS | ====================================================================*/ static void _timing(int handle) { int cycles; int ns; byte[] noresult = new byte[1]; // Test the SS timing CheetahApi.ch_spi_queue_clear(handle); Console.Write("Testing inter-SS delays...\n"); Console.Out.Flush(); CheetahApi.ch_spi_queue_oe(handle, 1); CheetahApi.ch_spi_queue_ss(handle, 0x1); cycles = CheetahApi.ch_spi_queue_delay_cycles(handle, 51); Console.Write(" Queued delay of {0:d} cycles within first SS " + "assert/deassert.\n", cycles); Console.Out.Flush(); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_ss(handle, 0x1); ns = CheetahApi.ch_spi_queue_delay_ns(handle, 1500000); Console.Write(" Queued delay of {0:d} ns within second SS " + "assert/deassert.\n", ns); Console.Out.Flush(); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // Test data timing in read mode Console.Write("Testing inter-data (read) delays...\n"); Console.Out.Flush(); CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0xca); ns = CheetahApi.ch_spi_queue_delay_ns(handle, 250000); Console.Write(" Queued delay of {0:d} ns after first byte " + "(0xca).\n", ns); Console.Out.Flush(); CheetahApi.ch_spi_queue_byte(handle, 2, 0xfe); cycles = CheetahApi.ch_spi_queue_delay_cycles(handle, 995); Console.Write(" Queued delay of {0:d} cycles after second byte " + "(0xfe).\n", cycles); Console.Out.Flush(); CheetahApi.ch_spi_queue_byte(handle, 3, 0x00); cycles = CheetahApi.ch_spi_queue_delay_cycles(handle, 20); Console.Write(" Queued delay of {0:d} cycles after last byte " + "(0x00).\n", cycles); Console.Out.Flush(); CheetahApi.ch_spi_queue_ss(handle, 0); byte[] data_in = new byte[6]; CheetahApi.ch_spi_batch_shift(handle, 6, data_in); // Test data timing with write mode Console.Write("Testing inter-data (write) delays...\n"); Console.Out.Flush(); CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0xba); ns = CheetahApi.ch_spi_queue_delay_ns(handle, 80000); Console.Write(" Queued delay of {0:d} ns after first byte " + "(0xba).\n", ns); Console.Out.Flush(); CheetahApi.ch_spi_queue_byte(handle, 2, 0xbe); cycles = CheetahApi.ch_spi_queue_delay_cycles(handle, 995); Console.Write(" Queued delay of {0:d} cycles after second byte " + "(0xbe).\n", cycles); Console.Out.Flush(); CheetahApi.ch_spi_queue_byte(handle, 3, 0x00); cycles = CheetahApi.ch_spi_queue_delay_cycles(handle, 20); Console.Write(" Queued delay of {0:d} cycles after last byte " + "(0x00).\n", cycles); Console.Out.Flush(); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_oe(handle, 0); CheetahApi.ch_spi_batch_shift(handle, 1, data_in); }