MSPM0C1104: Inquiry on merging Flash BSL and Application into a single bin for production programming (MSPM0C1104)

Part Number: MSPM0C1104
Other Parts Discussed in Thread: UNIFLASH

Dear TI Team,


We have compiled a custom Bootloader (project name: flash_bsl) on the MSPM0C1104 (16KB Flash / 1KB SRAM) based on the TI Flash BSL example. It occupies MAIN Flash 0x0000–0x17FF, and we have successfully implemented over-the-I2C application updates using our own host tool (mcu_upgrade, I2C BSL protocol, application written at 0x1800). During development we have always flashed the CCS build outputs flash_bsl.bin and skyfire.bin separately, and both the BSL and the application work correctly.


We are now preparing for production and have two questions we would like to ask:
Question 1: Is there a way to merge the two bin files into a single bin?
Our production programmer expects to load a single bin file per programming cycle. We noticed that the CCS-generated flash_bsl.bin (5168 bytes) appears to be in a "compact multi-segment" format — its tail (starting at 0x13D8) already contains the NONMAIN BCR/BSL configuration data concatenated after the MAIN image, while skyfire.bin is pure application code starting at 0x1800. Does TI provide an official tool or recommended approach to merge the BSL and the application into a single bin (or hex) file usable by a production programmer? For example, specific tiarmobjcopy/tiobj2bin options, or an export feature in UniFlash?


Question 2: When programming with a non-UniFlash programmer, will the NONMAIN information be lost and brick the MCU?
Our production line will not use UniFlash. As far as we understand, a bin file carries no address information. If the programmer treats flash_bsl.bin as contiguous data starting at 0x0000, then:

- The BCR/BSL configuration data at the tail (from 0x13D8) would be written to the wrong location in the MAIN region;
- The real NONMAIN region (BCR config at 0x41C00000, BSL config at 0x41C00100) would not be programmed and would remain blank.

In this production-programmer scenario, what is the correct mass-production programming flow? Do we have to generate an Intel HEX file containing the NONMAIN segments (so the programmer can resolve addresses)? Or should the NONMAIN be programmed separately? If the NONMAIN is left blank, will the device become locked (inaccessible via both SWD and BSL)?

Both linker command files are attached below for your reference.

Hardware: MSPM0C1104 (16KB Flash / 1KB SRAM)
BSL: flash_bsl (0x0000–0x17FF, with BCR/BSL config in NONMAIN)
App: skyfire (application starts at 0x1800)
Thank you very much for your help. Looking forward to your reply.


Attached: Linker commands
flash_bsl/mspm0c1104.cmd (BSL project):
-uinterruptVectors
MEMORY
{
    INTVEC(RWX)              :    org = 0x00000000,        len = 0x000000C0,
    INVOCATION_START(RWX)   :    org = 0x000000C0,        len = 0x00000010,
    FLASH_BSL_START(RWX)    :    org = 0x000000D0,        len = 0x00000030,
    FLASH_BSL (RWX)            :    org = 0x00000100,        len = 0x00001700,
    SRAM (RW)                :    org = 0x20000000,        len = 0x00000400,
    BCR_CFG                     :    org = 0x41C00000,        len = 0x00000080,
    BSL_CFG                    :    org = 0x41C00100,        len = 0x00000080,
    FACTORY_CFG                  :    org = 0x41C40000,        len = 0x00000200,
}
SECTIONS
{
    .intvecs            : PALIGN(8) {} > INTVEC
    .invStart            : PALIGN(8) {} > INVOCATION_START
    .flashBSL_start        : PALIGN(8) {} > FLASH_BSL_START
    GROUP(FLASH_MEMORY)
    {
        .text              : PALIGN(8) {}
        .const             : PALIGN(8) {}
        .cinit             : PALIGN(8) {}
        .rodata            : PALIGN(8) {}
    } > FLASH_BSL
    GROUP(SRAM)
    {
        .vtable            : {}
        .data              : {}
        .bss               : {}
    } > SRAM
    .stack  :   > SRAM (HIGH)
    .BCRConfig              : PALIGN(8){} > BCR_CFG
    .BSLConfig              : PALIGN(8){} > BSL_CFG
}
skyfire/cutomize_linker.cmd (App project):
-uinterruptVectors
--stack_size=64

MEMORY
{
    FLASH           (RX)  : origin = 0x00001800, length = 0x00002800
    SRAM            (RWX) : origin = 0x20000000, length = 0x00000400
    BCR_CONFIG      (R)   : origin = 0x41C00000, length = 0x000000FF
}

SECTIONS
{
    .intvecs:   > 0x00001800
    .text   : palign(8) {} > FLASH
    .const  : palign(8) {} > FLASH
    .cinit  : palign(8) {} > FLASH
    .pinit  : palign(8) {} > FLASH
    .rodata : palign(8) {} > FLASH
    .ARM.exidx    : palign(8) {} > FLASH
    .init_array   : palign(8) {} > FLASH
    .binit        : palign(8) {} > FLASH
    .TI.ramfunc   : load = FLASH, palign(8), run=SRAM, table(BINIT)

    .vtable :   > SRAM
    .args   :   > SRAM
    .data   :   > SRAM
    .bss    :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM (HIGH)

    .BCRConfig  : {} > BCR_CONFIG
}

  • Hi Gryphon,

    Question 1: I do not recommend to program NONMAIN region in a bin format. As bin format is a pure binary format without address information, so it is necessary to give a start address when programming bin file. The way to merge two bin files is to fill 0xFF data between two bin files, it may work for two bin format application firmware. But for NONMAIN content, as it is located in 0x41C00000, it is not feasible to fill 0xFF between 0x00000 to 0x41C00000 in bin file. My recommendation will be:

    • Use other format for NONMAIN content programming which has address information, such as HEX, TI-TXT.
    • If bin format is the only option, then you need to program NONMAIN separately. You may need to divide application firmware and NONMAIN and give start address 0x0 for application and give start address 0x41C00000 for NONMAIN.

    Question 2: If you use programmer like Uniflash (XDS110), J-Flash (J-Link), then NONMAIN programming is auto supported. But if other customize programmer is used, it should be carefully taken care to make sure NONMAIN is well programmed to target address (start from 0x41C00000), otherwise your configuration in NONMAIN will not take effect. To make NONMAIN is well programmed, you need to unprotect NONMAIN region before erase it in your flashing script. A programming example could be found in SDK:

    flashctl_nonmain_memory_write 

  • Hi Pengfei,


    We plan to use Intel HEX format for subsequent programming. Based on your suggestion, we just need to combine the APP and BSL into a single file, with any gaps filled with 0xFF, correct? 

    In this way, the BSL, APP, and NONMAIN regions can all be included in one HEX file, allowing us to complete the entire programming in a single pass.

  • Hi Gryphon,

    If you use HEX file, then as it is a format with address information for all data inside, then you even do not need to fill 0xFF between different parts. You could totally merge all BSL, APP and NONMAIN into a single HEX file for production.