This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: Dual boot configuration

Part Number: TMS320F28335

Tool/software:

Dear Team,

I am currently using the TMS320F28335 MCU with an external SPI-based EEPROM.

At present, I receive hex file frames via UART, store them in EEPROM, and upon receiving all the hex file data, I flash it from EEPROM to the internal flash memory, effectively updating the firmware. This approach is functioning well.

I now aim to enhance this setup by storing the hex file frames directly in another available sector of the internal flash, instead of using the external EEPROM. Once all hex file data is received, I plan to perform a software reset to initiate the new firmware—essentially implementing a dual-bank firmware update.

Could you please guide me on the implementation steps for this transition? If any relevant code examples are available, I would appreciate it if you could share those along with instructions on configuring the linker file for dual-bank firmware updates.

Thank you and best regards,
Dipak

  • Hi Dipak,

    Instead of an EEPROM, I believe one of our flash kernel implementations would better fit your problem. Please see Serial Flash Programming of C2000 Microcontrollers (Rev. H) flash kernel A for an example implementation and discussion.

    If you still want to emulate an EEPROM unit, reference our example implementation in EEPROM Emulation for Gen 2 C2000 Real-Time MCUs (Rev. A).

    Please also note that since this device only has one flash pump, any code that modifies flash must be run from RAM.

  • Hi Alex Wasinger,

    Thank you for your response!

    My goal is to receive a new firmware file via UART while my main application continues to run. Once the firmware is fully received, my application will perform a software reset to switch to the new firmware.

    Please note, I have a custom frame format set up for both data reception and acknowledgment.

    I would appreciate any guidance on implementing this type of configuration.

    Thank you for your assistance!

  • Dipak,

    No problem, feel free to open up more threads as you progress.

    Best,

    Alex

  • Hi Alex,

    I would like to know how to setup configuration for bank 2 for firmware update?

    -Dipak

  • Dipak,

    To change the entry point of boot to flash, you need to program a branch instruction to 0x33 FFF6, as described in section 1.1.3.3 of the TMS320x2833x, TMS320x2823x Technical Reference Manual and table 8-22 of TMS320F2833x, TMS320F2823x Real-Time Microcontrollers datasheet (Rev. Q).

    This device only has one flash bank, so you would have to program your application to a different sector and change the entry point if you want to have both firmware versions in flash at the same time before swapping. You could also use the flash kernel to update the firmware directly, without having to change the entry point.

    Best,

    Alex

  • Hi Alex,

    Let me explain again,

    Procedure:

    1. Linker File Setup:

      • Sector D is designated for the firmware in the linker file.
      • The hex file is generated based on this configuration.
    2. Bootloader Code:

      • Two sectors are designated for firmware updates:
        • Active Sector: Contains the currently running firmware (initially Sector D).
        • Inactive Sector: Reserved for the new firmware update (initially Sector F).
    3. Firmware Update Process: - firmware data is collected over UART.

      • Upon receiving a firmware update command:
        • A flag is set to indicate that the update is in progress.
        • The base address is adjusted to point to the inactive sector.
        • The bootloader checks the active and inactive sectors.
        • New firmware is written to the inactive sector (e.g., Sector F).
    4. After Writing to the Inactive Sector:

      • The bootloader marks the updated sector as active (Sector F).
      • The return address is set to the new active sector (Sector F).
      • The update flag is reset.
      • The application should start from the new active sector (Sector F).
      • Note: flag and active sector is stored in SECTOR B.

    Issue:

    • After the update, Sector F becomes active and Sector D becomes inactive. However, the bootloader is not starting the code from Sector F why?.

    Could you please guide me on what might be missing or any additional steps I need to take to resolve this?

    Best and regards,

    Dipak

    /*
    //###########################################################################
    //
    // FILE:	F28335.cmd
    //
    // TITLE:	Linker Command File For F28335 Device
    //
    //###########################################################################
    // $TI Release: F28335 API Release V2.10 $
    // $Release Date: August 18, 2008 $
    //###########################################################################
    */
    
    /* ======================================================
    // For Code Composer Studio V2.2 and later
    // ---------------------------------------
    // In addition to this memory linker command file,
    // add the header linker command file directly to the project.
    // The header linker command file is required to link the
    // peripheral structures to the proper locations within
    // the memory map.
    //
    // The header linker files are found in <base>\DSP2833x_Headers\cmd
    //
    // For BIOS applications add:      DSP2833x_Headers_BIOS.cmd
    // For nonBIOS applications add:   DSP2833x_Headers_nonBIOS.cmd
    ========================================================= */
    
    /* ======================================================
    // For Code Composer Studio prior to V2.2
    // --------------------------------------
    // 1) Use one of the following -l statements to include the
    // header linker command file in the project. The header linker
    // file is required to link the peripheral structures to the proper
    // locations within the memory map                                    */
    
    /* Uncomment this line to include file only for non-BIOS applications */
    /* -l DSP2833x_Headers_nonBIOS.cmd */
    
    /* Uncomment this line to include file only for BIOS applications */
    /* -l DSP2833x_Headers_BIOS.cmd */
    
    /* 2) In your project add the path to <base>\DSP2833x_headers\cmd to the
       library search path under project->build options, linker tab,
       library search path (-i).
    /*========================================================= */
    
    /* Define the memory block start/length for the F28335
       PAGE 0 will be used to organize program sections
       PAGE 1 will be used to organize data sections
    
        Notes:
              Memory blocks on F28335 are uniform (ie same
              physical memory) in both PAGE 0 and PAGE 1.
              That is the same memory region should not be
              defined for both PAGE 0 and PAGE 1.
              Doing so will result in corruption of program
              and/or data.
    
              L0/L1/L2 and L3 memory blocks are mirrored - that is
              they can be accessed in high memory or low memory.
              For simplicity only one instance is used in this
              linker file.
    
              Contiguous SARAM memory blocks can be combined
              if required to create a larger memory block.
     */
    
    
    MEMORY
    {
    PAGE 0:    /* Program Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */
    
       ZONE0       : origin = 0x004000, length = 0x001000     /* XINTF zone 0 */
       RAML0       : origin = 0x008000, length = 0x001000     /* on-chip RAM block L0 */
       RAML1       : origin = 0x009000, length = 0x001000     /* on-chip RAM block L1 */
       RAML2       : origin = 0x00A000, length = 0x001000     /* on-chip RAM block L2 */
       RAML3       : origin = 0x00B000, length = 0x001000     /* on-chip RAM block L3 */
       ZONE6       : origin = 0x0100000, length = 0x100000    /* XINTF zone 6 */ 
       ZONE7A      : origin = 0x0200000, length = 0x00FC00    /* XINTF zone 7 - program space */ 
    
       FLASHH      : origin = 0x300000, length = 0x008000     /* on-chip FLASH */
       FLASHG      : origin = 0x308000, length = 0x008000     /* on-chip FLASH */
    
       FLASHF      : origin = 0x310000, length = 0x008000     /* on-chip FLASH */
       FLASHE      : origin = 0x318000, length = 0x008000     /* on-chip FLASH */
       FLASHD      : origin = 0x320000, length = 0x007F80     /* on-chip FLASH */
       FLASHC      : origin = 0x328000, length = 0x008000     /* on-chip FLASH */
       FLASHB      : origin = 0x330000, length = 0x008000     /* on-chip FLASH */
       FLASHA      : origin = 0x338000, length = 0x008000     /* on-chip FLASH */
    
       CSM_RSVD    : origin = 0x327F80, length = 0x000076     /* Part of FLASHF.  Program with all 0x0000 when CSM is in use. */
       BEGIN       : origin = 0x327FF6, length = 0x000002     /* Part of FLASHF.  Used for "boot to Flash" bootloader mode. */
       CSM_PWL     : origin = 0x327FF8, length = 0x000008     /* Part of FLASHF.  CSM password locations in FLASHF */
    
       OTP         : origin = 0x380400, length = 0x000400     /* on-chip OTP */
       ADC_CAL     : origin = 0x380080, length = 0x000009     /* ADC_cal function in Reserved memory */
       
       IQTABLES    : origin = 0x3FE000, length = 0x000b50     /* IQ Math Tables in Boot ROM */
       IQTABLES2   : origin = 0x3FEB50, length = 0x00008c     /* IQ Math Tables in Boot ROM */  
       FPUTABLES   : origin = 0x3FEBDC, length = 0x0006A0     /* FPU Tables in Boot ROM */
       ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */        
       RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
       VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */
    
    PAGE 1 :   /* Data Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */
               /* Registers remain on PAGE1                                                  */
    
       BOOT_RSVD   : origin = 0x000000, length = 0x000050     /* Part of M0, BOOT rom will use this for stack */
       RAMM0       : origin = 0x000050, length = 0x0003B0     /* on-chip RAM block M0 */
       RAMM1       : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
       RAML4       : origin = 0x00C000, length = 0x001000     /* on-chip RAM block L1 */
       RAML5       : origin = 0x00D000, length = 0x001000     /* on-chip RAM block L1 */
       RAML6       : origin = 0x00E000, length = 0x001000     /* on-chip RAM block L1 */
       RAML7       : origin = 0x00F000, length = 0x001000     /* on-chip RAM block L1 */
       ZONE7B      : origin = 0x20FC00, length = 0x000400     /* XINTF zone 7 - data space */
    
    
    }
    
    /* Allocate sections to memory blocks.
       Note:
             codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code
                       execution when booting to flash
             ramfuncs  user defined section to store functions that will be copied from Flash into RAM
    */
    
    SECTIONS
    {
    
       /* Allocate program areas: */
       .cinit              : > FLASHD      PAGE = 0
       .pinit              : > FLASHD,     PAGE = 0
       .text               : > FLASHD      PAGE = 0
       codestart           : > BEGIN       PAGE = 0
       ramfuncs            : LOAD = FLASHB,
                             RUN = RAML0,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_END(_RamfuncsLoadEnd),
                             RUN_START(_RamfuncsRunStart),
                             LOAD_SIZE(_RamfuncsLoadSize),
                             PAGE = 0
    
       csmpasswds          : > CSM_PWL     PAGE = 0
       csm_rsvd            : > CSM_RSVD    PAGE = 0
    
     /* Other sections here */
        .myArray : > FLASHE  PAGE = 0/* Place the "myArray" section in FLASHD */
    
        /* Other sections here */
    
       /* Allocate uninitalized data sections: */
       .stack              : > RAMM1       PAGE = 1
       .ebss               : > RAML4       PAGE = 1
       .esysmem            : > RAMM1       PAGE = 1
    
       /* Initalized sections go in Flash */
       /* For SDFlash to program these, they must be allocated to page 0 */
       .econst             : > FLASHD      PAGE = 0
       .switch             : > FLASHD      PAGE = 0
    
       /* Allocate IQ math areas: */
       IQmath              : > FLASHD      PAGE = 0                  /* Math Code */
       IQmathTables     : > IQTABLES,  PAGE = 0, TYPE = NOLOAD
       IQmathTables2    : > IQTABLES2, PAGE = 0, TYPE = NOLOAD
       FPUmathTables    : > FPUTABLES, PAGE = 0, TYPE = NOLOAD
             
       /* Allocate DMA-accessible RAM sections: */
       DMARAML4         : > RAML4,     PAGE = 1
       DMARAML5         : > RAML5,     PAGE = 1
       DMARAML6         : > RAML6,     PAGE = 1
       DMARAML7         : > RAML7,     PAGE = 1
       
       /* Allocate 0x400 of XINTF Zone 7 to storing data */
       ZONE7DATA        : > ZONE7B,    PAGE = 1
    
       /* .reset is a standard section used by the compiler.  It contains the */ 
       /* the address of the start of _c_int00 for C Code.   /*
       /* When using the boot ROM this section and the CPU vector */
       /* table is not needed.  Thus the default type is set here to  */
       /* DSECT  */ 
       .reset              : > RESET,      PAGE = 0, TYPE = DSECT
       vectors             : > VECTORS     PAGE = 0, TYPE = DSECT
    
       /* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */
       .adc_cal     : load = ADC_CAL,   PAGE = 0, TYPE = NOLOAD
    
    
    
    
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    
    

  • Dipak,

    A few actions you can try:

    • Update your linker CMD file to store your application in FLASHF instead of FLASHD when building. This will ensure the program is written to the correct location in flash
    • Verify the branch address and the application start address (the BEGIN/codestart section) are the same
    • If wanting to boot from flash after the update, update the BEGIN section to start at 0x33FFF6, this will update the branch instruction mentioned in the TMS320F2833x, TMS320F2823x Real-Time Microcontrollers datasheet (Rev. Q) table 8-22 to point to the new firmware instead of the bootloader.

    Best,

    Alex

  • Hi Alex,

    • Update your linker CMD file to store your application in FLASHF instead of FLASHD when building. This will ensure the program is written to the correct location in flash
    • Answer: That is the key point , my hex file always contains sector d address but I will replace the sector d address to sector F in bootloader code and will place the whole hex data to sector F.

     

    Do I have to change reset vector table as well?

    Best and regards ,

    Dipak

  • Dipak,

    How are you changing the references/branch instructions within the code? This is not possible without updating the linker file to use the correct addresses.

    Best,

    Alex

  • Hi Alex,

    I have received the firmware with base address to sector D (0x320000)but I am writing it to on sector F(0x310000) by changing the base address ( handle this in bootloader code successfully )

    And once all the whole hex data is written to sector F I am giving the return address of sector F to the branch instruction but code is not working.

    Note : everytime I don't want change sector D and sector F address manually in linker file

    So I am generating the hex file with base address of sector D

    And I am handling the active and inactive sector in bootloader code.

    And also I would like to know is it possible to implement LFU in Tms320f28335?

    -Dipak

  • Dipak,

    Changing the base address of the firmware will also impact branch instructions, load instructions, etc., all of which still point to sector D. This is why your code is not running -- updating the linker file to use sector F will ensure all these instructions are correct.

    An LFU implementation is possible, but very difficult.

    Best,

    Alex

  • Can we change the branch instruction ,load instructions etc., in bootloader code manually?

    Can you please guide me how to do this?

  • Dipak,

    No, the TMS320F28335 doesn't support position independent code.

    If you want the linker file to stay the same, you will have to overwrite the application in sector D. 

    If redundancy is important, your bootloader could validate the application before branching, and if not valid wait for an update over a peripheral.

    Best,

    Alex

  • Alex,

    Then I am confused about LFU?

    LFU is not doing the same thing as we discussed above?

    Best,

    Dipak 

  • Dipak,

    LFU refers to firmware updates to a system while it is operating, with a mechanism to switchover to the new firmware either through a device reset, or without a device reset. Live Firmware Update With Device Reset on C2000 MCUs discusses an example of this in more detail.

    From my understanding (please correct me if I'm wrong), your "flash kernel"/bootloader must be running exclusively while it is receiving the application, which disqualifies it as an LFU because the old firmware doesn't continue to run during the update.

    Best,

    Alex

  • Dipak,

    I haven't heard back from you in a bit, so I am going to mark this thread as resolved.

    Best,

    Alex

  • Hi Alex,

    Apologies for the delayed response.

    I was unwell and unable to reply earlier.

    I just want to confirm whether the LFU linker file remains the same or differs.

    [ Specifically, it receives the firmware while the application is running and, once the firmware data is received successfully, update the firmware at the same address as the previously written firmware? ]

    Best regards,
    Dipak

  • Dipak,

    The linker file should match the memory region(s) that you are programming the application to.

    For example, if we have an application in sector D and would like to overwrite it with an updated version, also in sector D, the same linker file can be used.

    But, if the update is written to a different memory region, say sector F, then the linker file must be updated to place the application in sector F.

    C28 devices don't support A/B swapping memory/using the same addresses for different underlying flash cells, and as stated previously, the C2000 compiler tools do not support position independent code, so programming with an offset added will not work (see this e2e, which asks a similar question).

    Best,

    Alex