MSPM0G3519: POR does not reset INITDONE

Part Number: MSPM0G3519

I am using the TI MCUBoot port (CSC) on a custom board with and MSPM0G3519 MCU on it. After erasing secondary flash bank and flashing a new image to it I am issuing a Power On Reset using the call DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_POR). According to the documentation and forum posts this will clear INITDONE and allow for flash banks to be swapped by the bootloader, however INITDONE is not being cleared by the POR. Is there some other factor that could be affecting the failure to reset INITDONE? What additional steps can be taken to ensure it is cleared? 

  • Hi Aaron,

    A reset level higher than boot reset (includes both boot reset and POR reset) could both reset INITDONE.

    Have you enabled CSCEXISTS and FLASHBANKSWAPPOLICY filed in NONMAIN for your CSC solution? These two filed should be enabled to enable CSC process, you could refer to point #5 of 3.2.4.3 CSC NONMAIN Configuration of Cybersecurity Enablers in MSPM0 MCUs (Rev. A) for more details.

  • Hello Pengfei,

    CSCEXISTS and FLASHBANKSWAPPOLICY are both enabled. I am not having trouble entering CSC, I am never seeing INITDONE cleared by a POR. I see logs from the bootloader over uart, DL_SYSCTL_isINITDONEIssued() always returns true after a POR is issued, SECSTATUS always has a value of 0x1. When I am running in the main application and I call DL_SYSCTL_isExecuteFromUpperFlashBank() it always returns false, regardless of what image versions are in the two flash banks. I have included my CSC main application below. Is there some additional config that needs to be enabled to unlock the INITDONE flag? Is there some possible hardware issue that is stopping the MCU from completing a reset and clearing the INITDONE flag?



    CSC main

    int main(void)
    {
    uint8_t done = 0;
    fih_int bootStatus;
    struct boot_rsp bootRsp;
    SYSCFG_DL_init();
    MCUBOOT_LOG_INF("Starting bootloader\r\n");

    /* Execution flow for the privileged state. Device has no features but
    * static write protect enabled, and images are unverified, and
    * therefore must be authenticated.
    */
    MCUBOOT_LOG_INF("Checking initdone\r\n");
    if (!DL_SYSCTL_isINITDONEIssued()) {
    /* First boot - determine which bank to execute from and configure bank swap BEFORE INITDONE */
    MCUBOOT_LOG_INF("First boot - determining bank selection\r\n");
    boot_return_highest_version(&bootRsp);
    bootStatus = boot_go(&bootRsp);

    if ((0 == bootStatus) && (IMAGE_MAGIC == bootRsp.br_hdr->ih_magic)) {
    MCUBOOT_LOG_INF("Image found: offset = 0x%x, ver=%d.%d.%d.%d\r\n",
    bootRsp.br_image_off,
    bootRsp.br_hdr->ih_ver.iv_major,
    bootRsp.br_hdr->ih_ver.iv_minor,
    bootRsp.br_hdr->ih_ver.iv_revision,
    bootRsp.br_hdr->ih_ver.iv_build_num);

    /* Configure bank swap BEFORE INITDONE */
    if (bootRsp.br_image_off != PRIMARY_SLOT_OFFSET) {
    MCUBOOT_LOG_INF("Configuring bank swap for upper flash bank\r\n");
    DL_SYSCTL_executeFromUpperFlashBank();
    } else {
    MCUBOOT_LOG_INF("Configuring for lower flash bank (no swap)\r\n");
    DL_SYSCTL_executeFromLowerFlashBank();
    }
    }

    /* Set Firewalls (to be enabled upon INITDONE) */
    DL_SYSCTL_setWriteProtectFirewallAddrRange(
    (uint32_t) LOCKABLE_FLASH_FIREWALL);

    MCUBOOT_LOG_INF("Issuing INITDONE\r\n");
    DL_SYSCTL_issueINITDONE();
    }

    /* After INITDONE - boot from the configured bank */
    MCUBOOT_LOG_INF("initdone is set\r\n");

    MCUBOOT_LOG_INF("mcuboot_app\r\n");
    boot_return_highest_version(&bootRsp);

    bootStatus = boot_go(&bootRsp);
    MCUBOOT_LOG_INF("boot_go returned %d\r\n", bootStatus);
    if ((0 == bootStatus) && (IMAGE_MAGIC == bootRsp.br_hdr->ih_magic)) {
    MCUBOOT_LOG_INF("bootRsp: slot = %x, offset = %x, ver=%d.%d.%d.%d\r\n",
    bootStatus, bootRsp.br_image_off,
    bootRsp.br_hdr->ih_ver.iv_major,
    bootRsp.br_hdr->ih_ver.iv_minor,
    bootRsp.br_hdr->ih_ver.iv_revision,
    bootRsp.br_hdr->ih_ver.iv_build_num);

    /* Determine which bank we're executing from */
    uint32_t executing_bank;
    if (bootRsp.br_image_off != PRIMARY_SLOT_OFFSET) {
    MCUBOOT_LOG_INF("Executing from upper flash bank (after swap)\r\n");
    executing_bank = 1;
    } else {
    MCUBOOT_LOG_INF("Executing from lower flash bank\r\n");
    executing_bank = 0;
    }

    uint32_t current_version = bootRsp.br_hdr->ih_ver.iv_major << 24 |
    (bootRsp.br_hdr->ih_ver.iv_minor << 16) |
    (bootRsp.br_hdr->ih_ver.iv_revision << 8);
    // Encode bank number in LSB of signature
    uint32_t signature_with_bank = (SIGNATURE & 0xFFFFFFFE) | (executing_bank & 0x1);
    MCUBOOT_LOG_INF("Writing version info to flash: version 0x%08x, signature 0x%08x (bank %d), address 0x%x\r\n",
    current_version, signature_with_bank, executing_bank, FLASH_ADDR_FIRMWARE_VERSION);
    // Write current execution bank to both banks for redundancy
    write_version_info_to_flash(current_version, signature_with_bank, true);
    write_version_info_to_flash(current_version, signature_with_bank, false);

    } else {
    MCUBOOT_LOG_ERR("Boot go failed\r\n");
    mcubootFail();
    }
    do_boot(&bootRsp);
    //should never get here
    mcubootFail();
    }

  • After some additional investigation I see that CSCEXISTS is always zero in SECSTATUS. I have CSCEXISTS enabled in syscfg and I see in the generated boot_config.c file that cscexists is getting set to 0xffff. However when I use the memory viewer to look at 41c00018 it is set to 0xaabb, which indicates that CSC does not exist. I also see in the steps for the CSC projects that .BCRConfig and .BSLConfig are removed when using objcopy to create the BIN. When I change the objcopy step to not remove BCRConfig and BSLConfig the output bin becomes 1Gb in size and cannot be used.

    Objcopy step removing BSL and BCR
    C:/ti/ccs2041/ccs/tools/compiler/ti-cgt-armllvm_4.0.4.LTS/bin/tiarmobjcopy customer_secure_code_metering_prod.out -R .BCRConfig -R .BSLConfig -R .TI.bound* --output-target binary customer_secure_code_metering_prod-bank1-0x40000.bin

    My boot_config.c (not being used by build)

    PLACE_IN_MEMORY(".BCRConfig")
    const BCR_Config BCRConfig =
    {
        .bcrConfigID          = 0x4000000,
        .debugAccess          = BCR_CFG_DEBUG_ACCESS_EN,
        .swdpMode             = BCR_CFG_SWDP_EN,
        .tifaMode             = BCR_CFG_TIFA_EN,
        .bslPinInvokeEnable   = BCR_CFG_BSL_PIN_INVOKE_EN,
        .staticWriteProtectionMainLow  = CFG_DEFAULT_VALUE,
        .staticWriteProtectionMainHigh = CFG_DEFAULT_VALUE,
        .staticWriteProtectionNonMain  = BCR_CFG_NON_MAIN_STATIC_PROT_DIS,
        .debugHold            = BCR_CFG_DEBUG_HOLD_DIS,
        .CSCexist             = BCR_CFG_CSC_EXIST,
        .flashBankSwapPolicy  = BCR_CFG_FLASH_BS_EN,
        .fastBootMode         = BCR_CFG_FAST_BOOT_DIS,
  • Hi Aaron,

    Thanks for investigation and information for this issue.

    So you mean you are using the .bin format to download the firmware with NONMAIN (.BCRconfig and .BSLConfig) content and find the corresponding configuration is not well loaded to MCU flash right?

    Actually it is not recommended to used .bin format when their is NONMAIN content integrated within the firmware. Because .bin format has no address information, so by default the NONMAIN content in 0x41C00000 address will be just placed followed the application firmware. And if you just specify the filling data during the holes, it will cause a GB size file generated to fill the hole between application and 0x41C00000.

    So there are some way to solve this problem:

    • Use a format with address information as firmware, such as .hex, .txt.
    • If .bin file is a hard requirement, you need to make application firmware and NONMAIN content separated. You should be able to find the NONMAIN content in your current .bin file, and you could export them out and stored with a single .bin file.