This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NVIC does not tail-chain to PendSV ISR

I'm trying to implement context switching from handler mode to thread mode using PendSV. I set the PendSV pending bit inside an ISR with SCB->ICSR = SCB->ICSR | SCB_ICSR_PENDSVSET_Msk. After setting the PendSV pending bit, I can see that the PendSV exception is pending: SCB->ICSR = 0x10000813 (I think the ISRPREEMPT bit should be set as well but it's not).

NVIC should tail-chain to my PendSV handler before unstacking. Instead ISR unstacking occurs, a return to exception is executed, and a few thread-level instructions are executed, before the PendSV handler is called.

The SoftDevice is present but has not been enabled.

Any ideas on what might be causing this? Thanks.

  • I am confused here, i tested this and also found that tail chaining is not happening not only with PendSV but with any interrupt... but this is a ARM Cortex feature right. You are writing directly to SCB block and not using any of the NRF features. I will have to look more into this tomorrow but I am not sure how much i should trust the debugger on this. Is there any other way you verify this without using debugger/breakpoints

  • Thanks, Aryan, for replicating the problem and responding here. I was wondering the same thing, if the debugger (I'm using GDB) is unable to monitor tail-chaining as it happens. I was thinking of setting a breakpoint in the PendSV handler, running to the breakpoint and comparing the stack to what I think it should be. Alternatively, I could try printing and comparing the value of the stack pointer (MSP) in both exception handlers. I'll let you know what I find.

  • There is tail chaining happening. Debugger breakpoints is just messing up the timings. I'll show you tomorrow how i verified, now im already home and typing on phone is not very effective.

  • I think you're right. I placed a while (true) continue in the first exception handler and this is what the stack looks like:

    0x2000fe90: 0x2000feb8  0xfffffff9  0x20007899  0x00000000
    0x2000fea0: 0x00000000  0x20007899  0x000007ff  0x000266bf
    0x2000feb0: 0x00026404  0x21000000  0x00000000  0x20007b40
    0x2000fec0: 0x00000000  0x00000000  0x20007bbc  0x0000eb04
    0x2000fed0: 0x00000001  0x00000000  0x0000eb04  0x00000001
    0x2000fee0: 0x20007b98  0x20007c3c  0x2000ff08  0x00024b0d
    0x2000fef0: 0x20007b98  0x00000000  0x20007898  0x20007899
    0x2000ff00: 0x00000001  0x00000002  0x00000000  0x20007798
    

    The two words at the top of the stack were pushed by the exception handler.

  • Then I rebuild the program and in the PendSV exception handler I PUSH {R0, LR} then call a function which also enters a while (true) loop. And the stack looks like this:

    0x2000fe88: 0x2000feb8  0x0002e10d  0x00000038  0xfffffff9
    0x2000fe98: 0x20007899  0x00000000  0x00000000  0x20007899
    0x2000fea8: 0x000007ff  0x000266bf  0x00026404  0x21000000
    0x2000feb8: 0x00000000  0x20007b40  0x00000000  0x00000000
    0x2000fec8: 0x20007bbc  0x0000eb04  0x00000001  0x00000000
    0x2000fed8: 0x0000eb04  0x00000001  0x20007b98  0x20007c3c
    0x2000fee8: 0x2000ff08  0x00024b0d  0x20007b98  0x00000000
    0x2000fef8: 0x20007898  0x20007899  0x00000001  0x00000002
    

    Now those two words at the top of the previous stack have been replaced by four words - 2 from the PendSV handler and 2 from my C function.

Related