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.

Creating a custom main-memory BSL for firmware update

Other Parts Discussed in Thread: MSP430FR5969, MSP430F5659

Hello Katie,
I also have same kind of requirement. I am using MSP430FR5969 and want to upgrade its firmware over ZigBee. I have gone through the SLAA600A.pdf document but handling of interrupt vector table for fram series is not understood properly, can you please elaborate more on this.

What I understand that there is no vector table for bootloader (if I use Simple Protocol Configuration). Is my understanding correct?

  • Hi Deep,

    The bootloader itself does not use interrupts at all. However, the bootloader does reside in the area adjacent to the interrupt vector table of the MSP device (interrupt table goes up to 0xFFFE the reset vector), so that the bootloader and vectors are all included in the same protected area that the bootloader will not write to. On FRAM devices, this area is additionally protected from accidental write using the MPU (memory protection unit) to prevent any unauthorized writes by the application.

    Now, you may be referring to section 2.2.4 Interrupt Vectors in FRAM Devices, in www.ti.com/lit/pdf/slaa600. This is talking about a difference in the MSP-BOOT implementation on FRAM parts vs FLASH parts.

    On FLASH devices, in the application area there are the interrupt vector ISR code, and a proxy interrupt vector table, since the application cannot use the normal interrupt vector table as this is included in the Boot Area which will never be erased by an application code update. (This is to keep bootloader protected and able to recover from a failed load for example - you need to preserve the reset vector at 0xFFFE pointing to the bootloader in particular, as well as the bootloader itself, and 0xFFFE is in the same segment as the rest of the interrupt vectors and would be erased if you tried to reprogram them). The Proxy table simply contains the address for each ISR, and the proxy table is fixed at a particular location. This way the actual device interrupt vector table, which resides in the boot area and so won't be overwritten when updating application code, can simply point to these fixed addresses in the proxy table and it will work no matter what application code is loaded as long as the application contains a proxy table at this address. It has to have fixed addresses, because the bootloader doesn't know what code you are going to load in or where the ISRs in that code are - this is why we have a proxy table in a fixed address as an in-between step to redirect the interrupt vectors.

    On FRAM devices, it's actually a lot easier. This is because of the difference in erase functions between FLASH and FRAM technology. For FLASH, the smallest erase that you can do is an entire segment, which is some number of bytes. On FRAM devices, however, there is no separate erase step required - you can simply write to any byte just like with RAM. This means that we can reprogram the actual vector table in the device (going up to 0xFFFE) without erasing the bootloader and without erasing the reset vector at 0xFFFE - so we can do it safely. Because of this, FRAM doesn't really need the proxy table or fixed addresses in the vector table, because it simply reprograms the actual vector table of the part. The way this is handled in the bootloader code, is that when you load application code that has a proxy table, the bootloader sees that the addresses you are programming are for the proxy table (since the proxy table has a fixed address). Then it takes these values and copies them directly into the actual device vector table instead (unlocking the MPU protection momentarily to do so, then re-protecting it). Because of this, when the main application code runs, the interrupt vectors jump straight to the ISRs like in a normal application that had no bootloader, meaning none of the extra jump overhead from vector redirection that you have in the Flash code.

    The best place to understand this FRAM vector handling, is to look at the example code that comes with MSP-BOOT for the FR5739, which is a similar device to the FR5969 and so should be fairly portable. http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPBoot/latest/index_FDS.html Look at FR5739_I2C\Src\MSPBoot\MI at the file TI_MSPBoot_MI_FRAM.c. In the function TI_MSPBoot_MI_WriteByte() you'll see that it does a check with an if statement to see if the address being written is part of the application vector table. If it is, then it writes it into the actual interrupt table at the end of FRAM as well.

    I hope this helps clear things up a bit. This FRAM implementation for vectors is not explained as fully in the application note, so I'll try to get it updated to include a bit more detail for future reference.

    Regards,

    Katie 

  • Hello Katie,


    Thank you for your explanation on vector rederection, very clear! We are also currently working on a main memory bootloader for the F5659 variant. We are wondering if you might eleborate on a few questions regarding the bootloader.

    - Is there prefferd location to initialize the clocks? In the bootloader or in the application itself?.

    - On our custom PCB design we have some devices (sensors, I2C devices) that are used in the application, should these devices be initialized in the bootloader or in the application?

    -When looking at the example of MSPBoot in the intterupt table  of the bootloader we see a UNUSED define, but this define is not included in the proxy table. Can you tell me why this define is needed?


    - We need to use large code model due to some external dependencies, but this gives truncation warnings in our proxy table. The entries are uint16_t, can we change this to uint32_t without any problems? And does the vector table of the bootloader then also need to be uint32_t?


    We hope you have the chance to answer our questions, many thanks in advance.

  • Hi John,

    On MSP430F5659 this is a flash device that features a Flash BSL (rather than a ROM one), so instead of MSP-BOOT you could write a custom BSL in this BSL Flash memory on this device per www.ti.com/lit/pdf/slaa450. However there is only 2kB of BSL Flash so it would depend on how complex your bootloader communication protocol is/how much room it needs, but if it will fit there typically we'd recommend that (MSP-BOOT was mostly written for devices without a customizable Flash BSL, or cases where you can't fit it in only 2kB). This is because then the BSL is in a separate special protected area of Flash different from main memory, and the BSL can be entered via the BSL hardware entry sequence on TEST/RST lines even if the rest of the part is blank (and you don't have to do any of this vector redirected.

    If you still need/want to use MSP-BOOT though:

    John Hunter78 said:
    - Is there prefferd location to initialize the clocks? In the bootloader or in the application itself?.

    The app note www.ti.com/lit/pdf/slaa600 shows that typically the clock init is done in main before it is decided to go to App or Boot. See Figure 2 on p. 6.

    John Hunter78 said:
    - On our custom PCB design we have some devices (sensors, I2C devices) that are used in the application, should these devices be initialized in the bootloader or in the application?

    If they are not needed for the actual boot loading of code (like sensors probably are not), I'd say initialize them in the application. But if something is needed in the bootloader to receive/load code/make some decision about loading code (I2C maybe if that's how you're loading code) then I'd initialize it in the bootloader (Figure 2 again - comm init after you enter Boot). But this is going to be your judgement call somewhat - if your board needs you to have I/O set a certain way to prevent other things in the system from getting damaged or something like that, you would want to initialize it no matter whether you run boot or app.

    John Hunter78 said:
    -When looking at the example of MSPBoot in the intterupt table  of the bootloader we see a UNUSED define, but this define is not included in the proxy table. Can you tell me why this define is needed?

    So looking at for example TI_MSPBoot_VecRed_G2x53.c at the Vector_Table[]:

    const uint16_t Vector_Table[] =
    #   endif
    {
    
        UNUSED,                                     // FFE0 = unused
        UNUSED,                                     // FFE2 = unused
        APP_PROXY_VECTOR(0),                        // FFE4 = P1
        APP_PROXY_VECTOR(1),                        // FFE6 = P2
        UNUSED,                                     // FFE8 = unused
        APP_PROXY_VECTOR(2),                        // FFEA = ADC10
        APP_PROXY_VECTOR(3),                        // FFEC = USCI I2C TX/RX
        APP_PROXY_VECTOR(4),                        // FFEE = USCI I2C STAT
        APP_PROXY_VECTOR(5),                        // FFF0 = TA0_1
        APP_PROXY_VECTOR(6),                        // FFF2 = TA0_0
        APP_PROXY_VECTOR(7),                        // FFF4 = WDT
        APP_PROXY_VECTOR(8),                        // FFF6 = COMP_A
        APP_PROXY_VECTOR(9),                        // FFF8 = TA1_1
        APP_PROXY_VECTOR(10),                        // FFFA = TA1_0
        APP_PROXY_VECTOR(11),                        // FFFC = NMI
    };

    Take a look at this table next to the table in the datasheet for this device, www.ti.com/lit/gpn/msp430g2553 Table 5 Interrupt Sources, Flags, and Vectors (p. 11). You can see that the table in the code is defining exactly the table in the datasheet at the addresses listed in the datasheet. Unused is for interrupt vectors in the part that are still reserved but are not used for any interrupt vector (0xFFE8 for example). This vector table is already implemented in the device, but what you are doing here is assigning fixed proxy table addresses to correspond to each of the hardware interrupt vectors. The Unused defines are there so that you don't have to waste space in the proxy table for vectors that don't exist in the device. See also TI_MSPBoot_Mgr_Vectors_G2553.c comments above where the ProxyVectorTable is defined, as this also says "unimplemented vectors are removed to save flash space". So you'll want to look at the datasheet for your F5659 device, find this device hardware vector table, and implement it accordingly in your own bootloader code.

    John Hunter78 said:
    - We need to use large code model due to some external dependencies, but this gives truncation warnings in our proxy table. The entries are uint16_t, can we change this to uint32_t without any problems? And does the vector table of the bootloader then also need to be uint32_t?

    The proxy table itself needs to be located at addresses in the lower memory so that it is 16-bit addresses. This is because the hardware vectors in the part (from the table above) are at specific addresses only 2-bytes apart (FFF2, FFF4, etc) - they are limited to only 16-bit entries for storing the addresses of the ISRs. So normally when you build a normal MSP430 project, the linker places all of your ISRs in lower memory so that they have 16-bit addresses so the vector table can store them. Now, with vector redirection, our hardware vector table in the bootloader, is pointing to fixed addresses for the proxy table - this means that the addresses of the proxy table entries themselves must be only 16-bit because this is what is being placed in the actual vector table of the part - so the proxy table itself has to reside in the lower memory so it has a 16-byte address. However, since you control the proxy table itself, I think you could define the structure of the proxy table to have 32-bit entries itself - your ISRs could be anywhere because of the redirection. So the proxy table entries could be 32-bit. The only potential problem I could see, is that, looking at TI_MSPBoot_Mgr_Vectors_G2553.c, you can see that there is also an entry before each ISR that is the branch instruction 0x4030. I'm honestly not 100% sure if we'd need to somehow change this to allow branch to a 32 bit address instead of 16, or if there's any special offset or anything, since you're essentially putting machine code in here to do the branch - would take some experimentation. Note you may also need to modify the linker file to adjust the space for the proxy vector table if you are making it longer by using larger 32-bit values.

    Regards,

    Katie

  • As an update, I talked to Luis who wrote the app note, and he pointed me to a couple of related threads:

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/367115/1290382#1290382

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/324839

    http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/385861/1364269#pi239031349=2

    You can also just leave it so that your ISRs are always in lower memory (only 16-bit addresses) and tell it to ignore the truncation warning, because you know that the app ISR addresses will be no greater than 16-bit in that case.

**Attention** This is a public forum