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.

Use Ram as an alternate location for interrupt vector locations

Other Parts Discussed in Thread: MSP430F5438, MSP430F5528

Hi,

In the MSP430F5438 User's Guide, it reads that  by one setting the SYSRIVECT bit in SYCTL, one can redirect the interrupt vector to RAM.

Is there sample code on this topic ?, I assume that at some point there needs to be data being copied from flash to RAM, then setting this bit.

Background:

I am doing a BSL code; the BSL boots first then gives control to the main application. This all would work just fine, except that the BSL uses the SPI bus and an interrupt, which is also used by the application code.

The objective of the BSL is to boot the uC, then if there is no request by the main processor to update the flash (via SPI commands) then jump to main application main() function, at this point all interrupts should be routed to the main application and not  to the BSL.

So, one solution is to have the interrupt vector of the main application in RAM, which is doable, but I am not very sure how to accomplish

Thanks for the help.

Erick

  • Hi Leo,

    Thank for your answer.

    can we do it this way:

      /* write inerrupt table in ram    */
      IntVecFlash_start_ptr = (uint8 *)__segment_begin("INTVEC");  /* INTVEC is defined in the file linkage  */
      IntVecFlash_end_ptr = (uint8 *)__segment_end("INTVEC");
      IntVecRam_start_ptr = (uint8 *)__segment_begin("INTRAMVECT");  /* INTRAMVEC is defined in the file linkage  */

      function_size = (uint16)(IntVecFlash_end_ptr) - (uint16)(IntVecFlash_start_ptr);

      memcpy(IntVecRam_start_ptr,IntVecFlash_start_ptr,function_size);

      /*    SYSCTL configuration    */
      SYSCTL = (uint16)(SYSCTL) | SYSRIVECT;

  • Hi Erick,

    if you are going to use the interrupt vector in RAM, you should not generate code which use the flash interrupt vector. Please refer to the example code once again. Basically you shall not use the pragma vector since it will assign the ISR address to the flash interrupt vector.

    The basic idea why it is possible to reallocate interrupt vector to RAM in my opinion is to enable BSL use interrupts but it shall not collide with the flash interrupt vector which is usually used by the application.

  • Hi Leo,
    I just came upon this post and have a follow-up question about the interrupt vector re-allocation example projects you mentioned above (posted on the MSP430 FAQ)

    http://processors.wiki.ti.com/index.php/MSP430_FAQ#Is_there_a_way_to_re-allocate_the_interrupt_vector_on_MSP430.3F

    I see that the CCS v5.x example, you note that we must set compile option: --code_model==small.  Based on the C/C++ Compiler User's Guide (slau132g) section 6.1.1,  setting this option forces 16-bit function pointers and limits code to the lowest 64kB of flash memory.  Can you help me understand why this option is necessary in this example, particularly when working with MSP430X devices?  Does using alternate interrupt vectors in RAM somehow limit compiled code size to 64kB?

    I understand that all ISRs must always reside in the lower 64kB, so that they are 16-bit addressable (this is true for MSP430X devices as well).  I think your code ensures that its ISR is in this region via the line:

    #pragma CODE_SECTION(TIMER1_A0_ISR, ".text:_isr")

    which places the ISR in the .text:_isr section of memory.  The example's custom linker file places the .text:_isr section in
    the FLASH region of memory, which is defined in the linker file as:

        FLASH                   : origin = 0x5C00, length = 0xA380
        
    This appears to ensure that the ISR remains in the lowest 64kB of flash.  Assuming that's correct, why is it also necessary to limit all code to the lowest 64kB (using compile option: --code_model==small)?  

    I'm developing using CCS 5.x for the MSP430F5528 (a MSP430 device with > 64kB of flash) and am considering using the alternate interrupt vector location in RAM with an application that is > 64kB.   How would I adapt your CCS code example to work in this scenario?

    Thanks for your help!

    Tom

  • Hi Tom,

    nice observation you have there.

    The reason why i think it is necessary to use the small code model is that the function pointer data type:

    // ISR function pointer variable type
    typedef void (*isr_type_t)(void);

    which is the data type used as the single entry in the interrupt vector table.

    I can't test it right now, but i believe if you use --code_model==small, the compiler will consider this is a 2 byte pointer, and using --code_model==large, it will be considered as 20 bit pointer.

    Anyway, if you don't mind, i would like to ask you why are you considering to use the RAM alternate interrupt vector for your application?

    The only reason why i would use the alternate interrupt vector is only for implementing custom BSL on the 5xx, so the interrupt vector of BSL and application will not collide with each other. Since the BSL also lies below the 64KB address, using --code_model==small also makes sense

    Hope this helps.

  • Hi Leo,
    Thanks for the quick reply.

    Would it be possible to avoid the small code size requirement by defining the ISR function cariable pointer type, as you did in the IAR version of the example project? (I'm not able to compile right now or I'd check)

       //typedef void (*isr_type_t)(void);
       typedef unsigned int  isr_type_t;

    I am considering how I might implement a custom BSL on the 5xxx, as you guessed.  My first choice would be to implement the bootloader in BSL flash, but it won't fit there, unfortunately.  A few other requirements for this project:
     - the bootloader must start first (before the main application) after a reset
     - the custom bootloader must be able to use interrupts
     - the additional interrupt latency introduced by a jumptable isn't acceptable

    Those requirements seemed to rule out many of the good solutions discussed on these forums.  Since the custom bootloader must start first after a reset, I decided that it should 'own' the default interrupt vector table in flash - I don't want the main application firmware to ever erase/modify the flash segment which contains the RESET vector & other interrupt vectors.  That thought process led me to the following potential solution:

    The bootloader would reside in the main flash region, most likely at the top of the first 64kB flash region, so that it could include the HW interrupt vector table (includes the RESET vector).   Upon startup, the RESET vector at 0xFFFE directs the code to start the bootloader.  The bootloader can use the flash interrupt vector table for its own interrupts, if necessary.  The main application’s interrupts can use the alternate RAM interrupt vector table -- when the bootloader is about to transfer control to the main application, it will set the SYSRIVECT bit in SYSCTL to cause the interrupt vectors to be remapped to the top of RAM.
     
    I don't love the idea of using the RAM interrupt table for the main application since its unprotected, but at the moment I don't see a better solution, given the requirements.

    -Tom

  • Hi Tom,

    Tom Olsen said:


    Would it be possible to avoid the small code size requirement by defining the ISR function cariable pointer type, as you did in the IAR version of the example project? (I'm not able to compile right now or I'd check)

       //typedef void (*isr_type_t)(void);
       typedef unsigned int  isr_type_t;

    Yes, i think this should be possible. Can't see what it shouldn't work. However just as you, i can't really test it now. So would be nice if you could post your test result later on here again to share with others.

    Tom Olsen said:

    Those requirements seemed to rule out many of the good solutions discussed on these forums.  Since the custom bootloader must start first after a reset, I decided that it should 'own' the default interrupt vector table in flash - I don't want the main application firmware to ever erase/modify the flash segment which contains the RESET vector & other interrupt vectors.  That thought process led me to the following potential solution:

    The bootloader would reside in the main flash region, most likely at the top of the first 64kB flash region, so that it could include the HW interrupt vector table (includes the RESET vector).   Upon startup, the RESET vector at 0xFFFE directs the code to start the bootloader.  The bootloader can use the flash interrupt vector table for its own interrupts, if necessary.  The main application’s interrupts can use the alternate RAM interrupt vector table -- when the bootloader is about to transfer control to the main application, it will set the SYSRIVECT bit in SYSCTL to cause the interrupt vectors to be remapped to the top of RAM.
     
    I don't love the idea of using the RAM interrupt table for the main application since its unprotected, but at the moment I don't see a better solution, given the requirements.

    You are right, this could be problematic. I personally have never implemented the full solution for this (just understand the concept). 

    However i might have an idea. How if you implement the full custom BSL code in the main flash memory, but you modify the BSL code inside the BSL flash to jump into the full BSL code in the main flash memory. This will solve the headache for having to set the 0xFFFE reset vector address to your custom BSL. I think this would be a better idea.

  • Hi Leo,

    Thanks for the suggestion about how to implement a bootloader, I like your idea.

    I also finally had an opportunity to try compiling your CCS RAM interrupt vector code example with a large memory model.  I changed the ISR function variable pointer type to the following:

    typedef unsigned int  isr_type_t;

    ...and then changed the code model to large in the project settings.  I also modified the definition of RAM memory slightly in the linker so that the stack and/or other variables wouldn't be placed in the same location as our interrupt vector table at the top of RAM.  The project compiles (using CCS 4.2) with some truncation and type mismatch warnings (2 warnings per ISR), since it recognizes that we are using 16 bits to hold what should be a 20-bit function pointer.  I stepped through the resulting program and it looks like the ISR addresses are being retrieved and used as expected, though, and it seems to me that the code executes w/no problems. 

  • Hi,

    in my MSP430F552x application I use an external SPI flash and I want periodically to save the last written address to the internal INFO flash. However, eventually I have to erase a FLASH segment , which causes the program to halt for 23-32ms according to the datasheet, since my code is executing from flash.

    However, I am simultaneously receiveing data in the UART, so the UART ISR needs to run every byte, i.e. around 70uS for 115200bps.

    The rest of the code is not very time critical, only the UART ISR is. So I am looking into either moving the interrupt table to ram along with the UART ISR, or alternatively move just the Flash erase function to RAM and inside it poll the UART IFG to receive new bytes instead of relying on the ISR.

    Obviously, the first choice is more elegant, however from what I have read, it requires constructing the vector table before copying to RAM.

    I was wondering if there is a way to just copy the whole vector table from flash to ram at runtime without having to know which vectors are non-empty. Also, the space at the top of the RAM has to be reserved, is there a way to declare a RAM variable and force its placement to the specific location? Moreover, the size of the vector table would need to be fetched without having to manually set it when changing MSP models.

    I am intrigued to look more into it, I would just like to know if there are any obvious problems with my line of thought.

    Thank you,

    Giannis

**Attention** This is a public forum