CC2340R5: 蓝牙固件通过uart串口烧录时失败

Part Number: CC2340R5
Other Parts Discussed in Thread: UNIFLASH, SYSCONFIG

Tool/software:

When upgrading the CC2340R5 Bluetooth firmware via the serial port, the process fails during the CRC verification step, even though the flash erase and write operations were successful earlier. How should this issue be addressed?

  • Hi mike,

    When using the TI_CC2340_Linux_SBL tool you have to make sure that you create a custom bin file and ensure that the firmware binary file is aligned with the sector size (0x800).  The "Byte Count" of your image (0x64db4) implies that these instructions were not adhered to.

    Regards,
    Ryan

  • Could you please let me know the standard bin binary file format for the CC2340R5RGE Bluetooth firmware, or how to generate it through the memory option in the Uniflash tool? Alternatively, could you send me a copy directly? Thank you!

  • Hi, TI Engineer,

    I have sent you my host computer and CC2340R5RGE Bluetooth firmware code. Could you please help take a look? Our upgrades have been unsuccessful. The specific code is included in the attachment. Thank you!

    /*蓝牙固件地址cmd地址配置文件*/
    /******************************************************************************
    
     @file  cc23x0_app_freertos.cmd
    
     @brief cc23x0R5 linker configuration file for FreeRTOS
            with Code Composer Studio.
    
            Imported Symbols
            Note: Linker defines are located in the CCS IDE project by placing them
            in
            Properties->Build->Linker->Advanced Options->Command File Preprocessing.
    
            ICALL_RAM0_START:   RAM start of BLE stack.
            ICALL_STACK0_START: Flash start of BLE stack.
            PAGE_AlIGN:         Align BLE stack boundary to a page boundary.
                                Aligns to Flash word boundary by default.
    
     Group: WCS, BTS
     $Target Device: DEVICES $
    
     ******************************************************************************
     $License: BSD3 2017 $
     ******************************************************************************
     $Release Name: PACKAGE NAME $
     $Release Date: PACKAGE RELEASE DATE $
     *****************************************************************************/
    
    /*******************************************************************************
     * CCS Linker configuration
     */
    
    /* Override default entry point.                                             */
    --entry_point=resetISR
    
    /* Retain interrupt vector table variable                                    */
    --retain "*(.resetVecs)"
    
    /* Suppress warnings and errors:                                             */
    /* - 10063: Warning about entry point not being _c_int00                     */
    /* - 16011, 16012: 8-byte alignment errors. Observed when linking in object  */
    /*   files compiled using Keil (ARM compiler)                                */
    --diag_suppress=10063,16011,16012
    --heap_size=0
    --stack_size=800
    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M3_T_le_eabi.lib                                           */
    
    /* The starting address of the application.  Normally the interrupt vectors  */
    /* must be located at the beginning of the application. Flash is 128KB, with */
    /* sector length of 4KB                                                      */
    /*******************************************************************************
     * Memory Sizes
     */
    #define FLASH_BASE   0x00000000
    #define RAM_BASE     0x20000000
    #define FLASH_SIZE   0x00080000
    #define RAM_SIZE     0x00009000
    #define CCFG_BASE    0x4E020000
    #define CCFG_SIZE    0x800
    #define NVS_SIZE     0x4000
    #define NVS_BASE     (FLASH_SIZE - NVS_SIZE)
    
    #if defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT) || defined(OAD_DUAL_IMAGE)
    #define MCU_HDR_SIZE    0x100
    #define MCUBOOT_BASE    FLASH_BASE
    #define MCUBOOT_SIZE    0x6000
    #define APP_HDR_BASE    APP_HDR_ADDR
    #define APP_BASE        (APP_HDR_BASE + MCU_HDR_SIZE)
    #endif //defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT) || defined(OAD_DUAL_IMAGE)
    
    #if defined(OAD_APP_ONCHIP)|| defined(OAD_PERSISTENT)
    #define PERSISTENT_HDR_BASE 0x6000
    #define PERSISTENT_BASE     (PERSISTENT_HDR_BASE + MCU_HDR_SIZE)
    #define PERSISTENT_SIZE     (APP_HDR_BASE - PERSISTENT_BASE)
    #define APP_SIZE            (FLASH_SIZE - APP_BASE - NVS_SIZE)
    #endif //defined(OAD_APP_ONCHIP)|| defined(OAD_PERSISTENT)
    
    #ifdef OAD_APP_OFFCHIP
    #define APP_SIZE        (FLASH_SIZE - APP_BASE - NVS_SIZE)
    #endif //OAD_APP_OFFCHIP
    
    #ifdef OAD_DUAL_IMAGE
    #define APP_SIZE        ((FLASH_SIZE - NVS_SIZE - MCUBOOT_SIZE)/2 - MCU_HDR_SIZE)
    #endif //OAD_DUAL_IMAGE
    
    /*******************************************************************************
     * Memory Definitions
     ******************************************************************************/
    
    /*******************************************************************************
     * RAM
     */
    #define RAM_START      (RAM_BASE)
    #ifdef ICALL_RAM0_START
      #define RAM_END      (ICALL_RAM0_START - 1)
    #else
      #define RAM_END      (RAM_BASE + RAM_SIZE - 1)
    #endif /* ICALL_RAM0_START */
    
    /*******************************************************************************
     * Flash
     */
    
    #define FLASH_START                FLASH_BASE
    #define WORD_SIZE                  4
    
    #define PAGE_SIZE                  0x800
    
    #ifdef PAGE_ALIGN
      #define FLASH_MEM_ALIGN          PAGE_SIZE
    #else
      #define FLASH_MEM_ALIGN          WORD_SIZE
    #endif /* PAGE_ALIGN */
    
    #define PAGE_MASK                  0xFFFFE000
    
    /* The last Flash page is reserved for the application. */
    #define NUM_RESERVED_FLASH_PAGES   1
    #define RESERVED_FLASH_SIZE        (NUM_RESERVED_FLASH_PAGES * PAGE_SIZE)
    
    /* Check if page alingment with the Stack image is required.  If so, do not link
     * into a page shared by the Stack.
     */
    #ifdef ICALL_STACK0_START
      #ifdef PAGE_ALIGN
        #define ADJ_ICALL_STACK0_START (ICALL_STACK0_START * PAGE_MASK)
      #else
        #define ADJ_ICALL_STACK0_START ICALL_STACK0_START
      #endif /* PAGE_ALIGN */
    
      #define FLASH_END                (ADJ_ICALL_STACK0_START - 1)
    #else
      #define FLASH_END                (FLASH_BASE + FLASH_SIZE - RESERVED_FLASH_SIZE - 1)
    #endif /* ICALL_STACK0_START */
    
    #define FLASH_LAST_PAGE_START      (FLASH_SIZE - PAGE_SIZE)
    
    /*******************************************************************************
     * Stack
     */
    
    /* Create global constant that points to top of stack */
    /* CCS: Change stack size under Project Properties    */
    __STACK_TOP = __stack + __STACK_SIZE;
    
    /*******************************************************************************
     * ROV
     * These symbols are used by ROV2 to extend the valid memory regions on device.
     * Without these defines, ROV will encounter a Java exception when using an
     * autosized heap. This is a posted workaround for a known limitation of
     * RTSC/rta. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=487894
     *
     * Note: these do not affect placement in RAM or FLASH, they are only used
     * by ROV2, see the BLE Stack User's Guide for more info on a workaround
     * for ROV Classic
     *
     */
    __UNUSED_SRAM_start__ = RAM_BASE;
    __UNUSED_SRAM_end__ = RAM_BASE + RAM_SIZE;
    
    __UNUSED_FLASH_start__ = FLASH_BASE;
    __UNUSED_FLASH_end__ = FLASH_BASE + FLASH_SIZE;
    
    /*******************************************************************************
     * Main arguments
     */
    
    /* Allow main() to take args */
    /* --args 0x8 */
    
    /*******************************************************************************
     * System Memory Map
     ******************************************************************************/
    MEMORY
    {
      /* EDITOR'S NOTE:
       * the FLASH and SRAM lengths can be changed by defining
       * ICALL_STACK0_START or ICALL_RAM0_START in
       * Properties->ARM Linker->Advanced Options->Command File Preprocessing.
       */
    
    #if defined(OAD_APP_OFFCHIP)|| defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT) || defined(OAD_DUAL_IMAGE)
    
        MCUBOOT_SLOT(RX)       : origin = MCUBOOT_BASE        ,length = MCUBOOT_SIZE
        APP_HDR_SLOT(RX)       : origin = APP_HDR_BASE        ,length = MCU_HDR_SIZE
        APP_SLOT (RX)          : origin = APP_BASE            ,length = APP_SIZE
    
    #if defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT)
    
        PERSISTENT_HDR_SLOT(RX) : origin = PERSISTENT_HDR_BASE ,length = MCU_HDR_SIZE
        PERSISTENT_SLOT(RX)     : origin = PERSISTENT_BASE     ,length = PERSISTENT_SIZE
    
    #endif //defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT)
    
    #else //Without mcuboot
    
        FLASH (RX)   : origin = 0x0,      length = (FLASH_SIZE - NVS_SIZE)
    
    #endif //defined(OAD_APP_OFFCHIP)|| defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT)
    
      NVS_SLOT(RX) : origin = NVS_BASE ,length = NVS_SIZE
      /* Application uses internal RAM for data */
      SRAM (RWX) : origin = RAM_START, length = (RAM_END - RAM_START + 1)
    
      CCFG (RW) : origin = CCFG_BASE, length = CCFG_SIZE
    }
    
    /*******************************************************************************
     * Section Allocation in Memory
     ******************************************************************************/
    SECTIONS
    {
    #if defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT) || defined(OAD_DUAL_IMAGE)
    
    	.primary_hdr    :   > APP_HDR_SLOT, type = NOLOAD
    
    #if defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_DUAL_IMAGE)
    
        .resetVecs      :   > APP_BASE
        .text           :   > APP_SLOT
        .const          :   > APP_SLOT
        .constdata      :   > APP_SLOT
        .rodata         :   > APP_SLOT
        .binit          :   > APP_SLOT
        .cinit          :   > APP_SLOT
        .pinit          :   > APP_SLOT
        .init_array     :   > APP_SLOT
        .emb_text       :   > APP_SLOT
    
    #else
    
        .resetVecs      :   > PERSISTENT_BASE
        .text           :   > PERSISTENT_SLOT
        .const          :   > PERSISTENT_SLOT
        .constdata      :   > PERSISTENT_SLOT
        .rodata         :   > PERSISTENT_SLOT
        .binit          :   > PERSISTENT_SLOT
        .cinit          :   > PERSISTENT_SLOT
        .pinit          :   > PERSISTENT_SLOT
        .init_array     :   > PERSISTENT_SLOT
        .emb_text       :   > PERSISTENT_SLOT
    
    #endif //defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_DUAL_IMAGE)
    
    #else
      .resetVecs      :   >  FLASH_START
      .text           :   >> FLASH
      .const          :   >> FLASH
      .constdata      :   >> FLASH
      .rodata         :   >> FLASH
      .cinit          :   >  FLASH
      .pinit          :   >> FLASH
      .init_array     :   >  FLASH
      .emb_text       :   >> FLASH
    
    
    #endif //defined(OAD_APP_OFFCHIP) || defined(OAD_APP_ONCHIP) || defined(OAD_PERSISTENT) || defined(OAD_DUAL_IMAGE)
    
      .ccfg           :   > CCFG
      .ramVecs        :   > SRAM, type = NOLOAD, ALIGN(256)
      .data           :   > SRAM
      .bss            :   > SRAM
      .sysmem         :   > SRAM
      .nonretenvar    :   > SRAM
      .heap           :   > SRAM
      .stack          :   > SRAM (HIGH)
    
    }
    

    /*
     * Copyright (c) 2021-2023, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */ 
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <time.h>
    #include <string.h>
    
    /* Custom Includes */
    #include "Linux_Serial.h"
    #include "sbl_device.h"
    #include "sbl_device_cc2340.h"
    #include "myFile.h"
    
    /* read only variables */
    const char *portName = NULL;
    const char *filename = NULL; /*Path of .bin to be flashed*/
    const char *ccfgFilename= NULL;
    const char *command= NULL;
    static FILE *fPtr = NULL;  
    static FILE *CCFGfPtr= NULL; 
    
    /* CMD line cases */
    enum cmdArgs{
        ONE = 1,
        TWO = 2,
        THREE = 3,
        FOUR =4,
    };
    
    
    int main(int argc, char **argv)
    {
        printf("\n+-----------------------------------\n");
        printf("Serial Bootloader Library for CC2340\n");
        printf("Platform: Linux                     \n");
        printf("Compiler: GCC                       \n");
        printf("ARG0 = %s\n",argv[0]);
        printf("ARG1 = %s\n",argv[1]);
        printf("ARG2 = %s\n",argv[2]);
        printf("ARG3 = %s\n",argv[3]);
        printf("+-----------------------------------\n");
    
        /* Do some initial command line checks */
        switch(argc)
        {
        case FOUR:
            portName = argv[1];
            filename = argv[2];
            ccfgFilename=argv[3];
            printf("SBL Port i/p: %s\r\n", portName);
            printf("Firmware i/p: %s\r\n\n", filename);
            printf("CCFG Filename i/p: %s\r\n\n", ccfgFilename);
            printf("All Good :)\r\n");
            break;
        case TWO:
            if (strcmp(argv[1],"-help")==0){
    			printf("CC2340 -Linux Bootloader- HELP Overview\n");
    			printf("The function SBL.out take a total number of 3 Arguments:\n");
    			printf("To call the function use: \n");
    			printf("SBL.out [Serial Port] [Firmware] [CCFG]\r\n");
    			printf("[Serial Port]...name of serial port connected to CC2340\r\n");
    			printf("[Firmware]......Path of Firmware binary file\r\n");
    			printf("[CCFG]..........Path of CCFG binary file\r\n");
    			printf("+-----------------------------------\n");
    			exit(EXIT_SUCCESS);
    			break;}
        default:
            printf("INVALID ARG'S...EXISTING :(\r\n");
            printf("Valid format of running the SBL is:\r\n");
            printf("SBL.out [Serial Port] [Firmware Image path] [CCFG filepath]\r\n");
            printf("Type: SBL.out -help to get more information\r\n");
            printf("+-----------------------------------\n");
            exit(EXIT_FAILURE);
            break;
        }
    
        /*Start Bootloader 
        Initialize system*/
        printf("\n+-----------------------------------\n");
        uint8_t *memPtr = NULL;                 /* Ptr to hold read data */
        uint8_t *ccfgmemPtr = NULL;                 /* Ptr to hold read data */
        long fileSz = 0;                        /* Holds the size of the .bin file, in bytes */
        uint32_t fileCrc,ccfgCrc;       /* Variables to save CRC checksum */
        uint32_t tmp = 0;
        bool ackChk = false;
    
        uint32_t devCcfgBase=SBL_CC2340_CCFG_START_ADDRESS;      /*CFG start addrass only used for CC2340*/ 
        uint32_t byteCount=2048;       /*file size in bytes*/
        uint32_t ccfgByteCount=0;   /*file size in bytes for CC2340 CCFG*/
        uint32_t devFlashBase;   /*device Flash base*/
        printf("DevCcfgBase: 0x%x\r\n", devCcfgBase);
        printf("DevFlashBase: 0x%x\r\n", devFlashBase);
        uint32_t u32tRuntime_start,u32tRuntime_stop;
        u32tRuntime_start=time(NULL);
        
        printf("\n+-----------------------------------\n");
        /* Open the port */
        openPort(portName);
    
        /* Configure port */
        configPort();
        printf("+-----------------------------------\n");
    
        /* Setup callbacks */
        setupCallbacks();
    
        /* Set flash base for cc2340 */
        setDeviceFlashBase(CC23XX_FLASH_BASE);
    
        /* Detect baud rate */
        if(detectAutoBaud() != SBL_SUCCESS)
        {
            printf("ERROR: baud detect  failed\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
            printf("Baudrate detected !\n");
    
        /* Check if the host is reachable */
        if(ping() != SBL_SUCCESS)
        {
            printf("ERROR: Host unreachable\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
            printf("PING: Host detected !\n");
    
        if(readFlashSize(&tmp) != SBL_SUCCESS)
        {
            printf("ERROR: Unable to read flash size\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
            printf("Flash size: %u\n",getFlashSize());
    
        if(readRamSize(&tmp) != SBL_SUCCESS)
        {
            printf("ERROR: Unable to read RAM size\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
            printf("RAM size: %u\n",getRamSize());
    
        /* Open the file */
        if((fPtr = openFile(filename)) == NULL)
        {
            printf("ERROR: opening file\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("FILE open OK\n");
            if(!(fileSz = getFileSize(fPtr)))
            {
                printf("ERROR: getting file size\n");
                closePort();
                closeFile(fPtr);
                exit(EXIT_FAILURE);
            }
            else
            {
                printf("FILE size OK,\nFile Size: %lu Byte\n",fileSz);
    
                /* Allocate memory to read the file */
                memPtr = (uint8_t*)calloc(fileSz, sizeof(uint8_t));
                if(memPtr)
                {
                    uint32_t fileRd = 0;
    
                    printf(" CALLOC OK\n");
                    if((fileRd = fread(memPtr,1 , fileSz, fPtr)) != fileSz)
                    {
                        printf("ERROR: File read failed\n");
                        free(memPtr);
                        closePort();
                        closeFile(fPtr);
                        exit(EXIT_FAILURE);
                    }
                    else
                        printf("FILE read OK,\n file Read: %u Bytes\n", fileRd);
                }
                else
                {
                    printf("ERROR: calloc failed\n");
                    closePort();
                    closeFile(fPtr);
                    exit(EXIT_FAILURE);
                }
            }
        }/*End of all file operations*/ 
    printf("+-----------------------------------\n");
    /* Calculate file CRC checksum */
    fileCrc = calcCrcLikeChip(memPtr, fileSz);
    
    /*CCFG File Regions:
    ccfg.bootCfg.crc32          0x0000-0x000B
    ccfg.crc32                  0x0010-0x074B
    ccfg.userRecord.crc32       0x0750-0x07FB*/
       
    uint8_t Crc32Value[4];
    uint16_t CcfgRegionStart[4] =   {0x0000, 0x0010,0x075,0x07D0};
    uint16_t CcfgRegionEnd[4]=      {0x00B, 0x074, 0x0CB, 0x07FB};
    uint16_t regionStartAddr;
    uint16_t regionEndAddr;
    uint8_t addrIndex;
    
    if((CCFGfPtr = openFile(ccfgFilename)) == NULL)
        {
            printf("ERROR: opening file\n");
            closePort();
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("FILE open OK\n");
            printf("+-----------------------------------\n");
            printf("Start Updating CCFG....\n");
    
            /*Update CRC32 for 4 regions in CCFG*/
            for(addrIndex=0;addrIndex<4;addrIndex++){
                regionStartAddr=CcfgRegionStart[addrIndex];
                regionEndAddr=CcfgRegionEnd[addrIndex];
    
                /*set Read pointer to the beginning*/
                fseek(CCFGfPtr,regionStartAddr,SEEK_SET);
    
                /*read datra from region start to region end*/
                ccfgByteCount=regionEndAddr-regionStartAddr+1;
            
                /* Allocate memory to read the file */
                ccfgmemPtr = (uint8_t*)calloc(ccfgByteCount, sizeof(uint8_t));
                printf("memory allocated");
                if(ccfgmemPtr)
                {
                    uint32_t fileRd = 0;
                    printf("CALLOC OK\n");
                    if((fileRd = fread(ccfgmemPtr,1 , ccfgByteCount, CCFGfPtr)) != ccfgByteCount)
                    {
                        printf("ERROR: File read failed\n");
                        free(ccfgmemPtr);
                        closePort();
                        closeFile(CCFGfPtr);
                        exit(EXIT_FAILURE);
                    }
                    else
                        printf("FILE read OK, fileRd: %u \n", fileRd);
                }
                else
                {
                    printf("ERROR: calloc failed\n");
                    closePort();
                    closeFile(CCFGfPtr);
                    exit(EXIT_FAILURE);
                }
                /*calculate CRC checksum*/
                uint32_t ccfgfileCrc=calcCrcLikeChip(ccfgmemPtr,ccfgByteCount);
                printf("CRC32 for 0x%x to 0x%x is %x\n",regionStartAddr,regionEndAddr,ccfgfileCrc);
                Crc32Value[0] = (uint8_t)   (ccfgfileCrc&0x000000FF);
                Crc32Value[1] = (uint8_t)   ((ccfgfileCrc&0x0000FF00)>>8);
                Crc32Value[2] = (uint8_t)   ((ccfgfileCrc&0x00FF0000)>>16);
                Crc32Value[3] = (uint8_t)   ((ccfgfileCrc&0xFF000000)>>24);
    
                printf("CRC32Value= [0x%x,0x%x,0x%x,0x%x]\n",Crc32Value[0],Crc32Value[1],Crc32Value[2],Crc32Value[3]);
    
                /*Set write pointe to Byte of region end*/
                fseek(CCFGfPtr,regionEndAddr,SEEK_SET);
                /*Add data to region End*/
                fwrite(&Crc32Value[0],1,4,CCFGfPtr);
                printf("***CRC32 written to file address  %x to %x\n",regionStartAddr,regionEndAddr);
            } /*end of for loop*/
            
            /*Get Overall file size*/
            ccfgByteCount = getFileSize(CCFGfPtr); 
            ccfgmemPtr = (uint8_t*)calloc(ccfgByteCount, sizeof(uint8_t));
            uint32_t fileRd = 0;
            if((fileRd = fread(ccfgmemPtr,1 , ccfgByteCount, CCFGfPtr)) != ccfgByteCount)
                    {
                    printf("ERROR: Erase failed\n");
                    free(memPtr);
                    free(ccfgmemPtr);
                    closePort();
                    closeFile(CCFGfPtr);
                    closeFile(fPtr);
                    exit(EXIT_FAILURE);
                    }
                    else{
                        printf("FILE read OK, fileRd: %u \n", fileRd);
                        ccfgCrc=calcCrcLikeChip(ccfgmemPtr,ccfgByteCount);                    
                        }
        closeFile(CCFGfPtr);        
        }/* End of all file operations*/
        printf("+-----------------------------------\n");
    
        /* Erase flash */
        printf("Erasing flash ...\n");
        if(chipErase()!= SBL_SUCCESS)
        {
            printf("ERROR: Erase failed\n");
            free(memPtr);
            free(ccfgmemPtr);
            closePort();
            closeFile(CCFGfPtr);
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
        else
            printf("ERASE OK\n");
    
    
        /* Write file to device flash memory */
        printf("+-----------------------------------\n");
        printf("Writing flash ...\n");
        if(writeFlashRange(getDeviceFlashBase(), fileSz, (char*)memPtr) != SBL_SUCCESS)
        {
            printf("ERROR: writing failed\n");
            free(memPtr);
            free(ccfgmemPtr);
            closePort();
            closeFile(CCFGfPtr);
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
        else
            printf("\nWRITE OK\n");
    
         /* Write ccfg file to device flash memory */
        printf("+-----------------------------------\n");
        printf("Writing ccfg ...\n");
        if(writeFlashRange(devCcfgBase, ccfgByteCount, (char*)ccfgmemPtr) != SBL_SUCCESS)
        {
            printf("ERROR: Writing failed\n");
            free(memPtr);
            free(ccfgmemPtr);
            closePort();
            closeFile(CCFGfPtr);
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
        else
            printf("WRITE OK\n");  
    
        /* Calculate CRC checksum of flashed content */
        printf("Calculating CRC of flashed content ...\n");
        if(calculateCrc32(getDeviceFlashBase(), fileSz, &fileCrc) != SBL_SUCCESS)
        {
            printf("ERROR: CRC failed\n");
            free(memPtr);
            closePort();
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
        printf("Calculating CRC of CCFG content ...\n");
        if(calculateCrc32(devCcfgBase, ccfgByteCount, &ccfgCrc) != SBL_SUCCESS)
        {
            printf("ERROR: CRC failed\n");
            free(memPtr);
            closePort();
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
    
        /* Reset the device */
        if(reset() != SBL_SUCCESS)
        {
            printf("ERROR: RST failed!\n");
            printf("ERROR: Erase failed\n");
            free(memPtr);
            free(ccfgmemPtr);
            closePort();
            closeFile(CCFGfPtr);
            closeFile(fPtr);
            exit(EXIT_FAILURE);
        }
        else
            printf("RST OK\n");
        u32tRuntime_stop=time(NULL);
        printf("Runtime: %i Seconds\n",u32tRuntime_stop-u32tRuntime_start);	
        /* If we got here, means all succeeded */
        printf("+-----------------------------------\n");
        printf("CC2340 FIRMWARE UPGRADE COMPLETED !-\n");
        printf("+-----------------------------------\n\n");
    
        /* De-allocate the memory */
        free(memPtr);
    
        /* Close all */
        closeFile(fPtr);
        free(ccfgmemPtr);
        closePort();
    
        /* exit on success */
        exit(EXIT_SUCCESS);
    }
    

  • Here is a screenshot from the URL I shared:

    I recommend that you use the default TI_CC2340_Linux_SBL tool provided online.  Your upgrades could very well be successful even if the CRC check fails.  You should check the changes you've made to your application before and after attempting the upgrade.  You could also choose to remove the CCFG area from your binary output generation if you do not need to apply any changes to the default CCFG settings.

    Regards,
    Ryan

  • Hi, TI Engineer

    I currently have the following questions:

    1. The ccfg file exported through the Uniflash tool starts at address 0x4e020000 and ends at address 0x4e0207ff. It cannot be exported to 0x4e020800. How can this be made compatible?

    2. In the screenshot below, the size of the out file starting with data is as shown. When we burn the file, the process fails at the beginning of writing to flash. The file size, after actual calculation, is not an integer multiple of 2048 bytes. How should this be configured? Please provide guidance.

    3. In the screenshot below, the size of the out file starting with uart is as shown. When we burn the file, the process fails during the CRC check after writing to flash. The file size, after actual calculation, is not an integer multiple of 2048 bytes. How should this be configured? Please provide guidance.

    4. The link to the TI_CC2340_Linux_SBL tool provided by your company is inaccessible. Could you please provide the link again?

  • 1.0x4e0207ff is the last byte of CCFG and the last byte you should be reading from Uniflash for the CCFG
    2. You should not use the .out file with the Linux SBL tool as it only accepts binaries.  You should be reading out memory in binary format from Uniflash aligned with the 0x800 sector size.  This will require programming a CC2340R5 device once with the .out file (does not have to be the ultimate target)
    4. Attached is a copy if you cannot access GitHub

    TI_CC2340_Linux_SBL.zip

    Regards,
    Ryan

  • Hi Ryan,
    I have a few questions to confirm with you:

    1. Previously, when we performed Bluetooth firmware upgrades via the emulator, only the FCFG file was required. However, upgrading via UART now requires the CCFG file as well. Is there a way to update the CCFG file without entering bootloader mode to enable programming and proceed with the UART Bluetooth firmware upgrade?
    2. During programming, if there is a random power failure (without programming the CCFG), is it possible that the device will fail to enter bootloader mode?
    3. Does UART programming support encryption? If so, how should we proceed?
    4. Is there a bad block detection mechanism in the programmed flash? If so, what steps should we take to prevent the generation of bad blocks?

    Thank you!

  • Please be sure to read Chapter 8 (Device Boot and Bootloader) of the TRM.

    1. You likely don't mean the FCFG as this is a factory configuration which cannot be altered by users.  Upgrading via UART doesn't require a CCFG file if the default FCFG settings are being used (indicated by a blank CCFG which TI ships devices as the default).  CCFG is stored in flash and it is not recommended that users erase and write this flash during run-time as it could invalidate the CCFG if a power event or device reset occurs.
    2. The BLDR_CMD_CHIP_ERASE command erases CCFG, so this is possible if you are using a custom CCFG that strays from the default FCFG.  
    3. The ROM Serial Bootloader does not, this would require use of a custom bootloader.  You can start with MCUBoot and develop from there.
    4. This is addressed through the BLDR_CMD_CRC32 command.

    Regards,
    Ryan

  • Hi Ryan

    1.Could you provide a demo or relevant guidance documents regarding encrypted programming using a custom bootloader?

    2.What is the BLDR_CMD_CRC32 command mentioned? How can we verify it ourselves? In the corresponding SBL source code or firmware program, where is this command handled?

    3.During the firmware programming process, what is the specific solution for the bad block detection mechanism? Can we verify it ourselves? How is it handled in the corresponding source code?

    Thank you!

  • 1. It's possible to select "User-specific bootloader" and its Bootloader Vector Table from SysConfig.  Encryption TI Drivers and examples are available for your reference, although there is no full-function custom bootloader solution currently provided by TI publicly.

    2. All bootloader commands are fully described in Chapter 8 (Device Boot and Bootloader) of the TRM so that users can fully operate the ROM Serial Bootloader to upgrade devices within their application.

    3. CRC32 (Cyclic Redundancy Check 32) is a 32-bit error-detecting code that produces a fixed-length checksum from a block of data to verify its integrity.

    Regards,
    Ryan

  • Hi Ryan

    1. After compiling the custom bootloader using the IDE, how can we write it to the corresponding location, and how can we verify whether the modifications have taken effect?
    2. Besides the modifications provided last time, are there any other areas that also need to be modified?

    Thank you!

  • 1. Your custom bootloader project should have its own command linker file (*.cmd in CCS) for which you will set the resetVecs and other sectors of Flash memory.  You can verify whether they have taken effect by stepping through code (see the Debug OAD Code section in a SLA) or adding in debuggable outputs (like GPIOs or UART).
    2. I wouldn't know what else to mention at this point or I would already have done so.

    Regards,
    Ryan