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.

LP-MSP430FR2476: Interrupt Vector Table issue in BSL code

Part Number: LP-MSP430FR2476
Other Parts Discussed in Thread: MSP430FR2476

Hi Team,

I am working on BSL code and able to flash the code correctly on the same location of the memory(0x8004).But I have two applications and both the applications uses WDT so when running two applications it is problem.

Application1 is flashed at location 0x8004 and Application2 is flashed at location 0x81BE.
Also tried coding with dualimage example of MSP430FRBoot – Main Memory Bootloader and Over-the-Air Updates for MSP430Tm FRAM Large Memory Model Devices. No use as both the generated linker file has single vector table


Regards,
Pallavi

  • so when running two applications it is problem

    There is no way to running two applications or you use a RTOS to make them as two different tasks.

    No use as both the generated linker file has single vector table

    We have provide the python script tool to help you to generate the link files  that you  refer to it.

  • Hi Gary Gao,

    Thank you for replying,

    1.Ok i will try adding RTOS task.But Main Application to run for which i am trying this experiement has WDT.So i need WDT 

    2.Yes i have used the python script to generate the link file.That file has APPl_vector(only one vector table) so both the application 1 and 2 use the same vector table and points to same location of WDT_Vector.
    But i wanted app1 to point to WDT_Vector at one location of memory and app2 to point (WDT_Vector) another location of memory 

    Below is the files i am working on.Only required code is put on target and host
    4300.BSL.zip

    Regards,

    Pallavi

  • This is required because it is used for OTA update so one of the application is running and for the OTA update first we will receive the updated code and if in case the code is not verified or stops during updation,we have to go back to the application 1 and run it. Later on we can flash the updated firmware again

  • Sounds like a job for SYSRIVECT.

  • Hi David,

    yes i tried RAM Vector implemention

    referring this thread https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/399114/how-to-use-sysrivect-bit-in-register-sysctl



    since i have three seperate files i have created "vector_table.h" file in main file and application files.

    #ifndef VECTOR_TABLE_H_
    #define VECTOR_TABLE_H_

    extern void app1_WDT_ISR();
    extern void app2_WDT_ISR();


    #define RAM_MAX_ADRESS 0x1FFF
    #define MAP_VECTOR_BASE (RAM_MAX_ADRESS-1-RESET_VECTOR)
    #define NUM_VECTOR ( 1+( (RESET_VECTOR-RTC_VECTOR)>>1) )


    __interrupt void app1_WDT_ISR(void);
    __interrupt void app2_WDT_ISR(void);

    #endif /* VECTOR_TABLE_H_ */

    main.c

    #include "msp430.h"
    #include "TI_MSPBoot_Common.h"
    #include "TI_MSPBoot_CI.h"
    #include "TI_MSPBoot_MI.h"
    #include "TI_MSPBoot_AppMgr.h"
    #include "vector_table.h"


    // Local function prototypes


    void Software_Trim(); // Software Trim to get the best DCOFTRIM value
    #define MCLK_FREQ_MHZ 8 // MCLK = 8MHz

    static void clock_init(void);
    tBOOL TI_MSPBoot_AppMgr_AppisValid(void);


    char JmpToApp,jumpToApp2;
    unsigned char *addr = NULL;
    char app1_downloaded,app2_start,app2_end;

    //#pragma NOINIT unsigned int MAP_VECTOR[ NUM_VECTOR ]@MAP_VECTOR_BASE


    __no_init unsigned int MAP_VECTOR[ NUM_VECTOR ]@MAP_VECTOR_BASE;
    /******************************************************************************
    *
    * @brief Main function
    * - Initializes the MCU
    * - Selects whether to run application or bootloader
    * - If bootloader:
    * - Initializes the peripheral interface
    * - Waits for a command
    * - Sends the corresponding response
    * - If application:
    * - Jump to application
    *
    * @return none
    *****************************************************************************/
    void main_boot(void)
    {

    WDTCTL = WDTPW + WDTHOLD;


    PM5CTL0 &= ~LOCKLPM5;
    clock_init();
    __bis_SR_register(GIE);

    P4DIR |= BIT7;
    P4OUT |= BIT7;
    __delay_cycles(5000);
    P4OUT &= ~BIT7;


    MAP_VECTOR[(WDT_VECTOR - RTC_VECTOR) / 2] = app1_WDT_ISR;
    MAP_VECTOR[(WDT_VECTOR - RTC_VECTOR) / 2] = app2_WDT_ISR;

    SYSCTL |= SYSRIVECT;

    addr = (unsigned char*) 0x1804;
    JmpToApp = *addr;

    //if ((*JmpToApp) == 1)
    if (JmpToApp == 1)
    {
    __disable_interrupt();
    ((void (*)()) 0x8004)();
    }

    if(JmpToApp == 2)
    {
    //jumpToApp2 = 0;
    __disable_interrupt();
    ((void (*)()) 0x81BE)();
    }
    // Validate the application and jump if needed
    if (TI_MSPBoot_AppMgr_ValidateApp() == TRUE_t)
    {
    __no_operation();
    TI_MSPBoot_APPMGR_JUMPTOAPP();
    }


    TI_MSPBoot_CI_Init(); // Initialize the Communication Interface

    while (1)
    {

    // Poll PHY and Data Link interface for new packets
    TI_MSPBoot_CI_PHYDL_Poll();

    if (app1_downloaded == 1 && app2_start == 1 && app2_end == 0)
    {
    __disable_interrupt();
    ((void (*)()) 0x8004)();
    }


    // If a new packet is detected, process it
    if (TI_MSPBoot_CI_Process() == RET_JUMP_TO_APP)
    {

    // If Packet indicates a jump to App
    //*JmpToApp = 1;

    //JmpToApp = 1;

    if (app1_downloaded == 1)
    {
    addr = (unsigned char*) 0x1804;
    SYSCFG0 = FRWPPW | PFWP;
    *addr = 2;
    SYSCFG0 = FRWPPW | DFWP | PFWP;
    }
    else if (app1_downloaded != 1)
    {
    addr = (unsigned char*) 0x1804;
    SYSCFG0 = FRWPPW | PFWP;
    *addr = 1;
    SYSCFG0 = FRWPPW | DFWP | PFWP;
    }

    app1_downloaded = 1;
    TI_MSPBoot_AppMgr_JumpToApp();

    }


    #ifdef NDEBUG
    // Feed the dog every ~1000ms
    WATCHDOG_FEED();
    #endif
    }

    }


    Error:

    tried noint also but same error comes up. I don't know hat is MAP_Vector here

    Regards,

    Pallavi

  • I have no idea what that mess is supposed to do but what you need is simple.

    At reset the vectors are in the usual location and will have been set when the bootloader code was programmed. It will do whatever it needs to do then jump to an application.

    The application will have its initial stack location offset below the area used by the SRAM vector table by its customized linker script. It will set whichever vectors it needs, then set SYSRIVECT.

    The boot loader need have no clue what the applications are doing. Which is good.

  • Do i need to change the linker file (Appl_Vector location)for the application code 

    Or should i create vector table in app2 and place it some memory location and point WDT to it. If Yes how to create it 

  • You could have the application create vector table entries as usual and have the boot loader deal with them. Assuming that whatever is talking to the boot loader sends the vectors.

    Or have the application write them during initialization. As in write the address of the ISR to a specific address. If you only have the one ISR, this is probably easiest.

    Of course, being an FRAM part you can write to the normal vector table location almost as easily as to SRAM. The only tricky part being to disable any memory protection.

  • Hi David,

    Thank you for the reply,

    I have used 2nd method of writing application during initialization

    #include <msp430.h>
    #include <stdint.h>
    #include "TI_MSPBoot_Mgr_Vectors.h"
    // Define the WDT ISR
    #pragma vector = WDT_VECTOR
    __interrupt void app2_WDT_ISR(void)
    {
    P4OUT ^= BIT7; // Toggle LED1 in P1.0
    }

    int main()
    {
    WDTCTL = WDT_ADLY_1000;
    SFRIE1 |= WDTIE;

    // *(volatile uint16_t *)(0xfa96) = (uint16_t)app2_WDT_ISR;

    *(volatile uintptr_t *)(0xf3a4) = (uintptr_t)app2_WDT_ISR;


    P1DIR |= BIT0;
    P1OUT |= BIT0;

    PM5CTL0 &= ~LOCKLPM5;

    __delay_cycles(500000);
    P1OUT &= ~BIT0;
    __delay_cycles(500000);
    P1OUT |= BIT0;
    __delay_cycles(500000);
    P1OUT &= ~BIT0;

    // Configure P2.3 (S2 button) as interrupt with pull-up
    P2DIR &= ~BIT3;
    P2REN |= BIT3;
    P2IES |= BIT3;
    P2IFG &= ~BIT3;
    P2IE |= BIT3;

    __bis_SR_register(GIE);

    while (1)
    {
    __no_operation();
    }
    }


    #pragma vector = PORT2_VECTOR
    __interrupt void Port2_Isr(void)
    {
    P2IFG &= ~BIT3; // Clear the interrupt flag
    TI_MSPBoot_JumpToBoot(); // Jump to bootloader (assuming this function exists)
    }

    I didnot get the WDT interrupt.But application code entered properly with P1.0 on and off initially.

    Is this the way to initialize ISR to specific address? i have searched it online 

  • Possibly. I have never tried to do it in C, only assembly. But I can see that you didn't use the correct address. The vectors run from 0xff80 to 0xffff, inclusive. Well, kind of. The beginning of that space is used for other things.

    Looking at the linker script, I see the WDT is VECT32 which is at 0xffe2.

  • All the above questions were about this itself that there are two WDT and one memory, both are pointing to same location so only one code can be fit in and not the other one. WDT of application 1 and 2 are VECT32 so i wanted to change the address of one application so that both the program fit in the memory and check for app2 errors.once error free run the app2.if errors present then run app1.

    I tried searching for syntax for initializing WDT_VECTOR to different address.since the vector stored in ROM cannot add another location in that so  tried implementing RAM VECTOR but there are errors.

    i didnot get the proper way of initializing it.please help me initialize two WDT interrupt. Both WDT ISR  will be stored in the memory but based on some conditions only one will execute at a time. Want this syntax in C for CCS

    As you see in the linker file vectors run from F3A2 right so i have assigned F3A4 as the address.

    /* RAM Memory Addresses */
    __RAM_Start = 0x2000; /* RAM Start */
    __RAM_End = 0x3fff; /* RAM End */
    /* RAM shared between App and Bootloader, must be reserved */
    PassWd = 0x2000; /* Password sent by App to force boot mode */
    StatCtrl = 0x2002; /* Status and Control byte used by Comm */
    CI_State_Machine = 0x2003; /* State machine variable used by Comm */
    CI_Callback_ptr = 0x2004; /* Pointer to Comm callback structure */
    /* Unreserved RAM used for Bootloader or App purposes */
    _NonReserved_RAM_Start = 0x2008; /* Non-reserved RAM */

    /* Flash memory addresses */
    __Flash_Start = 0x8000; /* Start of Application area */
    /* Reserved Flash locations for Bootloader Area */
    __Boot_Start = 0xf400; /* Boot flash */
    __Boot_Reset = 0xFFFE; /* Boot reset vector */
    __Boot_VectorTable = 0xFFA2; /* Boot vector table */
    __Boot_SharedCallbacks_Len = 0x10; /* Length of shared callbacks (2 calls =4B(msp430) or 8B(msp430x) */
    __Boot_SharedCallbacks = 0xff70; /* Start of Shared callbacks */
    _BOOT_APPVECTOR = __Boot_SharedCallbacks; /* Definition for application table */
    _Appl_Vector_Start = 0xf3a2; /* 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 = 0x2008, length = 0x1ff8
    // Flash from _App_Start -> (APP_VECTORS-1)
    FLASH : origin = 0x8003, length = 0x739f
    FLASH2 : origin = 0x10000, length = 0x8000
    // Interrupt table from _App_Vector_Start->(RESET-1)
    INT00 : origin = 0xf3a2, length = 0x0002
    INT01 : origin = 0xf3a4, length = 0x0002
    INT02 : origin = 0xf3a6, length = 0x0002
    INT03 : origin = 0xf3a8, length = 0x0002
    INT04 : origin = 0xf3aa, length = 0x0002
    INT05 : origin = 0xf3ac, length = 0x0002
    INT06 : origin = 0xf3ae, length = 0x0002
    INT07 : origin = 0xf3b0, length = 0x0002
    INT08 : origin = 0xf3b2, length = 0x0002
    INT09 : origin = 0xf3b4, length = 0x0002
    INT10 : origin = 0xf3b6, length = 0x0002
    INT11 : origin = 0xf3b8, length = 0x0002
    INT12 : origin = 0xf3ba, length = 0x0002
    INT13 : origin = 0xf3bc, length = 0x0002
    INT14 : origin = 0xf3be, length = 0x0002
    INT15 : origin = 0xf3c0, length = 0x0002
    INT16 : origin = 0xf3c2, length = 0x0002
    INT17 : origin = 0xf3c4, length = 0x0002
    INT18 : origin = 0xf3c6, length = 0x0002
    INT19 : origin = 0xf3c8, length = 0x0002
    INT20 : origin = 0xf3ca, length = 0x0002
    INT21 : origin = 0xf3cc, length = 0x0002
    INT22 : origin = 0xf3ce, length = 0x0002
    INT23 : origin = 0xf3d0, length = 0x0002
    INT24 : origin = 0xf3d2, length = 0x0002
    INT25 : origin = 0xf3d4, length = 0x0002
    INT26 : origin = 0xf3d6, length = 0x0002
    INT27 : origin = 0xf3d8, length = 0x0002
    INT28 : origin = 0xf3da, length = 0x0002
    INT29 : origin = 0xf3dc, length = 0x0002
    INT30 : origin = 0xf3de, length = 0x0002
    INT31 : origin = 0xf3e0, length = 0x0002
    INT32 : origin = 0xf3e2, length = 0x0002
    INT33 : origin = 0xf3e4, length = 0x0002
    INT34 : origin = 0xf3e6, length = 0x0002
    INT35 : origin = 0xf3e8, length = 0x0002
    INT36 : origin = 0xf3ea, length = 0x0002
    INT37 : origin = 0xf3ec, length = 0x0002
    INT38 : origin = 0xf3ee, length = 0x0002
    INT39 : origin = 0xf3f0, length = 0x0002
    INT40 : origin = 0xf3f2, length = 0x0002
    INT41 : origin = 0xf3f4, length = 0x0002
    INT42 : origin = 0xf3f6, length = 0x0002
    INT43 : origin = 0xf3f8, length = 0x0002
    INT44 : origin = 0xf3fa, length = 0x0002
    INT45 : origin = 0xf3fc, length = 0x0002

    // App reset from _App_Reset_Vector
    RESET : origin = 0xf3fe, 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 */
    #ifndef __LARGE_DATA_MODEL__
    .text : {} >> FLASH /* CODE */
    #else
    .text : {} >> FLASH | FLASH2 /* CODE */
    #endif
    .cinit : {} > FLASH /* INITIALIZATION TABLES*/
    #ifndef __LARGE_DATA_MODEL__
    .const : {} >> FLASH /* CONSTANT DATA */
    #else
    .const : {} >> FLASH2 | FLASH /* CONSTANT DATA */
    #endif

    .cio : {} > RAM /* C I/O BUFFER */

    /* MSP430 INTERRUPT VECTORS */
    .int00 : {} > INT00
    .int01 : {} > INT01
    .int02 : {} > INT02
    .int03 : {} > INT03
    .int04 : {} > INT04
    .int05 : {} > INT05
    .int06 : {} > INT06
    .int07 : {} > INT07
    .int08 : {} > INT08
    .int09 : {} > INT09
    .int10 : {} > INT10
    .int11 : {} > INT11
    .int12 : {} > INT12
    .int13 : {} > INT13
    .int14 : {} > INT14
    .int15 : {} > INT15
    .int16 : {} > INT16
    .int17 : {} > INT17
    .int18 : {} > INT18
    .int19 : {} > INT19
    ECOMP0 : { * ( .int20 ) } > INT20 type = VECT_INIT
    PORT6 : { * ( .int21 ) } > INT21 type = VECT_INIT
    PORT5 : { * ( .int22 ) } > INT22 type = VECT_INIT
    PORT4 : { * ( .int23 ) } > INT23 type = VECT_INIT
    PORT3 : { * ( .int24 ) } > INT24 type = VECT_INIT
    PORT2 : { * ( .int25 ) } > INT25 type = VECT_INIT
    PORT1 : { * ( .int26 ) } > INT26 type = VECT_INIT
    ADC : { * ( .int27 ) } > INT27 type = VECT_INIT
    EUSCI_B1 : { * ( .int28 ) } > INT28 type = VECT_INIT
    EUSCI_B0 : { * ( .int29 ) } > INT29 type = VECT_INIT
    EUSCI_A1 : { * ( .int30 ) } > INT30 type = VECT_INIT
    EUSCI_A0 : { * ( .int31 ) } > INT31 type = VECT_INIT
    WDT : { * ( .int32 ) } > INT32 type = VECT_INIT


    RTC : { * ( .int33 ) } > INT33 type = VECT_INIT
    TIMER0_B1 : { * ( .int34 ) } > INT34 type = VECT_INIT
    TIMER0_B0 : { * ( .int35 ) } > INT35 type = VECT_INIT
    TIMER3_A1 : { * ( .int36 ) } > INT36 type = VECT_INIT
    TIMER3_A0 : { * ( .int37 ) } > INT37 type = VECT_INIT
    TIMER2_A1 : { * ( .int38 ) } > INT38 type = VECT_INIT
    TIMER2_A0 : { * ( .int39 ) } > INT39 type = VECT_INIT
    TIMER1_A1 : { * ( .int40 ) } > INT40 type = VECT_INIT
    TIMER1_A0 : { * ( .int41 ) } > INT41 type = VECT_INIT
    TIMER0_A1 : { * ( .int42 ) } > INT42 type = VECT_INIT
    TIMER0_A0 : { * ( .int43 ) } > INT43 type = VECT_INIT
    UNMI : { * ( .int44 ) } > INT44 type = VECT_INIT
    SYSNMI : { * ( .int45 ) } > INT45 type = VECT_INIT

    .reset : {} > RESET /* MSP430 RESET VECTOR */
    }

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

    -l msp430fr2476.cmd

  • You appear to be saying that you have two different bits of ISR code and you want the CPU to choose one. It can't. You can change the vector to point at the code you want to run but that is it.

    Or perhaps you are trying to multitask in some odd way.

    As for the vector table, that particular code may be storing a vector table at 0xf3a2 but the CPU doesn't care. Your program will have to copy it from that location to where the CPU is expecting it. Either in the default location at the top of low FRAM, or to the top of SRAM. Depending on what you do with SYSRIVECT.

  • You can change the vector to point at the code you want to run but that is it.

    Yes. How can i do it. Both are stored and i want on condition the vector to point to that code

  • I think you can enable the SRAM interrupt table, for this device support remapping interrupt vectors into the end area of the RAM by setting the SYSRIVECT bit in the SYSCTL register. You can load the interrupt table as needed into end of the SRAM to make it as active interrupt table.

  • What condition?

    The usual thing with boot loaders is that there is a single application. Easy enough. But you appear to have two. So whichever one is running and requires the WDT needs to capture the vector. How you do that is up to you since it depends critically one your code and your requirements.

    Too complicated for my tastes.

**Attention** This is a public forum