Objective:

To summarize the firmware and host utility that demonstrates fail-safe firmware update in FX3 from external EEPROM.

 

Flow-chart:

The sequence of steps involved in the boot-loading and firmware update is attached (FlowChart.pdf)

 

EEPROM Memory organization:

START ADDRESS

CONTENT

0x0000

Second Stage Boot-loader image

0x6000

Primary Firmware image

0x23000

Secondary Firmware image

0x3FFFF(Single Byte)

Firmware Update Byte (0x00 – Primary FW, 0xFF – Secondary FW)

 

Firmware:

  • Main application firmware is based on the USBBulkSourceSink example that comes with the FX3 SDK.
  • Second Stage boot-loader firmware is based on the Fx3BootAppGcc example that comes with the FX3 SDK.
  • The firmware source files and the IMGs are attached.
  • Release mode builds of firmware occupy lesser size than the debug builds and are hence preferred.

 

Key points to be noted in main application firmware:

 

1.    I2C block functionality is added and a DMA channel is created between CPU Producer socket and I2C Consumer socket. The firmware update is carried out over this DMA channel.

 

status = CyU3PI2cInit();

if(status == CY_U3P_SUCCESS)

{

CyU3PMemSet ((uint8_t *)&i2cConfig, 0, sizeof(i2cConfig));

i2cConfig.bitRate    = 100000;

i2cConfig.busTimeout = 0xFFFFFFFF;

i2cConfig.dmaTimeout = 0xFFFF;

i2cConfig.isDma      = CyTrue;

 

CyU3PI2cSetConfig (&i2cConfig, NULL);

}

apiRetStatus = CyU3PDmaChannelCreate (&glChHandleI2cTxHandle,

CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);

 

2.    Vendor command inclusions

 

a. 0xFF:

This command performs the actual firmware update over the DMA channel between CPU Producer and the I2C Consumer sockets.

 

case 0xFF:

CyU3PUsbAckSetup ();

i2cAddr = 0xA0 | ((wValue & 0x0007) << 1);

status  = CyU3PUsbGetEP0Data(wLength, glEp0Buffer, NULL);

if (status == CY_U3P_SUCCESS)

{

CyFxFlashProgI2cTransfer (wIndex, i2cAddr, wLength,

                                    glEp0Buffer, CyFalse);

}

break;

 

b. 0xFB:

This command reads the content of EEPROM at address 0x3FFFF to know the currently running firmware.

 

case 0xFB:

CyU3PMemSet ((uint8_t *)&i2cConfig, 0, sizeof(i2cConfig));

i2cConfig.bitRate    = 100000;

i2cConfig.busTimeout = 0xFFFFFFFF;

i2cConfig.dmaTimeout = 0xFFFF;

i2cConfig.isDma      = CyFalse;

CyU3PI2cSetConfig (&i2cConfig, NULL);

 

preamble.length    = 4;

preamble.buffer[0] = 0xA6;

preamble.buffer[1] = (0xFF);

preamble.buffer[2] = (0xFF);

preamble.buffer[3] = (0xA7);

preamble.ctrlMask  = 0x0004;

status = CyU3PI2cReceiveBytes(&preamble, buffer, 1, 0);

glEp0Buffer[0] = buffer[0];

if(buffer[0] == 0x00)

      FW_ID = 0x00AA00AA;// Any FW_ID can be used here

else if (buffer[0] == 0xFF)

      FW_ID = 0xFFBBFFBB;// Any FW_ID can be used here

glEp0Buffer[1] = (FW_ID & 0xFF);

glEp0Buffer[2] = ((FW_ID >> 8) & 0xFF);

glEp0Buffer[3] = ((FW_ID >> 16) & 0xFF);

glEp0Buffer[4] = ((FW_ID >> 24) & 0xFF);

 

CyU3PUsbSendEP0Data (5, glEp0Buffer);

 

CyU3PMemSet ((uint8_t *)&i2cConfig, 0, sizeof(i2cConfig));

i2cConfig.bitRate    = 100000;

i2cConfig.busTimeout = 0xFFFFFFFF;

i2cConfig.dmaTimeout = 0xFFFF;

i2cConfig.isDma      = CyTrue;

CyU3PI2cSetConfig (&i2cConfig, NULL);

break;

 

c. 0xFA:

This command toggles the content of EEPROM at address 0x3FFFF. This vendor command is to be called after the completion of the firmware update to update the EEPROM data at 0x3FFFF indicating the newest firmware.

 

case 0xFA:

CyU3PUsbAckSetup ();

preamble.length    = 4;

preamble.buffer[0] = 0xA6;

preamble.buffer[1] = (0xFF);

preamble.buffer[2] = (0xFF);

preamble.buffer[3] = (0xA7);

preamble.ctrlMask  = 0x0004;

CyU3PMemSet ((uint8_t *)&i2cConfig, 0, sizeof(i2cConfig));

i2cConfig.bitRate    = 100000;

i2cConfig.busTimeout = 0xFFFFFFFF;

i2cConfig.dmaTimeout = 0xFFFF;

i2cConfig.isDma      = CyFalse;

CyU3PI2cSetConfig (&i2cConfig, NULL);

status = CyU3PI2cReceiveBytes(&preamble, buffer, 1, 0);

if(buffer[0] == 0x00)

     buffer[0] = 0xFF;

else if(buffer[0] == 0xFF)

     buffer[0] = 0x00;

preamble.length    = 3;

preamble.buffer[0] = 0xA6;

preamble.buffer[1] = (0xFF);

preamble.buffer[2] = (0xFF);

preamble.ctrlMask  = 0x0000;

CyU3PI2cTransmitBytes(&preamble, buffer, 1, 0);

 

CyU3PMemSet ((uint8_t *)&i2cConfig, 0, sizeof(i2cConfig));

i2cConfig.bitRate    = 100000;

i2cConfig.busTimeout = 0xFFFFFFFF;

i2cConfig.dmaTimeout = 0xFFFF;

i2cConfig.isDma      = CyTrue;

CyU3PI2cSetConfig (&i2cConfig, NULL);

break;

 

NOTE: Vendor commands 0xFB and 0xFA use the I2C block in register mode and not in DMA mode. This is because the DMA channel was created only between CPU Producer and I2C Consumer. Since these vendor requests involve transactions of only a few bytes, it is sufficient to use the register mode access. However, the I2C block must be reconfigured to DMA mode after these I2C transactions are completed.

 

3.    Primary firmware and secondary firmware start addresses in the EEPROM are hard-coded as 0x6000 and 0x23000 respectively. Firmware IDs of 0x00AA00AA and 0xFFBBFFBB are defined based on the running firmware and can be obtained using the 0xFB vendor command. These IDs are just place holders and can always be replaced as there is no dependency on these IDs from the host application.

 

Key Points to be noted in second stage boot-loader firmware:

1.    I2C boot is enabled in the second stage boot-loader.

#define I2C_BOOT

2.    The FwUpdateCheck() function decides the start address of the main firmware to be loaded based on the FW update byte of the EEPROM (0x3FFFF).

          o    If this byte is 0x00, primary firmware image is loaded into the FX3 SRAM.

          o    If this byte is 0xFF, secondary firmware image is loaded into the FX3 SRAM.

 

Host Application:

There are two host applications (binary and the source) included with this memo.

1.    To generate the combined firmware image file with the inputs as the second stage boot-loader and the main firmware. This command line utility generates the combined firmware image with the second stage boot-loader image and two copies of the main firmware image. The procedure to use the utility is mentioned in the readme.txt file in the project folder.

NOTE: Refer to IMGCombine utility.

2.    To perform the firmware update over the vendor interface of FX3 by issuing appropriate vendor commands. The tool also displays the currently running firmware.

NOTE: Refer to Fx3FirmwareUpdate utility