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.

Application's interrupts don't work when bootloader calls the application

Other Parts Discussed in Thread: TMS570LS20216

Hello Ti Team,

I've got an issue where the symptom seems to be that when the bootloader calls the application, certain interrupts don't trigger. Could you please help direct
my debugging effort.

Basic setup

  • Processor: TMS570LS20216.
  • We've got a bootloader that can load code into flash through the UART with no issues. Both the upload and download functions work. Relevant functions from the F035 flash API are loaded and executed from RAM.
  • Bank:0 is reserved for the bootloader.
  • Banks:1, 2, & 3 are reserved for the application.
  • The bootloader always runs at power up and if the user doesn't want to use it, the application gets called after a timeout.

When do interrupts in the application work with no issues

  1. When loaded and run directly from CCS and,
  2. When all interrupts in the bootloader are turned off and the application called from the bootloader. So basically:
#define APP_BOOT_ADDRESS (0x00080000U)
bootloader_main()
{
#if 0 // def out everything. Just call the application.
...
...
#endif
       ((void (*)(void))APP_BOOT_ADDRESS)();
}

Other related setup description

Bootloader's linker file

MEMORY
{
VECTORS (RWX) : origin=0x00000000 length=0x00000020
FLASH (RX) : origin=0x00000020 length=0x001fffe0
STACKS (RW) : origin=0x08000000 length=0x00003500
RAM (RW) : origin=0x08003500 length=0x00024aFF
}

SECTIONS
{
.intvecs : {} > VECTORS
.flashapi : load = FLASH, run = RAM, LOAD_START(F035_LoadStart), LOAD_END(F035_LoadEnd), LOAD_SIZE(F035_LoadSize), RUN_START(F035_RunStart), RUN_END(F035_RunEnd), RUN_SIZE(F035_RunSize),
{
pf035a_api_eabi.lib (.text)
}
.text : {} > FLASH
.data : {} > RAM
.const : {} > FLASH
.cinit : {} > FLASH
.bss : {} > RAM
.stack : {} > STACKS
}

Bootloader's sys_intvecs.asm file

;-------------------------------------------------------------------------------
; sys_intvecs.asm
;
; (c) Texas Instruments 2009, All rights reserved.
;


;-------------------------------------------------------------------------------
; import reference for interrupt routines

.ref _c_int00
.ref _svc


;-------------------------------------------------------------------------------
; interrupt vectors

.sect ".intvecs"

b _c_int00
b #0x7FFF8
b #0x7FFF8
b #0x7FFF8
b #0x7FFF8
b #0x7FFF8
ldr pc,[pc,#-0x1b0]
ldr pc,[pc,#-0x1b0]

 

Application's linker file

MEMORY
{
VECTORS (X) : origin=0x00080000 length=0x00000020
FLASH (RX) : origin=0x00080020 length=0x0017FFE0
STACKS (RW) : origin=0x08000000 length=0x00001500
RAM (RW) : origin=0x08001500 length=0x00026B00
}

SECTIONS
{
.intvecs : {} > VECTORS
.text : {} > FLASH
.const : {} > FLASH
.cinit : {} > FLASH
.bss : {} > RAM
.data : {} > RAM
}

The interrupts I'am trying to work with

  • In the bootloader we're using four interrupts.
    • RTI 0 & 1

    • SCI RX interrupts for both the SCI ports.
  • The application uses RTI interrupts - 0 & 1 as well. These are the ones that don't seem to fire.

Thanks in advance!
Jude.

  • Hi Jude,
    What does your interrupt vector table look like for the application side? In order for the CPU to take an interrupt exception from the RTI on the application the below things need to happen:

    1. The RTI module needs to enable the corresponding compare interrupt? Please check if the interrupt is enabled. Did you at least see the interrupt flag set in the module.
    2. If #1 is done properly then the interrupt will go to the VIM module. In the VIM module the corresponding interrupt mask must be enabled for the RTI interrupt. Please check if the mask is properly set. Do you see the interrupt flag set in the VIM module.
    3. If #2 is done properly, the interrupt is generated to the CPU. In order for the CPU to take exception, the I bit in the CPSR must be clear to enable IRQ interrupt. Is the I bit clear?
    4. If CPU takes the exception it is going to fetch the corresponding ISR vector address using ldr pc, [pc, #-0x1B0]. This ISR address for RTI in application will be different from the ISR address for RTI in bootloader.

    If you place a breakpoint at 0x18 does the CPU stop when a RTI interrupt is generated?


    In your application did you update the VIM memory for the ISR vector addresses for the RTI?

    Below post may also provide you some insights on the bootloader/application interrupt handling.
    e2e.ti.com/.../994487
  • Hello Charles,

    Thanks for your quick response. I did read through the link you sent for ticket:994487. It appears that I could be running into the similar interrupt vector issue here.

    To answer your questions:
    (1) In the application, the RTI counter block 0 is configured and compare blocks 0 & 1 are configured for RTI timer interrupt generation. This works with no issues when the application is running without a bootloader in flash (i.e. application starts at 0x00)

    (2 & 3) As per #1, The interrupt mask is set correctly for the RTI module and I do see the relevant VIM flag set. Interrupts to the CPU are enabled by calling _enable_interrupts();



    Coming to your point (#4) regarding the ISR address for the RTI in the application and the bootloader have to be different. Could you please help me understand this is a bit please? because I think here is where the issue lies.

    Here is the application's current vector table for reference:

    ;-------------------------------------------------------------------------------
    ; sys_intvecs.asm
    ;
    ; (c) Texas Instruments 2009-2012, All rights reserved.
    ;

    .sect ".intvecs"


    ;-------------------------------------------------------------------------------
    ; import reference for interrupt routines

    .ref _c_int00


    ;-------------------------------------------------------------------------------
    ; interrupt vectors

    b _c_int00
    undefEntry
    b undefEntry
    svcEntry
    b svcEntry
    prefetchEntry
    b prefetchEntry
    dataEntry
    b dataEntry
    reservedEntry
    b reservedEntry
    ldr pc,[pc,#-0x1b0]
    ldr pc,[pc,#-0x1b0]


    ;-------------------------------------------------------------------------------
  • Charles,

    This is the snap short of the disassembly for the application's vector table:

    0007ffc4: FFFFFFFF .word 0xFFFFFFFF
    0007ffc8: FFFFFFFF .word 0xFFFFFFFF
    0007ffcc: FFFFFFFF .word 0xFFFFFFFF
    0007ffd0: FFFFFFFF .word 0xFFFFFFFF
    0007ffd4: FFFFFFFF .word 0xFFFFFFFF
    0007ffd8: FFFFFFFF .word 0xFFFFFFFF
    0007ffdc: FFFFFFFF .word 0xFFFFFFFF
    0007ffe0: FFFFFFFF .word 0xFFFFFFFF
    0007ffe4: FFFFFFFF .word 0xFFFFFFFF
    0007ffe8: FFFFFFFF .word 0xFFFFFFFF
    0007ffec: FFFFFFFF .word 0xFFFFFFFF
    0007fff0: FFFFFFFF .word 0xFFFFFFFF
    0007fff4: FFFFFFFF .word 0xFFFFFFFF
    0007fff8: FFFFFFFF .word 0xFFFFFFFF
    0007fffc: FFFFFFFF .word 0xFFFFFFFF
    00080000: EA005449 B 0x9512C
    00080004: EAFFFFFE B 0x80004
    00080008: EAFFFFFE B 0x80008
    0008000c: EAFFFFFE B 0x8000C
    00080010: EAFFFFFE B 0x80010
    00080014: EAFFFFFE B 0x80014
    00080018: E51FF1B0 LDR PC, 0x7FE70
    0008001c: E51FF1B0 LDR PC, 0x7FE74
    00080020: E92D400E STMFD R13!, {R1, R2, R3, R14}
    00080024: E3A0C000 MOV R12, #0
    ...
    ...


    Cheers,
    Jude.
  • Hi Jude,
    I don't see anything particularly wrong with the application vector table. What is going to happen is that once you are in application and you get a RTI interrupt, the CPU will take the IRQ exception at address 0x18. The CPU will execute ldr pc, [pc, #-0x1B0] to load the corresponding RTI ISR into the PC. Let's suppose you use compare 0 interrupt in the bootloader as well as in application. You need to have two different ISR vectors for the compare 0 interrupt when you are bootloader vs. when you are in application. The VIM RAM needs to be updated with the new RTI compare 0 interrupt when you jump from the bootloader to the application. This should be done as part of your application startup.
  • Hi Jude,
    One more thing for you to check is that before you jump from the bootloader to the application you need to make sure all the pending interrupt flags in the RTI and VIM are clear. Let's say if you use RTI in the bootloader and if it happens to set a compare0 flag and before you are able service it you have jumped to the application. The flags (both in RTI and VIM) remains pending left over from the bootloader. Now if you have the compare0 match in your application the VIM module is unable to detect this interrupt request since the flag was still pending from before. Not sure if this is the reason but worth checking again.
  • Hello Charles,

    Some feedback:

    • During startup of the bootloader and the application, the VIMRAM is populated with all the relevant ISR addresses. This population of the VIM RAM happens separately for the bootloader and the application (at startup of each).
    • I tried clearing all RTI interrupts before handing over control to the application. This unfortunately made no difference.
    • I also tried stopping the RTI counter block 0 before the application got called. No change here too.
    • Also tried switching to counter block 1 in the bootloader since counter block 0 is being used by the application, just to isolate the issue. No result here too. I wonder if this issue has anything to do with RTI interrupts at all (but that is just a guess at this point since the RTI interrupts run fine when the application is loaded at 0x00).

    I did some more digging and found a few things that looked odd:

    1. In the disassembly capture that I posted for the application, observe the instructions at 0x18 & 0x1c:
    1. 00080018: LDR PC, 0x7FE70      <=== 0x7FE70 is not a real address for the ISR ? Shouldn't this be 0xFFFF_FE70 ?
    2. 0008001C: LDR PC, 0x7FE74     <=== 0x7FE74 is not a real address for the ISR ? Shouldn't this be 0xFFFF_FE74 ?
    • I tried calling the application by issuing a software reset hoping that a software reset would clear any stale state from the bootloader, this also seems cleaner rather than calling the application directly as before. So instead of 
      #define APP_BOOT_ADDRESS (0x00080000U)
      ((void (*)(void))APP_BOOT_ADDRESS)();
      

      I used:

       SYSTEM_1->SYSECR = 0x8000U; /* Set Reset1=1 & Reset0=0 */ 

      This had a strange outcome as it loaded the bootloader and not the application. I'm I preforming a correct software reset ? Shouldn't the application be called given that "b 0x7FFF8" is the branch instruction ?

    Cheers,

    Jude.

  • Hi Jude,
    Once you are in application and if you get an interrupt the CPU will still go to 0x18 for the IRQ exception vector in the bootloader vector table. If you place a breakpoint at 0x18 do you see the CPU halted? So in theory, what you have at 0x0008018 shouldn't really matter. If the CPU does stop at 0x18 can you single step to see if the PC is loaded with the RTI ISR vector address intended for the RTI interrupt created by the application?

    Immediately after you jump to the application can you check if there is any pending interrupts for RTI in the VIM?

    Are you in Hardware vector mode using VIC port in bootloader and application?
  • Hello Charles,

    I got it going. The RTI timers now fire in the application with no issues. However, I'd like to answer your questions so as to have some continuity in the thread.

    (Q) If you place a breakpoint at 0x18 do you see the CPU halted?
    (A) While in the application, the CPU doesn't halt at 0x18 when an RTI or any other interrupt occurs. This seemed odd, so I reverted to running the bootloader
    and have a break point at 0x18 since the bootloader uses RTI timer interrupts as well. Even in the bootloader application, the CPU doesn't halt at 0x18 when a
    timer interrupt occurs. I can confirm from the disassembly that the address of the actual ISR is correctly loaded into the vim register IRQVECREG. The
    only explanation could be that hardware vectored interrupts are turned on, but I haven't found anything in the ASM code suggesting that. I will go back over it
    and look again.

    Why the RTI interrupts are now working
    Some feedback

    • There are no outstanding RTI interrupts when the application code gets called. I confirmed this using breakpoints at the point when the application started running (i.e. startup code for the application)
    • All other interrupts in the application work fine except for the RTI interrupts (i.e. SCI, NHET, DMA, etc..)

    Solution
    Stopping the counter block (reg:GCTRL) __and__ clearing the free running counter (reg:FRC) needs to be done in the bootloader just before the application is called. So essentially:-

    RTIGCTRL = 0;
    RTIFRC0  = 0;

    Just stopping the counter block is not sufficient. I looked in the TRM and couldn't find anything talking about resetting the FRC register.

    Would you have any ideas as to why the FRC register need to be reset for timer interrupts to work in the application code ?


    Cheers,
    Jude.

  • Hi Jude,
    I'm glad that your problem seems resolved.

    I don't know for sure why you must clear the free running counter to 0 in order for the RTI to work in application mode. I can only image if the compare value to be different between the application mode vs. bootloader mode. Perhaps, without first resetting the FRC, the FRC has already passed over your new compare value.

    Also the reason that the interrupt won't stop at 0x18 is because you use hardware VIC (Vectored Interrupt Controller). In hardware vectored mode the CPU does not take exception by going to 0x18 to fetch the ISR address but rather handshakes with the VIM module to obtain ISR vector address directly.
  • Hello Charles,

    The bootloader uses a compare value resulting in 1ms interrupts and the application uses a compare value resulting in 10us interrupt frequency. Why would the difference in the compare value cause an interrupt not to fire ? It might be true that the FRC has already passed over the new compare value.

    Would this be something to put in a TRM/Errata maybe ? Besides that, I think this ticket can be closed. Thanks much for helping me.

    Cheers,

    Jude.

  • Hi Jude,
    When you are in bootloader the compare will match every 1ms. The free running counter does not reset. It keeps incrementing. Each time a compare is matched, an interrupt is generated and at the same time the value stored in the update compare register (RTIUDCP) is added. So initially the compare value is 1ms, but the next compare value is 2ms and so. It is not the free running counter is reset after every compare match and the compare value stays at 1ms. Before you leave bootloader the FRC can very well already be a large value. Now you jump to the application code and reconfigure the compare value (RTICOMP) and update compare value (RTIUDCP) to 10us. The problem is that the FRC is already at a very high value and it will never match to a small compare value.

    If you think your question is answered can you please click the 'Verify Answer' button to close the thread? Thanks.