static void _readMemory(int handle, ushort addr, ushort length) { int count; int i; byte[] data_in = new byte[length + 3]; for (int j = 0; j < length + 3; j++) { data_in[j] = 0; } CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Queue the read command, address, and data CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0x03); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)((addr >> 8) & 0xff)); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)((addr >> 0) & 0xff)); CheetahApi.ch_spi_queue_byte(handle, length, 0x00); CheetahApi.ch_spi_queue_ss(handle, 0); count = CheetahApi.ch_spi_batch_shift(handle, length + 3, data_in); if (count < 0) { Console.Write("error: {0:s}\n", CheetahApi.ch_status_string(count)); } else if (count != length + 3) { Console.Write("error: read {0:d} bytes (expected {1:d})\n", count - 3, length); } // Dump the data to the screen Console.Write("\nData read from device:"); for (i = 0; i < length; ++i) { if ((i & 0x0f) == 0) { Console.Write("\n{0:x4}: ", addr + i); } Console.Write("{0:x2} ", data_in[i + 3] & 0xff); if (((i + 1) & 0x07) == 0) { Console.Write(" "); } } Console.Write("\n"); Console.Out.Flush(); }
/*===================================================================== | GENERIC DETECTION ROUTINE | ====================================================================*/ static void find_devices() { ushort[] ports = new ushort[16]; uint[] unique_ids = new uint[16]; int nelem = 16; // Find all the attached devices int count = CheetahApi.ch_find_devices_ext(nelem, ports, nelem, unique_ids); int i; Console.Write("{0:d} device(s) found:\n", count); // Print the information on each device if (count > nelem) { count = nelem; } for (i = 0; i < count; ++i) { // Determine if the device is in-use String status = "(avail) "; if ((ports[i] & CheetahApi.CH_PORT_NOT_FREE) != 0) { ports[i] &= unchecked ((ushort)~CheetahApi.CH_PORT_NOT_FREE); status = "(in-use)"; } // Display device port number, in-use status, and serial number Console.Write(" port={0,-3:d} {1:s} ({2:d4}-{3:d6})\n", ports[i], status, unique_ids[i] / 1000000, unique_ids[i] % 1000000); } }
/*===================================================================== | 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(); } }
/*====================================================================== | MAIN PROGRAM | =====================================================================*/ public static void Main(String[] args) { int handle = 0; int port = 0; // open port 0 by default int bitrate = 0; int mode = 0; int bitorder = 0; int length = 0; if (args.Length < 5) { print_usage(); Environment.Exit(1); } port = Convert.ToInt32(args[0]); bitrate = Convert.ToInt32(args[1]); mode = Convert.ToInt32(args[2]); bitorder = Convert.ToInt32(args[3]); length = Convert.ToInt32(args[4]); handle = CheetahApi.ch_open(port); if (handle <= 0) { Console.Error.Write( "Unable to open Cheetah device on port {0:d}\n", port); Console.Error.Write("Error code = {0:d} ({1:s})\n", handle, CheetahApi.ch_status_string(handle)); Environment.Exit(1); } Console.Write("Opened Cheetah device on port {0:d}\n", port); Console.Write("Host interface is {0:s}\n", ((CheetahApi.ch_host_ifce_speed(handle)) != 0) ? "high speed" : "full speed"); // Ensure that the SPI subsystem is configured. // Make sure that the bitorder parameter is valid, defaulting to LSB CheetahSpiBitorder spi_bitorder = (bitorder == (int)CheetahSpiBitorder.CH_SPI_BITORDER_MSB) ? CheetahSpiBitorder.CH_SPI_BITORDER_MSB : CheetahSpiBitorder.CH_SPI_BITORDER_LSB; CheetahApi.ch_spi_configure( handle, (CheetahSpiPolarity)(mode >> 1), (CheetahSpiPhase)(mode & 1), spi_bitorder, 0x0); Console.Write( "SPI configuration set to mode {0:d}, {1:s} shift, " + "SS[2:0] active low\n", mode, (spi_bitorder == CheetahSpiBitorder.CH_SPI_BITORDER_MSB) ? "MSB" : "LSB"); Console.Out.Flush(); // Power the target using the Cheetah adapter's power supply. CheetahApi.ch_target_power(handle, CheetahApi.CH_TARGET_POWER_ON); CheetahApi.ch_sleep_ms(100); // Set the bitrate. bitrate = CheetahApi.ch_spi_bitrate(handle, bitrate); Console.Write("Bitrate set to {0:d} kHz\n", bitrate); Console.Out.Flush(); _blast(handle, length); // Close and exit. CheetahApi.ch_close(handle); return; }
/*====================================================================== | MAIN PROGRAM | =====================================================================*/ public static void Main(String[] args) { int handle = 0; int port = 0; // open port 0 by default int bitrate = 0; int mode = 0; ushort arg5 = 0; ushort arg6 = 0; String command = ""; String binfilepath = ""; Byte[] data; if (args.Length < 6) { print_usage(); Environment.Exit(1); } port = Convert.ToInt32(args[0]); bitrate = Convert.ToInt32(args[1]); mode = Convert.ToInt32(args[2]); command = args[3]; arg5 = Convert.ToUInt16(args[4]); arg6 = Convert.ToUInt16(args[5]); if (args.Length > 6) { binfilepath = args[6]; } handle = CheetahApi.ch_open(port); if (handle <= 0) { Console.Error.Write( "Unable to open Cheetah device on port {0:d}\n", port); Console.Error.Write("Error code = {0:d} ({1:s})\n", handle, CheetahApi.ch_status_string(handle)); Environment.Exit(1); } Console.Write("Opened Cheetah device on port {0:d}\n", port); Console.Write("Host interface is {0:s}\n", ((CheetahApi.ch_host_ifce_speed(handle)) != 0) ? "high speed" : "full speed"); // Ensure that the SPI subsystem is configured. CheetahApi.ch_spi_configure( handle, (TotalPhase.CheetahSpiPolarity)(mode >> 1), (TotalPhase.CheetahSpiPhase)(mode & 1), CheetahSpiBitorder.CH_SPI_BITORDER_MSB, 0x0); Console.Write("SPI configuration set to mode {0:d}, {1:s} shift, " + "SS[2:0] active low\n", mode, "MSB"); Console.Out.Flush(); // Power off the target using the Cheetah adapter's power supply. CheetahApi.ch_target_power(handle, CheetahApi.CH_TARGET_POWER_OFF); CheetahApi.ch_sleep_ms(100); // Power the target using the Cheetah adapter's power supply. CheetahApi.ch_target_power(handle, CheetahApi.CH_TARGET_POWER_ON); CheetahApi.ch_sleep_ms(100); // Set the bitrate. bitrate = CheetahApi.ch_spi_bitrate(handle, bitrate); Console.Write("Bitrate set to {0:d} kHz\n", bitrate); Console.Out.Flush(); // Determine which command transaction type was requested. int commandID = -1; if (command == "read") { commandID = COMMAND_READ; } else if (command == "write") { commandID = COMMAND_WRITE; } else if (command == "erase") { commandID = COMMAND_ERASE; } else if (command == "verify") { commandID = COMMAND_VERIFY; } else { Console.Write("Unknown option: {0:s}\n", command); Console.Write("Valid options are: read, write, erase, " + "and verify\n\n"); print_usage(); Environment.Exit(1); } // Execute the appropriate command. switch (commandID) { case COMMAND_READ: _read(handle, arg5, arg6, out data); break; case COMMAND_WRITE: _write(handle, arg5, binfilepath); break; case COMMAND_ERASE: _erase(handle, arg5, arg6); break; case COMMAND_VERIFY: _verify(handle, arg5 * 1024, arg6 * 1024); break; } // Power off the target using the Cheetah adapter's power supply. CheetahApi.ch_target_power(handle, CheetahApi.CH_TARGET_POWER_OFF); // Close the device. CheetahApi.ch_close(handle); return; }
static int _read(int handle, int addr, int length, out byte[] data_in) { // Convert address and length from KB to bytes addr *= 1024; length *= 1024; // Create the buffer to receive the flash values into. data_in = new byte[length]; for (int j = 0; j < length; j++) { data_in[j] = 0; } byte[] noresult = new byte[1]; CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Set slave select to deasserted state, in case it was left // low by a previously interrupted transaction (ctrl-c). This // will reset the state machine inside the flash. CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_ss(handle, 1); // Queue fast read command code. CheetahApi.ch_spi_queue_byte(handle, 1, 0x0b); // Queue 3 bytes of address. CheetahApi.ch_spi_queue_byte(handle, 1, (byte)(addr >> 16)); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)(addr >> 8)); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)(addr >> 0)); // Queue dummy byte. CheetahApi.ch_spi_queue_byte(handle, 1, 0); // Shift the queued fast read command. int count = CheetahApi.ch_spi_batch_shift(handle, 0, data_in); if (count != 5) { Console.Error.Write("Expected 5 bytes from initial shift\n"); return(1); } // Read the data. // Set the value to send while reading the flash. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_byte(handle, length, 0x00); count = CheetahApi.ch_spi_batch_shift(handle, length, data_in); if (count != length) { Console.Error.Write("Expected {0:d} bytes from read shift " + "(got {1:d})\n", length, count); return(1); } // Dump the data to the screen //int i; //Console.Write("\nData read from device:"); //for (i=0; i < length; ++i) { // if ((i&0x0f) == 0) Console.Write("\n{0:x4}: ", addr+i); // Console.Write("{0:x2} ", data_in[i] & 0xff); // if (((i+1)&0x07) == 0) Console.Write(" "); //} //Console.Write("\n"); //Console.Out.Flush(); // Clear the state of the bus. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_oe(handle, 0); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); return(0); }
static int _verify(int handle, int length, int blocksize) { if (length == 0 || blocksize == 0) { return(2); } byte[] noresult = new byte[1]; int iter = (length - 1) / blocksize + 1; // Create the buffer to receive the flash values into. byte[] data_in = new byte[blocksize]; for (int j = 0; j < blocksize; j++) { data_in[j] = 0; } CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Set slave select to deasserted state, in case it was left // low by a previously interrupted transaction (ctrl-c). This // will reset the state machine inside the flash. CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_ss(handle, 1); // Queue fast read command code. CheetahApi.ch_spi_queue_byte(handle, 1, 0x0b); // Queue 3 bytes of address. CheetahApi.ch_spi_queue_byte(handle, 1, 0); CheetahApi.ch_spi_queue_byte(handle, 1, 0); CheetahApi.ch_spi_queue_byte(handle, 1, 0); // Queue dummy byte. CheetahApi.ch_spi_queue_byte(handle, 1, 0); // Shift the queued fast read command. int count = CheetahApi.ch_spi_batch_shift(handle, 5, data_in); if (count != 5) { Console.Write("Expected 5 bytes from initial shift\n"); return(1); } // Set the value to send while reading the flash. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_byte(handle, blocksize, 0x00); int i; ulong start = _timeMicroseconds(); // Variables for the integrity check. uint integrity_counter = 0; int integrity_errors = 0; int integrity_nb = 0; _printProgress(0, 0, 0, blocksize); // Read one block at a time. for (i = 0; i < iter; ++i) { // Read the next block of data. count = CheetahApi.ch_spi_batch_shift(handle, blocksize, data_in); if (count != blocksize) { Console.Write("Expected {0:d} bytes from block shift " + "(got {1:d})\n", blocksize, count); break; } // Check if the data in the flash matches a predefined // sequence. Namely, there should be a running 32 bit // counter in the data. int j = 0; while (integrity_nb < INTEGRITY_CHECK_NUM_BYTES && j < count) { uint val = (uint)((data_in[j + 0] << 24) | (data_in[j + 1] << 16) | (data_in[j + 2] << 8) | (data_in[j + 3] << 0)); if (val != integrity_counter % INTEGRITY_LOOP_SIZE) { ++integrity_errors; } ++integrity_counter; integrity_nb += 4; j += 4; } // Print out the progress. ulong currTime = _timeMicroseconds(); _printProgress((i + 1) * 100 / iter, ((double)(currTime - start)) / 1000000, i, blocksize); } // Clear the state of the flash. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0); CheetahApi.ch_spi_queue_oe(handle, 0); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); Console.Out.Flush(); Console.Error.Write("\nThere were {0:d} data errors.\n", integrity_errors); return((integrity_errors != 0) ? 2 : 0); }
//suppose this is the block erase function,sector size is 4k ,block size is 32k/64k //command d8 is block erase command static int _erase(int handle, int sector, int num) { byte[] noresult = new byte[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, 0); CheetahApi.ch_spi_batch_shift(handle, 0, noresult); int eraseAll = 0; if (sector == 0 && num == 2048) { eraseAll = 1; } String str; if (eraseAll != 0) { str = "Bulk"; } else { str = "Block"; } while (num != 0) { // Make sure the sector is a valid one. if (sector < 0 || sector > 2047) { break; } int addr = sector << 12; if (eraseAll == 0) { Console.Write("Erasing sector {0:d2} (bytes 0x{1:x6} " + "to 0x{2:x6})...\n", sector, addr, addr | 0xfff); Console.Out.Flush(); } else { Console.Write("Erasing entire device...\n"); Console.Out.Flush(); } // Start the erase sequence. CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); // Queue the write enable instruction for the flash. 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_queue_ss(handle, 0x1); if (eraseAll == 0) { // Queue the sector erase command. CheetahApi.ch_spi_queue_byte(handle, 1, 0x20); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)((addr >> 16) & 0xff)); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)((addr >> 8) & 0xff)); CheetahApi.ch_spi_queue_byte(handle, 1, (byte)((addr >> 0) & 0xff)); } else { // Queue the chip erase command. CheetahApi.ch_spi_queue_byte(handle, 1, 0xc7); } CheetahApi.ch_spi_queue_ss(handle, 0); // Shift the queued commands. (Don't need the data back.) 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); } ulong start = _timeMicroseconds(); CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_ss(handle, 0x1); CheetahApi.ch_spi_queue_byte(handle, 1, 0x05); CheetahApi.ch_spi_queue_byte(handle, 1, 0x00); CheetahApi.ch_spi_queue_ss(handle, 0); while (true) { CheetahApi.ch_sleep_ms(10); byte[] status_in = new byte[2]; CheetahApi.ch_spi_batch_shift(handle, 2, status_in); if ((status_in[1] & 0x01) == 0) { break; } } ulong end = _timeMicroseconds(); Console.Write("{0:s} erase took {1:f3} seconds\n", str, (double)(end - start) / 1000000); Console.Out.Flush(); if (eraseAll == 0) { ++sector; --num; } else { sector += 64; num = 0; } } // 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); return(0); }
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 _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(); }
/*===================================================================== | 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(); } }
/*========================================================================= | MAIN PROGRAM | ========================================================================*/ public static void Main(String[] args) { int handle = 0; int port = 0; // open port 0 by default int bitrate = 0; int mode = 0; ushort addr = 0; ushort length = 0; String command = ""; if (args.Length < 6) { print_usage(); Environment.Exit(1); } port = Convert.ToInt32(args[0]); bitrate = Convert.ToInt32(args[1]); mode = Convert.ToInt32(args[2]); command = args[3]; addr = Convert.ToUInt16(args[4]); length = Convert.ToUInt16(args[5]); // Open the device handle = CheetahApi.ch_open(port); if (handle <= 0) { Console.Error.Write( "Unable to open Cheetah device on port {0:d}\n", port); Console.Error.Write("Error code = {0:d} ({1:s})\n", handle, CheetahApi.ch_status_string(handle)); Environment.Exit(1); } Console.Write("Opened Cheetah device on port {0:d}\n", port); Console.Write("Host interface is {0:s}\n", ((CheetahApi.ch_host_ifce_speed(handle)) != 0) ? "high speed" : "full speed"); // Ensure that the SPI subsystem is configured CheetahApi.ch_spi_configure( handle, (TotalPhase.CheetahSpiPolarity)(mode >> 1), (TotalPhase.CheetahSpiPhase)(mode & 1), CheetahSpiBitorder.CH_SPI_BITORDER_MSB, 0x0); Console.Write("SPI configuration set to mode {0:d}, {1:s} shift, " + "SS[2:0] active low\n", mode, "MSB"); Console.Out.Flush(); // Power the target using the Cheetah adapter's power supply CheetahApi.ch_target_power(handle, CheetahApi.CH_TARGET_POWER_ON); CheetahApi.ch_sleep_ms(100); // Set the bitrate bitrate = CheetahApi.ch_spi_bitrate(handle, bitrate); Console.Write("Bitrate set to {0:d} kHz\n", bitrate); Console.Out.Flush(); byte[] noresult = new byte[1]; // Shift a dummy byte to clear the EEPROM state CheetahApi.ch_spi_queue_clear(handle); CheetahApi.ch_spi_queue_oe(handle, 1); 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, 0, noresult); // Perform the requested operation if (command == "write") { _writeMemory(handle, addr, length, 0); Console.Write("Wrote to EEPROM\n"); } else if (command == "read") { _readMemory(handle, addr, length); } else if (command == "zero") { _writeMemory(handle, addr, length, 1); Console.Write("Zeroed EEPROM\n"); } else { Console.Write("unknown command: {0:s}\n", command); } // Close and exit CheetahApi.ch_close(handle); return; }
/*===================================================================== | 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); }