/*====================================================================== | FUNCTIONS | =====================================================================*/ static void _blast_async(int handle, int txnlen, int iter) { double elapsed = 0; byte[] noresult = new byte[1]; // Make a simple queue to just assert OE. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, (byte)1); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); // Queue the batch which is a sequence of SPI packets // (back-to-back) each of length 4. CheetahApi.ch_spi_queue_clear(handle); int i; int count = 0; byte[] data_out = new byte[4]; for (i = 0; i < txnlen; ++i) { CheetahApi.ch_spi_queue_ss(handle, 0x1); data_out[0] = (byte)((count >> 24) & 0xff); data_out[1] = (byte)((count >> 16) & 0xff); data_out[2] = (byte)((count >> 8) & 0xff); data_out[3] = (byte)((count >> 0) & 0xff); ++count; CheetahApi.ch_spi_queue_array(handle, 4, data_out); CheetahApi.ch_spi_queue_ss(handle, 0x0); } ulong start = _timeMillis(); // First, submit first batch CheetahApi.ch_spi_async_submit(handle); int n, ret; for (n = 0; n < iter - 1; ++n) { // Submit another batch, while the previous one is in // progress. The application may even clear the current // batch queue and queue a different set of SPI // transactions before submitting this batch // asynchronously. CheetahApi.ch_spi_async_submit(handle); // The application can now perform some other functions // while the Cheetah is both finishing the previous batch // and shifting the current batch as well. In order to // keep the Cheetah's pipe full, this entire loop must // complete AND another batch must be submitted // before the current batch completes. CheetahApi.ch_sleep_ms(25); // Collect the previous batch ret = CheetahApi.ch_spi_async_collect(handle, 0, noresult); elapsed = ((double)(_timeMillis() - start)) / 1000; Console.Write("collected batch #{0:d3} in {1:f2} seconds\n", n + 1, elapsed); if (ret < 0) { Console.Write("status error: {0:s}\n", CheetahApi.ch_status_string(ret)); } Console.Out.Flush(); start = _timeMillis(); // The current batch is now shifting out on the SPI // interface. The application can again do some more tasks // here but this entire loop must finish so that a new // batch is armed before the current batch completes. CheetahApi.ch_sleep_ms(25); } // Collect batch the last batch ret = CheetahApi.ch_spi_async_collect(handle, 0, noresult); elapsed = ((double)(_timeMillis() - start)) / 1000; Console.Write("collected batch #{0:d3} in {1:f2} seconds\n", n + 1, elapsed); if (ret < 0) { Console.Write("status error: {0:s}\n", CheetahApi.ch_status_string(ret)); } 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 _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(); } }