eclipse-threadx / threadx

Eclipse ThreadX is an advanced real-time operating system (RTOS) designed specifically for deeply embedded applications.
https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/threadx/index.md
MIT License
2.88k stars 784 forks source link

Cortex-M port: TX_PORT_USE_BASEPRI and TX_PORT_BASEPRI has no effect on assembly code #168

Closed udoe closed 2 years ago

udoe commented 2 years ago

Hi,

We have an application which is sensitive to ISR jitter. There is one highest prio IRQ which never must be disabled. Hence we configured the kernel to use BASEPRI instead of PRIMASK. But it looks like these macros are not taken into account in assembly code, specifically here: ports\cortex_m7\gnu\src\tx_thread_schedule.S There are CPSID and CPSIE instruction in this code.

I admit, the period where interrupts are locked out is very short but on an NXP i.MXRT MCU , for example, it could be extended significantly by an instruction cache miss while executing code directly from serial flash (XiP). Depending on the flash speed it can extend to more than 10us in this case (~1000 core cycles).

Unless everything is placed in ITCM, this port does not allow for deterministic response time of a critical IRQ. IMHO, an RTOS kernel should never lock out interrupts globally.

Regards, Udo

goldscott commented 2 years ago

Are you building the assembly code with those two symbols (-DTX_PORT_USE_BASEPRI -DTX_PORT_BASEPRI=N) defined on the command line or in your project assembly code options?

No BASEPRI is used in the scheduler for a couple reasons: (1) we decided to block interrupts using PRIMASK until after the scheduler is entered, (2) the WFI instruction is optional in the scheduler wait loop. WFI only works with PRIMASK, not BASEPRI.

I believe BASEPRI could be used around the execution entry and exit function calls (_tx_execution_thread_entry and _tx_execution_thread_exit).

udoe commented 2 years ago

I'm passing these symbols to assembly code and I verified that _tx_thread_interrupt_control, _tx_thread_interrupt_disable etc. indeed use BASEPRI instead of PRIMASK.

My concern is about _tx_thread_schedule which uses CPSID/CPSIE instructions regardless of the TX_PORT_USE_BASEPRI and TX_PORT_BASEPRI symbols. I understand that WFI would not resume when interrupts are masked via PRIMASK. To me the question is: Why are interrupts disabled at all while the CPU is suspended in WFI?

Other RTOS kernel designs (for Cortex M) I have seen consistently use BASEPRI to cut IRQ priority in half. There are two categories of IRQs:

The latter category can be used to implement time-critical, low-latency ISR services required for some hardware designs like ours.

One could argue that interrupt lockout periods in the scheduler are very short. But we learned recently that when the code executes from slow external memory devices then an I-cache miss can cause very long stalls. So the length of the interrupt lockout period is not deterministic. It's more deterministic if the scheduler code is placed in ITCM (where the critical ISR has to reside as well).

Having a guarantee that the kernel never disables interrupts from the critical category simplifies application design and code placement requirements.

Udo

goldscott commented 2 years ago

Hi Udo, I've been doing some more research on this topic and I agree with you - we can use BASEPRI in the scheduler. I'm going to make some updates to our code. Would you mind sending me an email at azure-rtos-support@microsoft.com so that I can send you these updates before we release them on github? Thanks!

goldscott commented 2 years ago

BASEPRI support has been added to Cortex-M schedulers, e.g. here: https://github.com/azure-rtos/threadx/blob/master/ports/cortex_m7/gnu/src/tx_thread_schedule.S