Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

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 command

Description
#define SPI_WREN 0x06Set Write Enable Latch
#define SPI_WRDI 0x04Reset Write Enable Latch
#define SPI_RDSR1 0x05Read Status Register 1
#define SPI_RDSR2 0x35Read Status Register 2
#define SPI_WRSR 0x01Write Status Register
#define SPI_READ 0x03Read data from memory
#define SPI_FAST_READ 0x0bSimilar to the READ command, but possibly uses a faster clock
#define SPI_WRITE 0x02Write data to memory array
#define SPI_SE 0xD8Erase one sector in memory
#define SPI_BE 0xC7Erase all memory
#define SPI_DP 0xb9Write Enable Command

#define SPI_RES 0xab

Read Electonic Signature
#define SPI_RDID 0x9Freads the ID of the SPI Flash

The SPI Command can be dispatched through

  • a particular SW API function: TE_USB_FX2_SendCommand(..., command_arrayCommand, …) where
  • "command_array" is a byte array that contains both
    • CMD_FLASH_WRITE_COMMAND (call the spi_command() firmware function in the TE USB FX2 microcontroller) and
    • SPI Flash Commands (multiple SPI Flash Commands could be dispatched through spi_command() firmware called before).

...

In particular, SPI Flash Commands could be used:

 

  • to reads the ID of the SPI Flash (# Define SPI_RDID 0x9F)
  • to unlock the SPI Flash.

 

 

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.
The real code need indirection for SPI command (if written in C#).

Code Block
languagec#
titlePseudocode, The real code need indirection for SPI command (if written in C#)
byte[] Command = new byte[64];
byte[] Reply = new byte[64];

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);

...

 

 
Command[2] = (byte) 3; //Number of SPI bytes as reply: mid

...

 

 = 0x20 did = 0x20 uid = 0x16
Command[3] = (byte) 0x9F; //(byte)SPI_Commands.CMD_SPI_RDID;

...

 

 // SPI_RDID 0x9F ≡ get ID command
Command[4] = (byte)0;

...

 


Command[5] = (byte)0;

...

 


Command[6] = (byte)0;

/*
TE_USB_FX2_SendCommand (Command[0] = (byte) FX2_Commands.CMD_FX2_FLASH_WRITE_COMMAND) calls "case CMD_FLASH_WRITE_COMMAND"

"case CMD_FLASH_WRITE_COMMAND" calls spi_command(EP1OUTBUF[1], &EP1OUTBUF[3], EP1OUTBUF[2], &EP1INBUF[1]) with EP1OUTBUF[3]= SPI_RDID SPI Flash Command

EP1OUTBUF = Command
Reply = EP1INBUF
*/

if (TE_USB_FX2_SendCommand(..., Command, CmdLength, Reply, ReplyLength, 5000) == true) 
{
	LogTextLine += "SPI Flash IDCODE " + "uid = 0x" + Reply[1].ToString("x") + "mid = 0x "+ Reply[2].ToString("x")+ " did = 0x" + Reply[3].ToString("x") + "\r\n";

...


}
Code Block
languagec#
titleC# real code; indirection for SPI commands

...

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

...

 indirection

...

 


Command2[0] = (byte)FX2_Commands.CMD_FX2_FLASH_WRITE_COMMAND;

...

 


Command2[1] = (byte)0x01; //

...

Numeber of SPI commands used by spi_command(): putcSPI(SPI_RDID

...

 

);                  
Command2[2] = (byte)0x03;

...

 

 //Number of SPI bytes as reply: mid = 0x20 did = 0x20 uid = 0x16
Command2[3] = (byte)0x9F

...

 

//To use the firmware function spi_command() you need to use a double indirection

 

; //(byte)SPI_Commands.CMD_SPI_RDID; // SPI_RDID 0x9F ≡ get ID command
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

...

_

...

SendCommand(

...

 

{

 

LogTextLine += "SPI Flash IDCODE 0x" + Reply1[1].ToString("x") + " 0x"

 

+ Reply1[2].ToString("x") + " 0x" + Reply1[3].ToString("x") + "\r\n";

 

}

 

else

 

{

 

...

..., Command1, CmdLength1, Reply1, ReplyLength1, 5000) == true) 
{
	LogTextLine += "SPI Flash IDCODE " + "uid = 0x" + Reply1[1].ToString("x") + "mid = 0x "

...

 

+ Reply1[2].ToString("x")+ " did = 0x" + Reply1[3].ToString("x") + "\r\n";

...

 


}

 

-------------------------------------------------

 

 

 

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 += "Doesn't work" + "\r\n" } As explained bellow the problems seems some unmatched settings. 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();) in spi_command () function and spi_command () has a setting in not equired (FPGA_POWER=0;) for SPI_RDID used in process_flash_id(). -----------------------------------

 

FX2_Commands.CMD_FX2_FLASH_WRITE_COMMAND call spi_command(), in spi_command 0x9F SPI command (CMD_SPI_RDID) is used

 

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

Code Block
languagecpp
titleLines 207-211 of te_api.c
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;

 

 

 

 

 

void spi_command(BYTE CmdLen, unsigned char *CmdData, BYTE RdLen, unsigned char *RdData)

 

aka

 


	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] =

...

 0x20; // for example
Reply[2] = EP1INBUF[2] =

...

 0x20; // for example
Reply[3] = EP1INBUF[3] =

...

 

-----------------------

 

// SPI Flash commands

#define SPI_READ 0x03

#define SPI_WREN 0x06

#define SPI_WRDI 0x04

#define SPI_RDSR1 0x05

#define SPI_RDSR2 0x35

#define SPI_WRSR 0x01

#define SPI_READ 0x03

#define SPI_FAST_READ 0x0b

#define SPI_WRITE 0x02

#define SPI_SE 0xD8

#define SPI_BE 0xC7

#define SPI_DP 0xb9

#define SPI_RES 0xab

#define SPI_RDID 0x9F

 

https://github.com/Trenz-Electronic/TE-USB-Suite/blob/master/TE_USB_FX2.firmware/te_usb_api.ver.3.2/te_api.c

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

https://github.com/Trenz-Electronic/TE-USB-Suite/blob/master/TE_USB_FX2.firmware/te_usb_api.ver.3.2/spi.c

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"; }

 

...

 0x16; // for example
*/
Scroll Title
titleFlash IDCODEs

Flash

Manufacturer ID

Memory Type

Capacity

M25P32

20h - Micron

20h

16h

W25Q64FV

EFh - Winbond

40h

17h

FW running on USB FX2 microcontroller

This is a piece of real code

spi.c, lines 63-89

Code Block
languagecpp
titleLines 63-89 of spi.c
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;
}