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

How to set interrupt priorities in CMSIS-RTOS RTX?

I have a question about the correct setting of the Cortex-M interrupt priorities in CMSIS-RTOS RTX. The CMSIS-RTX online manual (for the latest version 4.78) does not talk about this issue, and in fact, does not explain at all how to write ISRs for CMSIS-RTX.

Correct setting of the Cortex-M interrupt priorities is important, because the CMSIS-RTOS RTX kernel apparently does not disable interrupts explicitly. Instead, the atomic execution of critical sections is implemented as the SVC (Supervisor Call) exception, which runs at priority higher than any task.

Specifically, the priority of the SVC exception is set in the NVIC to the lowest possible level (0xFF), so is the priority of the PendSV and SysTick exceptions. With this setting, the exceptions cannot preempt each other, so their execution is mutually exclusive. So far so good.

But, what about the application-specific interrupts. It seems that they too need to be prioritized in the NVIC at the lowest level (0xFF), because any other setting would allow the IRQs to preempt the SVC/PendSV exceptions and could lead to corruption of the internal RTX state.

Is this observation accurate?

If so, then RTX would essentially defeat the purpose of the NVIC ("nested" interrupt controller), as the interrupts would NOT be allowed to nest.

Second, the CMSIS-RTX users must be made aware that they need to manually adjust the priorities of all their interrupts to 0xFF, by calling NVIC_SetPriority(<irq>_IRQn, 0xFFU) for all their interrupts. This is necessary, because all IRQs have priority 0 (the highest) out of reset, and with this setting they would be allowed to preempt RTX critical sections.

And finally, the whole design of CMSIS-RTOS RTX around the SVC exception makes most of the RTOS code execute in the exception context of the Cortex-M processor. This immensely hinders debugging, because you lose the call-stack context. In fact, the whole RTOS code feels like debugging a humongous ISR. This is exactly counter to the best practice to "keep your ISRs short".

Any comments about these issues would be highly appreciated.

Miro Samek
state-machine.com

Parents
  • In the CMSIS RTX source code(based on cortex-M3), the priority of SVC exception is not 0xFF. It depends on the priority group setting. The systick exception priority is 0x0. The PendSV exception priority is 0xFF.
    The source code is listed here:

    __inline static void rt_svc_init (void) {
    #if !defined(__TARGET_ARCH_6S_M)
      U32 sh,prigroup;
    #endif
      NVIC_SYS_PRI3 |= 0x00FF0000U;
    #if defined(__TARGET_ARCH_6S_M)
      NVIC_SYS_PRI2 |= (NVIC_SYS_PRI3<<(8+1)) & 0xFC000000U;
    #else
      sh       = 8U - __clz(~((NVIC_SYS_PRI3 << 8) & 0xFF000000U));
      prigroup = ((NVIC_AIR_CTRL >> 8) & 0x07U);
      if (prigroup >= sh) {
        sh = prigroup + 1U;
      }
      NVIC_SYS_PRI2 = ((0xFEFFFFFFU << sh) & 0xFF000000U) | (NVIC_SYS_PRI2 & 0x00FFFFFFU);
    #endif
    }
    
    
    
    
    

Reply
  • In the CMSIS RTX source code(based on cortex-M3), the priority of SVC exception is not 0xFF. It depends on the priority group setting. The systick exception priority is 0x0. The PendSV exception priority is 0xFF.
    The source code is listed here:

    __inline static void rt_svc_init (void) {
    #if !defined(__TARGET_ARCH_6S_M)
      U32 sh,prigroup;
    #endif
      NVIC_SYS_PRI3 |= 0x00FF0000U;
    #if defined(__TARGET_ARCH_6S_M)
      NVIC_SYS_PRI2 |= (NVIC_SYS_PRI3<<(8+1)) & 0xFC000000U;
    #else
      sh       = 8U - __clz(~((NVIC_SYS_PRI3 << 8) & 0xFF000000U));
      prigroup = ((NVIC_AIR_CTRL >> 8) & 0x07U);
      if (prigroup >= sh) {
        sh = prigroup + 1U;
      }
      NVIC_SYS_PRI2 = ((0xFEFFFFFFU << sh) & 0xFF000000U) | (NVIC_SYS_PRI2 & 0x00FFFFFFU);
    #endif
    }
    
    
    
    
    

Children
No data