问题描述
我一直在玩azure-rtos(THREADX),并尝试为基于cortex R5的系统移植OS。查看端口文件后,似乎OS会在Supervisor(SVC)模式下运行线程。
例如,在函数_tx_thread_stack_build
中,在为线程构建堆栈时,CPSR
的初始化值使得模式位对应于SVC模式。此初始化值随后将用于初始化CPSR,然后跳转到线程输入功能。
以下是函数_tx_thread_stack_build
的代码片段,该函数在线程堆栈上存储CPSR的初始化值。供您参考,请参见文件tx_thread_stack_build.S。
.global _tx_thread_stack_build
.type _tx_thread_stack_build,function
_tx_thread_stack_build:
@ Stack Bottom: (higher memory address) */
@
...
MRS r1,CPSR @ Pickup CPSR
BIC r1,r1,#CPSR_MASK @ Mask mode bits of CPSR
ORR r3,#SVC_MODE @ Build CPSR,SVC mode,interrupts enabled
STR r3,[r2,#4] @ Store initial CPSR
...
再举一个例子,函数tx_thread_context_restore.S
从IRQ模式切换到SVC模式以保存线程被切出的上下文,这表明OS在这里假定线程正在以SVC模式运行。供您参考,请参见文件tx_thread_context_restore.s
以下是摘录的线程的函数保存上下文的摘要。
LDMIA sp!,{r3,r10,r12,lr} ; Recover temporarily saved registers
MOV r1,lr ; Save lr (point of interrupt)
MOV r2,#SVC_MODE ; Build SVC mode CPSR
MSR CPSR_c,r2 ; Enter SVC mode
STR r1,[sp,#-4]! ; Save point of interrupt
STMDB sp!,{r4-r12,lr} ; Save upper half of registers
MOV r4,r3 ; Save SPSR in r4
MOV r2,#IRQ_MODE ; Build IRQ mode CPSR
MSR CPSR_c,r2 ; Enter IRQ mode
LDMIA sp!,{r0-r3} ; Recover r0-r3
MOV r5,r5 ; Enter SVC mode
STMDB sp!,{r0-r3} ; Save r0-r3 on thread's stack
这使我想到一个问题,有没有一种方法可以在USER模式下运行线程?在OS中,通常情况是线程以USER模式运行,而其内核和提供的服务以SVC模式运行,而Azure RTOS似乎不是这种情况。
解决方法
这是设计使然,ThreadX是一个小型的单片内核,其中应用程序代码与内核紧密集成在一起,并且位于相同的地址空间和模式下。这样可以实现更高的性能和更低的占用空间。您还可以使用ThreadX模块,其中可用的MPU或MMU用于将内核和用户代码分成不同的模式并提供额外的保护,但这会带来较小的性能和占用空间的负担。