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.

MSP430F5438A: Main Memory Bootloader

Part Number: MSP430F5438A
Other Parts Discussed in Thread: MSP430F5529,

Hi everyone,

I want to design Main Memory Bootloader and I am taking reference from slaa600d and MSP430F5529_Examples for Main Memory Bootloader.

I have a requirement where I have Bootloader, Application1 and Application2 sharing the MSP430F5438A flash. And MSP430F5438A should be able to reprogram itself in Application2 area using Bootloader without any external event and interference. Application1 is the backup Application which will be untouched by Bootloader. So basically the MSP430 receives the new code to be programmed from an external processor over CAN and stores it in a serial SPI flash. Then it resets itself to go to bootloader. Bootloader reads the code from serial SPI flash and downloads the new code to the Application2 area. In case of any problem, we have the default backup application in Application1 area which is untouched and Bootloader can jump to it if any problem and corruption in Application2.

So there is no need for me to use Communication Interface Code.

I am not using custom BSL because it restricts the Bootloader code to 2KB. For the time being, I am putting my bootloader in the lower flash and divide the upper flash into two regions for Application1 and Application2. 

Also, I am putting the proxy reset vectors in the lower flash and the proxy vector addresses are shared by Application1 and Application2 both. Is it possible? I am not using Vector redirection to RAM because there is always a possibility of RAM corruption even though I know with vector redirection to RAM, proxy vector addresses will be logically separated.

I am still in the idea stage and I have attached my three linker command files in the text format. They are Bootloader.txt, App1.txt, and App2.txt. I would like to know if there are any potential problems in the linker cmd files. Please have a look at it.

Any suggestions, possible point of failures and workarounds will be helpful for me.

P.S. I am using almost all lower flash almost 40 KB for the bootloader and 216 KB upper flash for Application1 + Application2 for testing purposes at the initial stage.

Thanks and Regards,

Ankit

/******************************************************************************/
/* LINKER COMMAND FILE FOR MSPBoot BOOTLOADER USING msp430f5529  */
/* File generated with MSPBoot_linkergen_Flash.pl on 06-22-2017 */
/*----------------------------------------------------------------------------*/


/****************************************************************************/
/* SPECIFY THE SYSTEM MEMORY MAP                                            */
/****************************************************************************/
/* The following definitions can be changed to customize the memory map for a different device
 *   or other adjustments
 *  Note that the changes should match the definitions used in MEMORY and SECTIONS
 *
 */
/* RAM Memory Addresses */
__RAM_Start = 0x1C00;                 /* RAM Start */
__RAM_End = 0x5BFF;                     /* RAM End */
    /* RAM shared between App and Bootloader, must be reserved */
    PassWd = 0x1C00;                 /* Password sent by App to force boot  mode */
    StatCtrl = 0x1C02;             /* Status and Control  byte used by Comm */

    /* Unreserved RAM used for Bootloader or App purposes */
    _NonReserved_RAM_Start = 0x1C03; /* Non-reserved RAM */

/* Flash memory addresses */
/* App area     : 4400-F3FF & 10000-149FF*/
/* Download area: 14A00-243FF*/
/* Boot area    : F400-FFFF*/

_Appl1_Start = 0x10000;             /* Start of Application1 area */
_Appl1_End = 0x2ADFF;                 /* End of Application1 area */
_Appl2_Start = 0x2AE00;             /* Start of Application2 area */
_Appl2_End = 0x45BFF;                 /* End of Application2 area */

    /* Reserved Flash locations for Bootloader Area */
    __Boot_Start = 0x5CFE;         /* Boot flash */
    __Boot_Reset = 0xFFFE;                          /* Boot reset vector */
    __Boot_VectorTable = 0xFF80;      /* Boot vector table */
    //__Boot_SharedCallbacks_Len = 6; /* Length of shared callbacks (2 calls =4B(msp430) or 8B(msp430x) */
    //__Boot_SharedCallbacks = 0xFF7A; /* Start of Shared callbacks */
    _Appl_Proxy_Vector_Start = 0x5C00; /* Proxy interrupt table */
    /* Reserved Flash locations for Application Area */
    _Appl1_Checksum_Checksum = (_Appl1_Start);                   /* CRC16 of Application */
    _Appl1_Start_Memory = (_Appl1_Start+2);                 /* Application Area */
    _Appl1_CRC_Size1 = (_Appl1_End - _Appl1_Start_Memory +1);         /* Number of bytes in lower memory calculated for CRC */

	_Appl2_Checksum = (_Appl2_Start);                   /* CRC16 of Application */
    _Appl2_Start_Memory = (_Appl2_Start+2);                 /* Application Area */
    _Appl2_CRC_Size1 = (_Appl2_End - _App2_Start_Memory +1);         /* Number of bytes in lower memory calculated for CRC */

    _Appl_Reset_Vector = (__Boot_Start - 2);
    
    /* MEMORY definition, adjust based on definitions above */
MEMORY
{
    SFR                     : origin = 0x0000, length = 0x0010
    PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
    PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
    // RAM from _NonReserved_RAM_Start - __RAM_End
    RAM                     : origin = 0x1C03, length = 0x3FFC
    // Flash from __Boot_Start -( __Boot_SharedCallbacks or INT_VECTOR_TABLE)
    FLASH                   : origin = 0x5CFE, length = 0xA282
    // Shared callbacks from __Boot_SharedCallbacks + Len (when used)
    //BOOT_SHARED_CALLBACKS   : origin = 0xFF7A, length = 6
    // Boot vector Table from __Boot_VectorTable- __Boot_Reset
    INT_VECTOR_TABLE        : origin = 0xFF80, length = 0x7E
    // Boot reset from __Boot_Reset-_Flash_End
    RESET                   : origin = 0xFFFE, length = 0x0002
}

/****************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY                              */
/****************************************************************************/

SECTIONS
{
    .bss        : {} > RAM                /* GLOBAL & STATIC VARS              */
    .data       : {} > RAM                /* GLOBAL & STATIC VARS              */
    .sysmem     : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
    .stack      : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */

    .text       : {} >> FLASH        /* CODE                 */
    .cinit      : {} > FLASH        /* INITIALIZATION TABLES*/ 
    .const      : {} >> FLASH       /* CONSTANT DATA        */
    .cio        : {} > RAM          /* C I/O BUFFER                      */

    .BOOT_APP_VECTORS : {} > BOOT_SHARED_CALLBACKS
    /* MSP430 INTERRUPT VECTORS          */
    .BOOT_VECTOR_TABLE : {} > INT_VECTOR_TABLE
    .reset       : {}               > RESET  /* MSP430 RESET VECTOR         */ 
}

/****************************************************************************/
/* INCLUDE PERIPHERALS MEMORY MAP                                           */
/****************************************************************************/

-l msp430f5438a.cmd

/******************************************************************************/
/* LINKER COMMAND FILE FOR MSPBoot BOOTLOADER USING msp430f5529  */
/* File generated with MSPBootLinkerGen.pl on 06-22-2017 */
/*----------------------------------------------------------------------------*/


/****************************************************************************/
/* SPECIFY THE SYSTEM MEMORY MAP                                            */
/****************************************************************************/
/* The following definitions can be changed to customize the memory map for a different device
 *   or other adjustments
 *  Note that the changes should match the definitions used in MEMORY and SECTIONS
 *
 */
/* RAM Memory Addresses */
__RAM_Start = 0x1C00;                 /* RAM Start */
__RAM_End = 0x5BFF;                     /* RAM End */
    /* RAM shared between App and Bootloader, must be reserved */
    PassWd = 0x1C00;                 /* Password sent by App to force boot  mode */
    StatCtrl = 0x1C02;             /* Status and Control  byte used by Comm */

    /* Unreserved RAM used for Bootloader or App purposes */
    _NonReserved_RAM_Start = 0x1C03; /* Non-reserved RAM */

/* Flash memory addresses */
__Flash_Start = 0x10000;             /* Start of Application area */
   /* Reserved Flash locations for Bootloader Area */
    __Boot_Start = 0x5CFE;         /* Boot flash */
    __Boot_Reset = 0xFFFE;                          /* Boot reset vector */
    __Boot_VectorTable = 0xFF80;      /* Boot vector table */
    //__Boot_SharedCallbacks_Len = 6; /* Length of shared callbacks (2 calls =4B(msp430) or 8B(msp430x) */
    //__Boot_SharedCallbacks = 0xFF7A; /* Start of Shared callbacks */
    //_BOOT_APPVECTOR = __Boot_SharedCallbacks;       /* Definition for application table             */
    _Appl_Proxy_Vector_Start = 0x5C00; /* Proxy interrupt table */
    /* Reserved Flash locations for Application Area */
 
/* MEMORY definition, adjust based on definitions above */
MEMORY
{
    SFR                     : origin = 0x0000, length = 0x0010
    PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
    PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
    // RAM from _NonReserved_RAM_Start - __RAM_End
    RAM                     : origin = 0x1C03, length = 0x3FFC
	// Info Mem Sections
	INFOA                   : origin = 0x1980, length = 0x80
    INFOB                   : origin = 0x1900, length = 0x80
    INFOC                   : origin = 0x1880, length = 0x80
    INFOD                   : origin = 0x1800, length = 0x80
    // Flash from _App_Start -> (APP_PROXY_VECTORS-1)
    FLASH                   : origin = 0x10000, length = 0x1AE00
    // Interrupt Proxy table from  _App_Proxy_Vector_Start->(RESET-1)
    APP_PROXY_VECTORS       : origin = 0x5C00, length = 252
    // App reset from _App_Reset_Vector
    RESET                   : origin = 0x5CFC, length = 0x0002
}

/****************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY                              */
/****************************************************************************/

SECTIONS
{
    .bss        : {} > RAM                /* GLOBAL & STATIC VARS              */
    .data       : {} > RAM                /* GLOBAL & STATIC VARS              */
    .sysmem     : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
    .stack      : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */

    .text:_isr  : {}  > FLASH            /* Code ISRs                         */
	
    .text       : {} >> FLASH               /* CODE                 */

    .cinit      : {} > FLASH        /* INITIALIZATION TABLES*/ 

    .const      : {} >> FLASH       /* CONSTANT DATA        */ 


    .cio        : {} > RAM                /* C I/O BUFFER                      */
	
	.infoA     : {} > INFOA              /* MSP430 INFO FLASH Memory segments */
    .infoB     : {} > INFOB
    .infoC     : {} > INFOC
    .infoD     : {} > INFOD

    .APP_PROXY_VECTORS : {} > APP_PROXY_VECTORS /* INTERRUPT PROXY TABLE            */
    .reset       : {}               > RESET  /* MSP430 RESET VECTOR                 */
}

/****************************************************************************/
/* INCLUDE PERIPHERALS MEMORY MAP                                           */
/****************************************************************************/

-l msp430f5438a.cmd

/******************************************************************************/
/* LINKER COMMAND FILE FOR MSPBoot BOOTLOADER USING msp430f5529  */
/* File generated with MSPBootLinkerGen.pl on 06-22-2017 */
/*----------------------------------------------------------------------------*/


/****************************************************************************/
/* SPECIFY THE SYSTEM MEMORY MAP                                            */
/****************************************************************************/
/* The following definitions can be changed to customize the memory map for a different device
 *   or other adjustments
 *  Note that the changes should match the definitions used in MEMORY and SECTIONS
 *
 */
/* RAM Memory Addresses */
__RAM_Start = 0x1C00;                 /* RAM Start */
__RAM_End = 0x5BFF;                     /* RAM End */
    /* RAM shared between App and Bootloader, must be reserved */
    PassWd = 0x1C00;                 /* Password sent by App to force boot  mode */
    StatCtrl = 0x1C02;             /* Status and Control  byte used by Comm */

    /* Unreserved RAM used for Bootloader or App purposes */
    _NonReserved_RAM_Start = 0x1C03; /* Non-reserved RAM */

/* Flash memory addresses */
__Flash_Start = 0x2AE00;             /* Start of Application area */
   /* Reserved Flash locations for Bootloader Area */
    __Boot_Start = 0x5CFE;         /* Boot flash */
    __Boot_Reset = 0xFFFE;                          /* Boot reset vector */
    __Boot_VectorTable = 0xFF80;      /* Boot vector table */
    //__Boot_SharedCallbacks_Len = 6; /* Length of shared callbacks (2 calls =4B(msp430) or 8B(msp430x) */
    //__Boot_SharedCallbacks = 0xFF7A; /* Start of Shared callbacks */
    //_BOOT_APPVECTOR = __Boot_SharedCallbacks;       /* Definition for application table             */
    _Appl_Proxy_Vector_Start = 0x5C00; /* Proxy interrupt table */
    /* Reserved Flash locations for Application Area */
 
/* MEMORY definition, adjust based on definitions above */
MEMORY
{
    SFR                     : origin = 0x0000, length = 0x0010
    PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
    PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
    // RAM from _NonReserved_RAM_Start - __RAM_End
    RAM                     : origin = 0x1C03, length = 0x3FFC
	// Info Mem Sections
	INFOA                   : origin = 0x1980, length = 0x80
    INFOB                   : origin = 0x1900, length = 0x80
    INFOC                   : origin = 0x1880, length = 0x80
    INFOD                   : origin = 0x1800, length = 0x80
    // Flash from _App_Start -> (APP_PROXY_VECTORS-1)
    FLASH                   : origin = 0x2AE00, length = 0x1AE00
    // Interrupt Proxy table from  _App_Proxy_Vector_Start->(RESET-1)
    APP_PROXY_VECTORS       : origin = 0x5C00, length = 252
    // App reset from _App_Reset_Vector
    RESET                   : origin = 0x5CFC, length = 0x0002
}

/****************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY                              */
/****************************************************************************/

SECTIONS
{
    .bss        : {} > RAM                /* GLOBAL & STATIC VARS              */
    .data       : {} > RAM                /* GLOBAL & STATIC VARS              */
    .sysmem     : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
    .stack      : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */

    .text:_isr  : {}  > FLASH            /* Code ISRs                         */
	
    .text       : {} >> FLASH               /* CODE                 */

    .cinit      : {} > FLASH        /* INITIALIZATION TABLES*/ 

    .const      : {} >> FLASH       /* CONSTANT DATA        */ 


    .cio        : {} > RAM                /* C I/O BUFFER                      */
	
	.infoA     : {} > INFOA              /* MSP430 INFO FLASH Memory segments */
    .infoB     : {} > INFOB
    .infoC     : {} > INFOC
    .infoD     : {} > INFOD

    .APP_PROXY_VECTORS : {} > APP_PROXY_VECTORS /* INTERRUPT PROXY TABLE            */
    .reset       : {}               > RESET  /* MSP430 RESET VECTOR                 */
}

/****************************************************************************/
/* INCLUDE PERIPHERALS MEMORY MAP                                           */
/****************************************************************************/

-l msp430f5438a.cmd

  • Hello Ankit,

    The MSPBOOT document you found is going to be your best starting point here. There is also example code implementing MSPBOOT associated with it. There is also a tool/script provide to setup your linker files appropriately, but I'm unsure if handles two different app images. You will find this at the link below. You may also want to check out MSPFRBOOT as well. MSPFRBOOT was based off of MSPBOOT , but written for our FRAM devices. The reason I mention it as it has an "Over the Air Update" portion that I believe handles two different app images. That could be a guide for you here.

    http://www.ti.com/tool/MSPBSL
  • Hi Jace,

    Thanks for your reply. I am going through the examples.
    Can I ask you whether two applications can share the same proxy vectors area in the flash? Any potential problems?

    Thanks and Regards,
    Ankit
  • Hi Ankit,

    The general structure of your linker files look ok. Linker files are complex though and it's hard to tell if they are 100% correct without testing them. It looks like you generated these using the perl script provided with MSPBoot, so they'll at least work for the default MSPBoot setup.

    However, you're approach is a little different from the dual image MSPBoot scenario. From what I understand, you'd like to keep the old application in memory, undisturbed, after loading in the new application. When MSPBoot is used in dual image mode, the bootloader will load the new image into a temporary space, calculate the CRC and then move it into the application space. This effectively overwrites the old application but it ensures that the new application is valid before performing the overwrite. You'll need to modify MSPBoot's core functionality to achieve the behavior you want.

    Regarding the shared interrupt vector space. Unless App1 and App2 are using completely different interrupts, then they cannot share the same vector space. The proxy vector space is setup so that the addresses in the interrupt vector table can remain fixed. The interrupt vector table and the bootloader share the same flash memory segment, so updating these addresses would require moving bootloader code to RAM, executing from RAM, and then updating the interrupt vector addresses. This is dangerous and not recommended because a loss of power during this process would mean the bootloader is corrupted.

    A possible workaround is to have the interrupt vector table point to a proxy table (as it does already). Then have a separate temporary table that holds the old application's vectors. This would require the bootloader to move App1's vectors from the proxy table to the temporary table before updating the proxy table with App2's vectors. Then if you wanted to switch back to App1, you would have to swap the contents of the proxy and temporary tables.

    On a final note, 40KB is a lot of space to allocate to the bootloader. Is this really necessary? Also, if you have an external SPI flash, why not store the backup image on the external flash so you only have to store 1 image on the MSP430 at a time. This would give you more space for your application, avoid the shared vector space issue, and reduce the complexity of the solution.

    Best regards,
    Caleb Overbay
  • Hi Caleb,

    Thanks for the explanation.

    I like the answer suggested by you to use the separate temporary table. I will try it out.

    I won't be using 40KB. I am going to alott extra space to the apps and probably use 8KB for the Bootloader.

    Our system is safety critical. So we cannot just rely on the external SPI flash. We need safe mechanism which I feel can be achieved if we always have a copy of original firmware in the flash untouched and bootloader can just directly jump to it instead of flashing the original firmware from external SPI flash.


    Thanks and Regards,
    Ankit
  • Hi Caleb,

    What is the use of reset vector (pointing to 0xF7FE in the main memory bootloader example) in the application in the App when we know that actual reset vector (0xFFFE) is in Bootloader?

    I feel that there is no actual use of the reset vector in the application and it is added as a dummy.

    Thanks and Regards,

    Ankit

  • Hi Caleb,

    I understand the use of pplication reset vector. It's not a dummy but an address from where Bootloader will jump to application.
    I am facing another problem now. In debug mode, when I am trying to jump to address stored in application reset vector from bootloader, i am getting a reset and my control comes back to main of bootloader. I was hoping that in disassembly I can see the code going to application. What could be the problem?

    Thanks and Regards,
    Ankit
  • Ankit,

    For this situation with the reset, please look at the following wiki: processors.wiki.ti.com/.../Handling_MSP430_System_Reset_Events

    If you add some debug code at the beginning of your program, you can see what actually gave you your reset. This should help narrow down the issue.
  • Hi Jace,

    Thanks for the reply. I managed to fix the problem. It was a mismatch of proxy vector placement for one of the ISR which was causing the reset. I managed to fix it.

    I have another question for you and Caleb. Previously I had asked about sharing of the Vector table by two different apps (App1 and App2). I would like to ask it in a different way. Instead of using text:_isr section in the individual linker cmd files to include code for all the ISRs, can I individually define the section for each interrupt in the linker cmd files, and make sure they are in the same area of flash? In that way I will make sure that App1 and App2, both use the same ISR address (physical flash address) for a particular Interrupt. And Bootloader Interrupt Vector table just need to point to one proxy vector table (same for App1 and App2) and keep it constant; instead of copying different proxy vector tables for different Apps.

    Any problems and challenges you see in my implementation?

    Thanks and Regards,
    Ankit
  • Hello Ankit,

    Your idea sounds solid in theory to me, but I think you are in uncharted waters here. I can see some complications with this method, especially if you happen to make a typo somewhere in the referencing, but also potential maintenance of the program.
  • Hi Ankit,

    This approach would work if you never needed to make changes to the ISR code AND both App1 and App2 used the exact same ISR code. For instance, assume you're updating from App1 to a newer version with bug fixes in App2. One bug fix was a mistake in your PORT1_ISR. When App2 is downloaded to the device, it will effectively erase the old App1's PORT1_ISR.

    Now if the device needs to revert back to App1 for some reason (e.g. App2 corruption), you've already overwritten the old PORT1_ISR with the now possibly corrupt PORT1_ISR. To truly keep at least one clean and working image on the device you'll need to have two separate PORT1_ISR code instances as I described in my first approach using a temporary proxy vector table.

    Best regards,
    Caleb Overbay
  • Hi Jace and Caleb,

    Thanks for your reply. I understand now the possible problems in my approach and won't go forward with it.

    Caleb, I suppose in the approach you suggested, I have to change the flash content (Vector table), every time I need to switch from App1 to App2 and vice-versa. There is a possibility that flash corruption happens during writing to Vector Table and MSP430 gets stuck in bootloader and keep on trying to write and fail. Whereas const uint16_t Vector_Table[] means Vector table is fixed and cannot be changed.

    I was looking for an approach where we don't have to do any flash operation for switching to App1 and in case of any problem with App2, bootloader will safely jump to App2 (an untouched true copy). I think it is not possible and I have to think of some other design change.

    Thanks and Regards,
    Ankit

  • Hi Caleb,

    Is there a possibility that Interrupt Vector Table points to App1's Proxy Vector Table always, however when we switch to App2 then we use Vector redirection to RAM? In this case App1 uses the proxy vector table approach and no need to change flash. And App2 will use Vector redirection to RAM. Do you think it is a good approach?

    Thnaks and Regards,
    Ankit
  • Hi Ankit,

    The proxy vector table will always need to be used because the true hard-coded vector table always points to the proxy table. For your approach to work, you'd have to modify the true vector table when switching between applications which risks corruption of the bootloader.

    You could make both applications use vector redirection to RAM in order to avoid the need to write to flash when switching applications (i.e. place your proxy table in RAM). For example you could hard-code the true vector table to point to locations in RAM and then have each application load its own vectors into that location when the respective app starts. However, I believe the reset vector for an application would need to be present in the new RAM proxy vector table for the bootloader to be able to jump to the respective app. You'll have to store the reset address for each application somewhere so the bootloader could just jump to it directly without performing a reset.

    Best regards,
    Caleb Overbay
  • Thanks a lot Caleb :)

**Attention** This is a public forum