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.

[FAQ] How to use Flash Mirror Mode

Part Number: MSP432E401Y
Other Parts Discussed in Thread: MMWAVEPOEEVM

Tool/software: TI C/C++ Compiler

We are working on a field firmware upgrade solution for our MSP432E project in which a new firmware image will be received via FTP and stored in a local file system that is accessible by MSP432E. The MSP432E will then read the new image from the filesystem and program it to Flash. Then we are hoping to leverage the "Flash Mirror Mode" to switch between two Flash images on the device. A few questions:

  • Are there any example for this type of field upgrade solution?
  • Is there a source code example for how to parse an program image created by armhex.exe? We don't want to use .out Elf files because these have a significantly larger file size.

We are using TI ARM Compiler v18.12.3.LTS

Thanks in advance.

  • Hello,

    Sorry for the delay. We are looking into this and will get back to you ASAP.

    Thanks,

    Alexis

  • Hi rperezti,

    Check out the MSP432E4 SimpleLink Academy lab, MSP432E4 Boot Loader. There is a section in this lab that walks you through the steps needed to run the BSL scripter to download the Boot Loader for TFTP data transfer. 

    I will look into your second query and get back to you shortly.

    BR,

    Seong

  • Here are some notes on how we were able to leverage the MSP432E4 Flash Mirror Mode using a TI-RTOS based project.

    • The MSP432E4 Flash Mirror Mode is described in Section 7.2.3.3 of the TRM here.
    • This mode allows the MSP432E4 CPU to "hot swap" execution between the bottom 512KB of Flash memory (0 to 0x7FFFF) and the top 512KB of Flash memory (0x80000 to 0x100000).
    • When the FMME bit of the FLASHCONF register is set, the Flash address translation is changed on-the-fly, such that the CPU continues execution of code from the upper half of Flash (+080000h offset).
    • From the CPU's perspective, the "mirrored code" at the top half of Flash is mapped to the lower half of Flash when the FMME bit is set, so the program must be linked with run addresses in lower Flash. In other words, branch addresses and pointer references are all in the range 0x000000h to 0x07FFFFh.
    • In order for this to work, the code that executes the setting of FMME bit must be identical between the lower half of Flash and the upper half (+080000h offset). If these two code locations are not identical, then the CPU will likely throw an exception as its execution context is changed incorrectly.

    One way to make use of this feature is to have a program at the lower half of Flash (e.g. a bootloader) that conditionally switches execution to a program in the top half of Flash. Here is one way to use this with a TI-RTOS based program:

    • Create a Reset hook function that decides whether to engage mirror mode (e.g. checks a switch setting) and sets the FMME bit to enable Flash Mirror Mode.
      • Modify the .CFG file to include a line like this:

      Startup.resetFxn = "&my_reset";

      • For this example we check the state of MSP432E4 GPIOPN1 which is connected to a switch on the MMWAVEPOEEVM. Define my_reset() function in the project with some code like this:

    void my_reset(void)
    {
    
    int32_t x;
    
    /* Enagle GPIO on PN1 to check SW2 */
    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    
    GPIODirModeSet(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_DIR_MODE_IN);
    
    GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_1);
    
    if (!(GPIOPinRead( GPIO_PORTN_BASE, GPIO_PIN_1) && GPIO_PIN_1))
    {
    
    /* Button SW2 pressed, so let's run mirror mode */
    
    x = HWREG(FLASH_CONF);
    
    x |= FLASH_CONF_FMME;
    
    HWREG(FLASH_CONF) = x;
    
    asm(" nop");
    
    asm(" nop");
    
    }
    
    else /* Disable mirror mode */
    {
    
    x = HWREG(FLASH_CONF);
    
    x &= ~FLASH_CONF_FMME;
    
    HWREG(FLASH_CONF) = x;
    
    asm(" nop");
    
    asm(" nop");
    
    }
    
    }
    

    • Link the address of this hook function to the same offset for both program images. To do this, you must fix the address of the _c_int00 function in boot.asm as well as the XDC function "xdc_runtime_Startup_reset__I" and your reset hook function from above. The reason this is necessary is that when a TI-RTOS program starts the _c_int00 function calls xdc_runtime_Startup_reset__I, which then calls the reset hook function. After transitioning to mirror mode, its critical that the CPU returns to the correct place in code. You can read more about this in the "Runtime" section of the XDC CDOC here. The linker syntax for fixing these addresses looks like this:
    SECTIONS
    {
    
        .special: {
                      * (.text:xdc_runtime_Startup_reset__I) /* Fix addr of xdc_runtime_Startup_reset__I */ 
                      my_reset.obj (.text) /* Fix addr of my_reset() */ 
                      ti/targets/arm/rtsarm/lib/boot.aem4f<boot.oem4f>(.text) /* Fix addr of _c_int00 */
                  }  > 0x00006000 /* Arbitrarily chosen offset */
    }
    • Program the primary program image at offset 0x0 of Flash, and program the alternate version at offset 0x80000 of Flash. Remember to link the alternate image as if it runs from offset 0x0 of Flash, but use an offset of 0x80000 when programming it into Flash memory.

    That's it, you will be able to switch between the two images by driving GPIOPN1 low or high after power on reset.

**Attention** This is a public forum