Other Parts Discussed in Thread: UNIFLASH, CC2640
Hi, I am trying to flash an image to a 2640 device over UART using the bootloader. We are able to establish a connection to the bootloader and send commands successfully. However, we have not been unable to flash an image successfully. The process always fails on the CMD_GET_STATUS packet after a successful COMMAND_SEND_DATA is sent. The packet returns with an ACK, but the received status is a failure with the status code COMMAND_RET_FLASH_FAIL. If I send only 1 byte of data in the COMMAND_SEND_DATA packet, we are able to send a few packets successfully. However, the process will always fail around the 8th byte in the image. I am sending a 2640 .bin image which was built using Code Composer Studio and the hex2bin script. I have validated the image using Uniflash, by flashing the image onto the device without issue. Is there a step that I am missing?
Below is the code we are using. This code is for a cc3220 we are using to communicate with the cc2640. I have already validated that the packets are sent correctly. The entrypoint is the OTA2640() function:
#include <Board.h> #include <device-control/device-control.h> #include <errors/errors.h> #include <file-system/file-system.h> #include <logger/logger.h> #include <stdio.h> #include <ti/devices/cc32xx/inc/hw_types.h> #include <ti/drivers/GPIO.h> #include <ti/drivers/net/wifi/device.h> #include <uart/uart.h> #include <unistd.h> #include <ti/devices/cc32xx/driverlib/prcm.h> void start2640Bootloader() { Stop2640(); GPIO_write(1, 1); usleep(100000); Start2640(); usleep(100000); } typedef struct bootloaderPacket bootloaderPacket; struct bootloaderPacket { uint8_t size; uint8_t checksum; uint8_t data[253]; }; void setChecksum(bootloaderPacket *blPacket) { blPacket->checksum = 0; uint8_t i = 0; for (i = 0; i < blPacket->size - 2; i++) { blPacket->checksum += blPacket->data[i]; } } bootloaderPacket createBootloaderPacket(uint8_t command, void *data, uint8_t dataSize) { bootloaderPacket blPacket; blPacket.data[0] = command; memcpy(&blPacket.data[1], data, dataSize); blPacket.size = dataSize + 3; setChecksum(&blPacket); return blPacket; } error *SendBootloaderPacket(UARTHandle uartHandle, bootloaderPacket *blPacket) { int8_t retVal = UART_write(uartHandle, blPacket, blPacket->size); if (retVal < 0) { return NewError("Unable to send bootloader packet"); } usleep(10000); return NULL; } #define BootloaderACK 0xCC #define BootloaderNACK 0x33 error *sendAck(UARTHandle uartHandle) { uint8_t ackPacket[] = {BootloaderACK}; int8_t retVal = UART_write(uartHandle, ackPacket, sizeof(ackPacket)); if (retVal < 0) { return NewError("Unable to send ack"); } return NULL; } bool readResponseIsAck(UARTHandle uartHandle) { uint8_t uartReadData; do { UART_read(uartHandle, &uartReadData, 1); } while (uartReadData == 0); if (uartReadData != BootloaderACK) { LogInteger("Did not get an ACK: %d\n", uartReadData); return false; } return true; } bool readResponseIsNack(UARTHandle uartHandle) { return !readResponseIsAck(uartHandle); } bootloaderPacket readBootloaderPacket(UARTHandle uartHandle) { bootloaderPacket blPacket; do { UART_read(uartHandle, &blPacket.size, 1); } while (blPacket.size == 0); UART_read(uartHandle, &blPacket.checksum, 1); UART_read(uartHandle, blPacket.data, blPacket.size - 2); return blPacket; } bool readResponseStatusIsSuccess(UARTHandle uartHandle) { bootloaderPacket blPacket = readBootloaderPacket(uartHandle); switch (blPacket.data[0]) { case COMMAND_RET_SUCCESS: Log("Status response: success\n"); return true; case COMMAND_RET_UNKNOWN_CMD: Log("Status response: unknown command\n"); return false; case COMMAND_RET_INVALID_CMD: Log("Status response: invalid command\n"); return false; case COMMAND_RET_INVALID_ADR: Log("Status response: invalid address\n"); return false; case COMMAND_RET_FLASH_FAIL: Log("Status response: flash fail\n"); return false; default: LogInteger("Status response: unexpected value: %d\n", blPacket.data[0]); return false; } } uint8_t autobaudBytes[] = {0x55, 0x55}; error *setBootloaderBaud(UARTHandle uartHandle) { UART_write(uartHandle, autobaudBytes, sizeof(autobaudBytes)); if (readResponseIsNack(uartHandle)) { NewError("setBootloaderBaud response was a NACK"); } return NULL; } bootloaderPacket createPingPacket() { return createBootloaderPacket(BL_PING, NULL, 0); } error *ping2640Bootloader(UARTHandle uartHandle) { bootloaderPacket pingPacket = createPingPacket(); SendBootloaderPacket(uartHandle, &pingPacket); if (readResponseIsNack(uartHandle)) { return NewError("ping2640Bootloader response was a NACK"); } Log("Ping success\n"); return NULL; } bootloaderPacket createGetStatusPacket() { return createBootloaderPacket(BL_GET_STATUS, NULL, 0); } error *get2640BootloaderStatus(UARTHandle uartHandle) { bootloaderPacket getStatusPacket = createGetStatusPacket(); SendBootloaderPacket(uartHandle, &getStatusPacket); if (readResponseIsNack(uartHandle)) { return NewError("get2640BootloaderStatus response was a NACK"); } Log("Get Bootloader Status Success!!\n"); if (!readResponseStatusIsSuccess(uartHandle)) { return NewError("Get bootloader status did not return a success\n"); } sendAck(uartHandle); return NULL; } bootloaderPacket createEraseFlashPacket(uint32_t startAddress, uint32_t dataSize) { uint8_t data[8]; data[0] = (startAddress >> 24) & 0xFF; data[1] = (startAddress >> 16) & 0xFF; data[2] = (startAddress >> 8) & 0xFF; data[3] = (startAddress)&0xFF; data[4] = (dataSize >> 24) & 0xFF; data[5] = (dataSize >> 16) & 0xFF; data[6] = (dataSize >> 8) & 0xFF; data[7] = (dataSize)&0xFF; return createBootloaderPacket(BL_DOWNLOAD, &data, sizeof(data)); } error *erase2640BootloaderFlash(UARTHandle uartHandle) { bootloaderPacket eraseFlashPacket = createEraseFlashPacket(0x0000, 0x20000); SendBootloaderPacket(uartHandle, &eraseFlashPacket); if (readResponseIsNack(uartHandle)) { return NewError("erase2640BootloaderFlash response was a NACK!!!!!"); } Log("erase2640BootloaderFlash Success!\n"); return NULL; } bootloaderPacket createDownloadStartPacket(uint32_t startAddress, uint32_t dataSize) { uint8_t downloadCmd[8]; downloadCmd[0] = (startAddress >> 24) & 0xFF; downloadCmd[1] = (startAddress >> 16) & 0xFF; downloadCmd[2] = (startAddress >> 8) & 0xFF; downloadCmd[3] = (startAddress)&0xFF; downloadCmd[4] = (dataSize >> 24) & 0xFF; downloadCmd[5] = (dataSize >> 16) & 0xFF; downloadCmd[6] = (dataSize >> 8) & 0xFF; downloadCmd[7] = (dataSize)&0xFF; return createBootloaderPacket(BL_DOWNLOAD, &downloadCmd, sizeof(downloadCmd)); } error *start2640BootloaderDownload(UARTHandle uartHandle, uint32_t dataSize) { bootloaderPacket startDownloadPacket = createDownloadStartPacket(0x0000, dataSize); SendBootloaderPacket(uartHandle, &startDownloadPacket); if (readResponseIsNack(uartHandle)) { return NewError("start2640BootloaderDownload response was a NACK!!!!!"); } Log("start2640BootloaderDownload Success!\n"); return NULL; } bootloaderPacket createSendDataPacket(void *data, uint32_t dataSize) { return createBootloaderPacket(BL_SEND_DATA, data, dataSize); } error *send2640BootloaderData(UARTHandle uartHandle, void *data, uint32_t dataSize) { bootloaderPacket sendDataPacket = createSendDataPacket(data, dataSize); SendBootloaderPacket(uartHandle, &sendDataPacket); if (readResponseIsNack(uartHandle)) { return NewError("send2640BootloaderData response was a NACK!!!!!"); } Log("send2640BootloaderData Success!\n"); return NULL; } error *OTA2640() { UARTHandle uartHandle = createUARTHandle(Board_UART0); start2640Bootloader(); error *err = setBootloaderBaud(uartHandle); if (err != NULL) { return err; } err = ping2640Bootloader(uartHandle); if (err != NULL) { return err; } err = erase2640BootloaderFlash(uartHandle); if (err != NULL) { return err; } err = get2640BootloaderStatus(uartHandle); if (err != NULL) { return err; } GetFileInfoResponse fileInfoResponse = getFileInfo("cc2640.bin"); if (fileInfoResponse.err != NULL) { return fileInfoResponse.err; } err = start2640BootloaderDownload(uartHandle, fileInfoResponse.fileInfo.Len); if (err != NULL) { return err; } err = get2640BootloaderStatus(uartHandle); if (err != NULL) { return err; } OpenFileResponse openFileResonse = openReadFile("cc2640.bin"); if (openFileResonse.err != NULL) { return openFileResonse.err; } uint8_t dataBytes[252]; uint32_t fileOffset = 0; while (fileOffset < fileInfoResponse.fileInfo.Len) { ReadFileResponse readFileResponse = readFile(openFileResonse.fileHandle, dataBytes, sizeof(dataBytes), fileOffset); if (readFileResponse.err != NULL) { return readFileResponse.err; } fileOffset += readFileResponse.bytesRead; err = send2640BootloaderData(uartHandle, dataBytes, readFileResponse.bytesRead); if (err != NULL) { return err; } err = get2640BootloaderStatus(uartHandle); if (err != NULL) { return err; } } return NULL; }