These are commands that are not (yet) explicitly exposed in the C# and C++ library (they are constants define / enum: SPI_Command in a te_api.h firmware file ?????).
SPI Flash | commands#define SPI_READ 0x03command | Description |
---|---|---|
#define SPI_WREN 0x06 | Set Write Enable Latch | |
#define SPI_WRDI 0x04 | Reset Write Enable Latch | |
#define SPI_RDSR1 0x05 | Read Status Register 1 | |
#define SPI_RDSR2 0x35 | Read Status Register 2 | |
#define SPI_WRSR 0x01 | Write Status Register | |
#define SPI_READ 0x03 | Read data from memory | |
#define SPI_FAST_READ 0x0b | Similar to the READ command, but possibly uses a faster clock | |
#define | #defineSPI_WRITE 0x02 | Write data to memory array |
#define SPI_SE 0xD8 | Erase one sector in memory | |
#define SPI_BE 0xC7 | Erase all memory | |
#define SPI_DP 0xb9 | Write Enable Command | |
#define SPI_RES 0xab | Read Electonic Signature | |
#define SPI_RDID 0x9F | reads the ID of the SPI Flash |
The SPI Command can be dispatched through
...
...
First case example (reads the ID of the SPI Flash) | |
---|---|
SW host computer: |
...
reads the ID of the SPI Flash | // This is pseudocode close to the real one.
{ LogTextLine
} | |||||||||||||||||||||||||||
//This is a piece of real code (FW running on USB FX2 microcontroller) case CMD_FLASH_WRITE_COMMAND: EP1INBUF[0] = 0x55; //void spi_command(BYTE CmdLen, unsigned char *CmdData, BYTE RdLen, unsigned char *RdData) spi_command(EP1OUTBUF[1], &EP1OUTBUF[3], EP1OUTBUF[2], &EP1INBUF[1]); new_data = 1; break; /* Command[0] = CMD_FLASH_WRITE_COMMAND; used by TE_USB_FX2_SendCommand () to call "case CMD_FLASH_WRITE_COMMAND" and then spi_command() EP1OUTBUF[1] = CmdLen = Command[1]= CmdLength = 1; // used by spi_command(), MD_SPI_RDID = 0x9F is a single byte EP1OUTBUF[2] = RdLen = Command[2]= ReplyLength = 3; // used by spi_command(), SPI Flash ID should be 3 byte EP1OUTBUF[3] = Command[3] = CMD_SPI_RDID = 0x9F; //used by spi_command() Reply[0] = EP1INBUF[0] = 0x55; Reply[1] = EP1INBUF[1] = 0xEF; // for example Reply[2] = EP1INBUF[2] = 0x40; // for example Reply[3] = EP1INBUF[3] = 0x17; // for example */ | ||||||||||||||||||||||||||||
byte[] Command1 = new byte[64];
byte[] Reply1 = new byte[64];
int CmdLength1 = 4;
int ReplyLength1 = 64;
byte[] Command2 = new byte[64];
byte[] Reply2 = new byte[64];
int CmdLength2 = 64;
int ReplyLength2 = 64;
//To use the firmware function spi_command() you need to use a double indirection
Command2[0] = (byte)FX2_Commands.CMD_FX2_FLASH_WRITE_COMMAND;
Command2[1] = (byte)0x01;//(byte)FX2_Commands.CMD_SPI_RDID;
Command2[2] = (byte)0x03;
Command2[3] = (byte)0x9F;
//To use the firmware function spi_command() you need to use a double indirection
Command1[0] = Command2[0];
Command1[1] = Command2[1];
Command1[2] = Command2[2];
Command1[3] = Command2[3];
Command1[4] = (byte)0;
Command1[5] = (byte)0;
Command1[6] = (byte)0;
if (TE_USB_FX2.TE_USB_FX2.TE_USB_FX2_SendCommand(ref TE_USB_FX2_USBDevice, ref Command1, ref CmdLength1, ref Reply1, ref ReplyLength1, 5000) == true)
{
LogTextLine += "SPI Flash IDCODE 0x" + Reply1[1].ToString("x") + " 0x"
+ Reply1[2].ToString("x") + " 0x" + Reply1[3].ToString("x") + "\r\n";
}
else
{
LogTextLine += "SPI Flash IDCODE 0x" + Reply1[1].ToString("x") + " 0x"
+ Reply1[2].ToString("x") + " 0x" + Reply1[3].ToString("x") + "\r\n";
}
-------------------------------------------------
-----------------------
Lines 207-211 : TE API Command CMD_FLASH_WRITE_COMMAND =
case CMD_FLASH_WRITE_COMMAND:
EP1INBUF[0] = 0x55;
spi_command(EP1OUTBUF[1], &EP1OUTBUF[3], EP1OUTBUF[2], &EP1INBUF[1]);
new_data = 1;
break;
where
Lines 63-89
void spi_command(BYTE CmdLen, unsigned char *CmdData, BYTE RdLen, unsigned char *RdData){
volatile unsigned char spi_count, rd_buff;// pr_address;
OED = 0x73; // 0b01110011;
FPGA_POWER = 0; //power off fpga
FLASH_ENABLE; //assert chip select
//Write command
spi_count = CmdLen;
if (spi_count > 64) spi_count = 64;
while (spi_count > 0){
putcSPI(*CmdData); //send read command
CmdData++;
spi_count = spi_count - 1;
}
//Read response
spi_count = RdLen;
if (spi_count > 64) spi_count = 64;
while (spi_count > 0){
rd_buff = getcSPI();
*RdData = rd_buff;
RdData++;
spi_count = spi_count - 1;
}
FLASH_DISABLE;
}
However, there is a problem with SPI_RDID command used in process_flash_id() : it requires two "settings" not normally present (FPGA_PROG = 0; and busy_polling();) spi_command () function has a setting not equired (FPGA_POWER=0;) for SPI_RDID used in process_flash_id().
https://github.com/Trenz-Electronic/FX2CDC/blob/master/vcom-cli/te_vcom.c
Lines 353 - 359
if(string_match("flash id",command_buf)){
//FPGA_POWER = 0;
FPGA_PROG = 0; //It is not like spi_command() that use FPGA_POWER = 0;
OED = 0x73; // Configure MOSI, CCLK, CSO_B, PS_ON, PROG as outputs
process_flash_id();
processed = 1;
}
Lines 212 -234
void process_flash_id(void) {
BYTE mid, did, uid;
char msg[] = "IDCODE ??????";
busy_polling();
FLASH_ENABLE; // assert chip select putcSPI(SPI_RDID); // get ID command
mid = getcSPI();
did = getcSPI();
uid = getcSPI();
FLASH_DISABLE; // negate chip select
msg[7] = hex_char_h(mid);
msg[8] = hex_char_l(mid);
msg[9] = hex_char_h(did);
msg[10] = hex_char_l(did);
msg[11] = hex_char_h(uid);
msg[12] = hex_char_l(uid);
//print_ep6_string(msg);
//if((mid == 0xEF) && (did == 0x40) && (uid == 0x17))
// print_ep6_string("W25Q64FV");
//if((mid == 0x20) && (did == 0x20) && (uid == 0x16))
// print_ep6_string("M25P32");
}
/* Wait till Flash ready */
void busy_polling (void) {
unsigned char sr = 1;
while ((sr & 0x01) != 0) { // stay in loop until !busy
FLASH_ENABLE; // assert chip select
putcSPI(SPI_RDSR1); // send read status register command
sr = getcSPI(); // read data byte
FLASH_DISABLE; // negate chip select
}
}
In particular, I have tried in two ways with CmdLength = 4 (Command[0] to Command[3]) and ReplyLength = 4; (Reply[0] to Reply[3]).
Command[0] = (byte) FX2_Commands.CMD_FX2_FLASH_WRITE_COMMAND;
Command[1] = (byte) 1; //Numeber of SPI commands used by spi_command() : putcSPI(SPI_RDID); // get ID command
Command[2] = (byte) 3; //Number of SPI bytes as reply: mid == 0xEF && did == 0x40 && uid == 0x17
Command[3] = (byte) 0x9F;//(byte)SPI_Commands.CMD_SPI_RDID;
Command[4] = (byte)0;
Command[5] = (byte)0;
Command[6] = (byte)0;
/* The code in green doesn't work because the default of TE_API is CMD_READ_VERSION, so this command is seen as equal to
CMD_READ_VERSION and gives Firmware Version number 3.2.1.1
SEE these lines of code (99-113) at https://github.com/Trenz-Electronic/TE-USB-Suite/blob/master/TE_USB_FX2.firmware/te_usb_api.ver.3.2/te_api.c
//if( !( EP1OUTCS & 0x02) ){ // Got something
// cmd_cnt++;
// for (i = 0; i < 0x40; i++)
// EP1INBUF[i] = 0xFF; // fill output buffer
// switch(EP1OUTBUF[0]){ // Decode command
// //-----------------------------------------------------------------
// default:
// case CMD_READ_VERSION:
// EP1INBUF[0] = fx2_ver_maj_;
// EP1INBUF[1] = fx2_ver_min_;
// EP1INBUF[2] = fx2_tip_maj_;
// EP1INBUF[3] = fx2_tip_min_;
// new_data = 1;
// break;
Command[0] = (byte) 0x9F;//(byte)FX2_Commands.CMD_SPI_RDID;
Command[1] = (byte)0; //(byte)FX2_Parameters.MB_I2C_ADDRESS;
Command[2] = (byte)0; //(byte)FX2_Parameters.I2C_BYTES_SIZE;
Command[3] = (byte)0;
Command[4] = (byte)0;
Command[5] = (byte)0;
Command[6] = (byte)0;
//SPI_RDID 0x9F
*/
if (TE_USB_FX2.TE_USB_FX2.TE_USB_FX2_SendCommand(ref TE_USB_FX2_USBDevice, ref Command, ref CmdLength, ref Reply, ref ReplyLength, 20000) == false)
LogTextLine += "Doesn't work" + "\r\n";
else {
LogTextLine += "R1 " + Reply[1].ToString("x") + "\r\n";
LogTextLine += "R2 " + Reply[2].ToString("x") + "\r\n";
LogTextLine += "R3 " + Reply[3].ToString("x") + "\r\n";
LogTextLine += "R4 " + Reply[4].ToString("x") + "\r\n";
LogTextLine += "R5 " + Reply[5].ToString("x") + "\r\n";
LogTextLine += "R6 " + Reply[6].ToString("x") + "\r\n";
LogTextLine += "R7 " + Reply[7].ToString("x") + "\r\n";
LogTextLine += "R8 " + Reply[8].ToString("x") + "\r\n";
LogTextLine += "R9 " + Reply[9].ToString("x") + "\r\n"; }
...
| ||||||||||||||||||||||||
FW running on USB FX2 microcontroller This is a piece of real code (FW running on USB FX2 microcontroller) te_api.c, lines 207-211 EP1INBUF: read Reply[] from USB FX2 microcontroller to host computer EP1OUTBUF: write Command[] from host computer to USB FX2 microcontroller
| ||||||||||||||||||||||||
FW running on USB FX2 microcontroller This is a piece of real code spi.c, lines 63-89
|