This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Is there ANY Cortex core that supports reentrant interrupts?

Note: This was originally posted on 28th February 2011 at http://forums.arm.com

For some (external to me) reason I am stuck with the Cortex but trying to find work around to my software issues with the lack of reentrant interrupts in CM3. Does CM4 support reentrancy? Or maybe CM0? Anything at all?
Please help!


  • Note: This was originally posted on 14th March 2011 at http://forums.arm.com

    Joseph, how exactly this example can be integrated into my code? What I am calling in my SysTick interrupt, where my re-entrant code goes?
    Sim's code I could understand easily but this one doesn't make any sense to me

  • Note: This was originally posted on 15th March 2011 at http://forums.arm.com

    Thanks Joseph! I really appreciate your help. Would it be too much if I asked for some code example? As I mentioned above I don't know M3 at its low level neither have any intention whatsoever to develop skills in it (it's a brain sick concept to me), but I really have to pull that single project with it. It is this little part only that interacts with NVIC that causes me so much headache.
    And unfortunately I NEED reentrancy in this particular case.
    Please!
  • Note: This was originally posted on 28th February 2011 at http://forums.arm.com

    Thanks Marcus. Yes I was referring to M3 and if you are right that actually gives me hope as I was comfortably using the ARM7's VIC with re-entrant interrupts. There was even an application note (from NXP, I think) that described that. So I am trying to find something similar for this poor new chip as well.
  • Note: This was originally posted on 6th March 2011 at http://forums.arm.com


    It is possible to use re-entrant interrupts on Cortex-M3/4 using the non-base-thread feature. You simply need to enable NONBASETHRDENA, and have the interrupt create a stack frame to run the body of the handler and perform a return using it,  thus removing the interrupt from the active list, and therefore lowering the core's priority such that the same interrupt can be taken again.

    hth
    s.



    Thank you Sim,
    I am not very familiar with this one. Would you be able to post a short example? Please?
  • Note: This was originally posted on 7th March 2011 at http://forums.arm.com

    Thank you very much! I will give it a shot
  • Note: This was originally posted on 7th March 2011 at http://forums.arm.com

    Sim, can you please help me out just a little bit more? I tried your example and it generates a HardFault exception after exiting my re-entrant function for the first time. Here is my test code which is basically a copy-paste of yours (I use Rowley Crossworks if that is of any importance). I've set the NONBASETHRDENA bit outside in my initialisation code: SCB_CCR|=SCB_CCR_NONBASETHRDENA;
    When I trace the exception occurs upon the execution of POP {PC}, which prompts my thoughts that the stack is maybe not right set up for the exit. However I really don't know and rely on your comments for this.
    Thank you!


    void SysCall(void) {

        LED^=1;  // just for the test

        __asm("thread_exit:");
        __asm("SVC 0");                 // return to handler mode
    }

    void SysTick_Handler(void) __attribute__ ((naked));
    void SysTick_Handler(void) {
        __asm("PUSH {r4,lr}");          // preserve EXC_RETURN (and SP align)
        __asm("LDR r0,=thread_exit");   // thread LR must generate an exit
        __asm("LDR r1,=SysCall");       // thread PC is our real handler
        __asm("LDR r2,=0x01000000");    // PSR for thread in Thumb-state
        __asm("PUSH {r0-r2}");          // create LR, PC and PSR
        __asm("SUB sp,sp,#(5*4)");      // allocate space for r0-r3 and r12
        __asm("LDR r0,=0xFFFFFFF9");    // thread using MSP return
        __asm("BX r0");                 // return to newly created thread
    }

    void SVC_Handler(void) __attribute__ ((naked));
    void SVC_Handler(void) {
        __asm("ADD sp,sp,#(9*4)");      // remove thread and r4 from stack
        __asm("POP {pc}");              // perform standard exception return
    }
  • Note: This was originally posted on 12th March 2011 at http://forums.arm.com

    Any little help, please? I really need it here...
  • Note: This was originally posted on 12th March 2011 at http://forums.arm.com


    Are Thread and Handler mode both using the Main stack pointer?

    s.


    That was my initial thought as well so I traced the code many times to make sure that only the main stack is in use. Unfortunately it's somewhere else where the error is hidden


  • Note: This was originally posted on 28th February 2011 at http://forums.arm.com

    Hi Marcus,

    Cortex-R and Cortex-A processors does not have NVIC. Users (SoC designers) using these processors can use the Generic Interrupt Controller (GIC) or they could use their own interrupt controller. In terms of the processor itself, these processors don't have the priority level management as in Cortex-M processors so a programmer can create reentrant interrupt as in ARM7TDMI.

    regards,
    Joseph
  • Note: This was originally posted on 14th March 2011 at http://forums.arm.com

    An example is here:
    http://books.google....0enable&f=false

    You need to add additional steps to modify the Systick active status in IPSR.
  • Note: This was originally posted on 15th March 2011 at http://forums.arm.com

    The example is for showing Non-base thread enable but isn't really intend to be using as reentrant exception.

    In the beginning of the SysTick handler, you need to use another higher priority exception (e.g. calling an SVC service 0 in the example, but make sure the priority of SVC is higher than your SysTick handler. Hardfault exception would be triggered otherwise.)

    After SVC return, switch off the active status of the SysTick exception. Now you should be able to trigger the SysTick exception again.

    In general I think (note: personal opinion here) it is best to avoid using reentrant of same exception.
    Since the SysTick exception can be a normal C function, you can just call it directly without trigger a exception.

    Alternative you could avoid reentrant code all together. Many OS has been developed for Cortex-M3 without the need to use reentrant of SysTick handler.
  • Note: This was originally posted on 16th March 2011 at http://forums.arm.com

    Hi there,

    Sorry I don't have any other example code for this, and at the moment my work load is really high so I can't spend time preparing such as example.
    From memory there has been other people trying this, and from distant memory someone did this without using non-base thread enable.
    (enter exception handler, modify stack frame and return address, exception return to thread which execute a different wrapper, execute the "real" exception handler in thread and carry out a normal function return to the interrupt program).

    I would suggest you to post on STM32 forum,
    (https://my.st.com/pu...2/AllItems.aspx)
    and TI Stellaris forum
    (http://e2e.ti.com/su...ller/f/471.aspx)
    and see if anyone happy to share their code.

    regards,
    Joseph
  • Note: This was originally posted on 28th February 2011 at http://forums.arm.com

    Presumably, you are talking about Cortex-M processors (v6-M, v7-M architectures). As far as your preferred interrupt mechanism is concerned, I am afraid you are out of luck with these.  All other Cortex-brand processors (v7-R, v7-A) come with essentially the same interrupt mechanism that ARM7 has, too.

    Regards
    Marcus
  • Note: This was originally posted on 2nd March 2011 at http://forums.arm.com

    It is possible to use re-entrant interrupts on Cortex-M3/4 using the non-base-thread feature. You simply need to enable NONBASETHRDENA, and have the interrupt create a stack frame to run the body of the handler and perform a return using it,  thus removing the interrupt from the active list, and therefore lowering the core's priority such that the same interrupt can be taken again.

    hth
    s.
  • Note: This was originally posted on 7th March 2011 at http://forums.arm.com

    This is a thought experiment rather than tested code, but you could try something like:

    int_handler
      PUSH {r4,lr}         ;// Preserve EXC_RETURN (and SP align)
      LDR r0,=thread_exit  ;// Thread LR must generate an exit
      LDR r1,=int_code     ;// Thread PC is our real handler
      LDR r2,=0x01000000   ;// PSR for thread in Thumb-state
      PUSH {r0-r2}         ;// Create LR, PC and PSR
      SUB sp,sp,#(5*4)     ;// Allocate space for r0-r3 and r12
      LDR r0,=0xFFFFFFF9   ;// Thread using MSP return
      BX r0                ;// Return to newly created thread

    svc_handler
      ADD sp,sp,#(9*4)     ;// Remove Thread and r4 from stack
      POP {pc}             ;// Perform standard exception return
     
    thread_exit
      SVC 0                ;// Return to handler mode

    int_code
      ....

    boot_code
      LDR r1,=0xE000ED14   ;// CCR register address
      LDR r0,[r1]
      ORR r0,r0,#1         ;// Enable NONBASETHRDENA
      STR r0,[r1]
      ....

    The short int_handler creates an exception stack frame for a new thread to actually run the re-entrant interrupt handler (int_code in the example).
    By returning, the int_handler automatically re-enables its interrupt for preemption, thus permitting re-entrancy.
    Exiting from the int_code routine requires entry back to handler mode (performed via setting the LR to point to an SVC in the example above), which then strips the thread from the stack frame, and returns as though the original interrupt handler would have done.
    Note that to make this behave properly, the handler used for exiting (SVCall in this case) needs to have the same or higher priority than the triggering interrupt.
    The example assumes that the source is a pulse interrupt, if this isn't the case, then int_handler would also need to clear the source before starting the thread.
    There are various other optimisations you could do, for example using the same interrupt for entry and exit by using software triggered interrupts etc.

    hth
    s.