2024-09-10 10:11 AM
I use ThreadX (in addition to other X series middlewares) on nearly all of my projects. I have been in the habit of adding calls to _tx_thread_context_save/restore in all interrupt handlers inside stm32<xx>xx_it.c, per the guidance in ThreadX documentation.
Today I was reworking an old project and pulled up the assembly for _tx_thread_context_save to see a note that states:
/* DESCRIPTION */
/* */
/* This function is not needed for Cortex-M. */
Referencing https://community.st.com/t5/stm32-mcus/part-1-how-to-create-a-threadx-low-power-project-from-scratch/ta-p/571446, I see no step outlined to add the calls for context save/restore. I've read various Issues on the official ThreadX github account and the old Microsoft Azure ThreadX Q&A board that go back and forth on whether these calls are necessary or recommended (https://github.com/eclipse-threadx/threadx/issues/381 , https://learn.microsoft.com/en-us/answers/questions/994826/azure-rtos-execution-profile-kit-with-stm32u5-b-u5). I've also found threads here on the ST forums that do the same (https://community.st.com/t5/stm32-mcus-embedded-software/mx-generated-code-for-irq-handlers-doesn-t-address-threadx/td-p/718368).
So, what's the consensus on these context save/restore calls? I most often develop on STM32U5 and H7 series, if that makes any difference, though at my organization, any family is possible depending on the project.
Solved! Go to Solution.
2024-09-10 01:49 PM
Turns out I just needed to reread the assembly. These functions do actually do something, IFF you have certain ThreadX parameters defined, namely TX_ENABLE_EXECUTION_CHANGE_NOTIFY or TX_EXECUTION_PROFILE_ENABLE. The assembly for _tx_thread_context_save is below -- note that without either of these options set, this assembly functions simply jumps to the IRQ handler from which it was called without doing anything. I searched my project and can confirm _tx_execution_isr_enter is not a defined symbol, no assembly function present. Not sure if this is different on different chipsets, but this is how it is for the STM32U5 port.
So for anyone else who encounters this same question, these save/restore function calls are necessary IFF you have defined TX_ENABLE_EXECUTION_CHANGE_NOTIFY or TX_EXECUTION_PROFILE_ENABLE. Otherwise, you can leave these calls out of your IRQ handlers to no ill effect... unless you want an extra unconditional branch statement executed in your interrupt handler, for some reason.
// VOID _tx_thread_context_save(VOID)
// {
.section .text
.balign 4
.syntax unified
.eabi_attribute Tag_ABI_align_preserved, 1
.global _tx_thread_context_save
.thumb_func
.type _tx_thread_context_save, function
_tx_thread_context_save:
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
BX lr
// }
.end
2024-09-10 01:09 PM - edited 2024-09-10 01:31 PM
In a certain city, they decided to pave the square with stone tiles. One architect suggested that the tiles should be polished. Another architect insisted that the tiles should be rough. The mayor of the city resolved their dispute in a way that satisfied both: the tiles should be polished, but laid with the polished side down.
In spirit of this old anecdote, you can dutifully place the save/restore functions (macros) - but define them as no-ops. Unless you want to use these functions for measuring time etc.
2024-09-10 01:49 PM
Turns out I just needed to reread the assembly. These functions do actually do something, IFF you have certain ThreadX parameters defined, namely TX_ENABLE_EXECUTION_CHANGE_NOTIFY or TX_EXECUTION_PROFILE_ENABLE. The assembly for _tx_thread_context_save is below -- note that without either of these options set, this assembly functions simply jumps to the IRQ handler from which it was called without doing anything. I searched my project and can confirm _tx_execution_isr_enter is not a defined symbol, no assembly function present. Not sure if this is different on different chipsets, but this is how it is for the STM32U5 port.
So for anyone else who encounters this same question, these save/restore function calls are necessary IFF you have defined TX_ENABLE_EXECUTION_CHANGE_NOTIFY or TX_EXECUTION_PROFILE_ENABLE. Otherwise, you can leave these calls out of your IRQ handlers to no ill effect... unless you want an extra unconditional branch statement executed in your interrupt handler, for some reason.
// VOID _tx_thread_context_save(VOID)
// {
.section .text
.balign 4
.syntax unified
.eabi_attribute Tag_ABI_align_preserved, 1
.global _tx_thread_context_save
.thumb_func
.type _tx_thread_context_save, function
_tx_thread_context_save:
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
BX lr
// }
.end