Skip navigation
Home > All Places > USB > USB Superspeed Peripherals > Blog > Authors SrinathS_16

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

SrinathS_16

FX3 DMA Socket Suspend

Posted by SrinathS_16 Moderator Feb 2, 2019

Objective:

To understand the functionality of CyU3PDmaChannelSetSuspend() API of FX3 through firmware example implementation.

 

Related APIs:

CyU3PDmaChannelResume()

CyU3PDmaChannelGetBuffer()

CyU3PDmaChannelCommitBuffer()

 

API Usage:

The CyU3PDmaChannelSetSuspend() API can be used to suspend either the PRODUCER or the CONSUMER socket of a particular DMA channel. When a socket is suspended, further write (to a PRODUCER socket) or read (from the CONSUMER socket) cannot be performed until it is resumed. This API can be helpful when the data needs to be modified before being committed to the CONSUMER socket. In case of MANUAL channels, this API is not much helpful since the data has to be manually committed each time. But, in the case of AUTO channels, this API can be used to modify the data before being committing it to the CONSUMER.

 

API Prototype:

CyU3PReturnStatus_t

CyU3PDmaChannelSetSuspend (

        CyU3PDmaChannel *handle,                /**< Handle to the channel to be modified. */

        CyU3PDmaSckSuspType_t prodSusp,         /**< Suspend option for the producer socket. */

        CyU3PDmaSckSuspType_t consSusp          /**< Suspend option for the consumer socket. */

        );

 

API functionality:

- The CyU3PDmaChannel identifies the DMA channel of which the socket is to be suspended.

- The CyU3PDmaSckSuspType_t determines the nature in which the socket is suspended. The different options available are:

     1. CY_U3P_DMA_SCK_SUSP_NONE               -     Socket will not be suspended and will be in normal mode of operation.

     2. CY_U3P_DMA_SCK_SUSP_EOP                -     Socket will be suspended whenever the EOP bit in the buffer is set.

     3. CY_U3P_DMA_SCK_SUSP_CUR_BUF            -     Socket will be suspended after the current buffer is processed.

     4. CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF   -     Socket will be suspended whenever there is a short packet from the PRODUCER socket.

 

Firmware Implementation:

The USBBulkSourceSink firmware and the GpifToUsb firmware that comes with the FX3 SDK have been modified with additional vendor commands to implement the socket suspend on DMA channel. Also, in the GpifToUsb firmware, the GPIF II state machine has been modified to include the COMMIT action. This generates an EOP condition on the buffer.

Vendor request handling is as follows. 0xFA implements a consumer socket suspend when there is an EOP condition, 0xFB implements a consumer socket suspend after the current buffer is completed and 0xFC implements a consumer socket suspend when there is a partial buffer, 0xFD gets the buffer and fills it with a known set of bytes (0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF in the attached examples), commits the buffer to the consumer and then resumes the consumer socket.

 

NOTE 1: When the socket suspend option is set to CY_U3P_DMA_SCK_SUSP_EOP, the socket will be suspended after handling any buffer with the EOP bit set. Typically the EOP bit will be set on any data buffers that are wrapped up on the PIB (GPIF) side through a COMMIT action. The DMA buffer with the EOP bit set would have been handled before the socket gets suspended, meaning that it is not possible to make changes to the contents of that data packet.

 

NOTE 2: When using the mentioned vendor commands, set the wLength field ('Bytes to Transfer' box in Control Center) to 0.

 

Case 1: CY_U3P_DMA_SCK_SUSP_EOP

Test Procedure:
- Program the GpifToUsb firmware into the FX3 using the Cypress USB Control Center.

- Use Cypress USB Control Center to read data from the 0x81 BULK IN endpoint. Since the state machine has been modified, 24 bytes of data will be received on the Control Center window for each IN transfer.

- From the Cypress USB Control Center, issue the 0xFA vendor command. This sets up the DMA channel consumer to be suspended after handling a buffer with EOP bit set.

- Perform the next BULK IN transfer on the 0x81 endpoint. This transfer will be successful (Refer NOTE 1).

- On the next BULK IN transaction from 0x81 endpoint, there will be an error on the Control Center. This indicates that the socket is now suspended.

- From the Cypress USB Control Center, issue the 0xFD vendor command. The buffer is obtained, filled with known bytes of data and committed to the consumer. The socket suspend is removed and the channel is resumed.

- Perform an IN data transfer from the Cypress USB Control Center. The known bytes of data that was manually committed will be seen on the display window.

- On subsequent reads from the 0x81 BULK IN endpoint, 24 bytes of data will be received continuously.

 

Case 2: CY_U3P_DMA_SCK_SUSP_CUR_BUF:

Test Procedure:

- Program the USBBulkLoopAutoEnum firmware into the FX3 using the Cypress USB Control Center.

- Use the Bulkloop application from the FX3 SDK to perform OUT and IN transactions with the corresponding endpoints. The application shows 'Successes' on the transactions.

- From the Cypress USB Control Center, issue the 0xFB vendor command. This suspends the consumer socket after the current buffer is processed. The suspension of the socket will be evident from the Bulkloop application which now starts showing 'Failures'. Stop the transactions on the Bulkloop application.

- From the Cypress USB Control Center, issue the 0xFD vendor command. The buffer is obtained, filled with known bytes of data and committed to the consumer. The socket suspend is removed and the channel is resumed.

- Perform an IN data transfer from the Cypress USB Control Center. The known bytes of data that was manually committed will be seen on the display window.

- Bulkloop application can again be started which now shows 'Successes' indicating resumption of the channel socket.

 

Case 3: CY_U3P_DMA_SCK_SUSP_CONS_PARTIAL_BUF

Test Procedure:

- Program the USBBulkLoopAutoEnum firmware into the FX3 using the Cypress USB Control Center.

- Use the Bulkloop application from the FX3 SDK to perform OUT and IN transactions with the corresponding endpoints. The application shows 'Successes' on the transactions.

- From the Cypress USB Control Center, issue the 0xFB vendor command. This sets up the consumer socket to be suspended after it receives a short packet. The Bulkloop application continues to show 'Successes' indicating that the socket is not yet suspended.

- From the Cypress USB Control Center, send a smaller number of bytes of data (say 10 bytes) over the BULK OUT endpoint. This generates a partial buffer from the PRODUCER socket which in turn generates a suspend condition on the consumer socket. The suspension of the socket will be evident from the Bulkloop application which now starts showing 'Failures'. Stop the transfers on the Bulkloop application.

- From the Cypress USB Control Center, issue the 0xFD vendor command. The buffer is obtained, filled with known bytes of data and committed to the consumer. The socket suspend is removed and the channel is resumed.

- Perform an IN data transfer from the Cypress USB Control Center. The known bytes of data that was manually committed will be seen on the display window.

- Bulkloop application can again be started which now shows 'Successes' indicating resumption of the channel socket.