在STM32这样的嵌入式平台上,FreeRTOS的工作原理和任务调度等功能我们经常能够有所耳闻,但是对于大部分刚接触RTOS的小伙伴们经常也会为RTOS的抽象而烦恼,在学习的过程中不免会有这么一个疑惑:
如此抽象的RTOS软件架构是如何最终落实到像STM32这样的处理器底层硬件电路呢?
1.任务定时切换- 系统定时器(SysTick)
FreeRTOS的任务调度需要一个周期性中断来触发系统的任务切换,这个中断通常是通过 SysTick 定时器 实现的。STM32有一个内建的SysTick定时器,它是一个24位的计数器,能够生成定时中断,进而触发任务调度。
-
寄存器体现:SysTick寄存器(如
SysTick->CTRL
,SysTick->LOAD
,SysTick->VAL
)用于设置定时器的工作模式、计数周期以及当前计数值。SysTick->LOAD
:存储定时器的重载值,即计时周期。SysTick->VAL
:定时器当前的计数值。SysTick->CTRL
:控制寄存器,设置SysTick定时器的启用、计数器模式等。
FreeRTOS通常会在其启动代码中配置该寄存器,以确保每隔一定时间发生中断,从而进行任务调度。
2. 中断控制和任务切换
FreeRTOS中的任务切换通常会在中断处理过程中进行。STM32中的中断控制器(NVIC)负责管理中断的使能和优先级,FreeRTOS通过NVIC来启用和管理系统定时器中断和其他外部中断。
- 寄存器体现:
- NVIC(中断控制器)寄存器如
NVIC_ISERx
(中断使能寄存器)、NVIC_IPRx
(中断优先级寄存器) 用于控制中断的启用、禁用和优先级设置。 - 在FreeRTOS中,
vPortEnterCritical()
和vPortExitCritical()
宏会通过操作这些寄存器来关闭和恢复中断,从而避免在任务切换时发生中断。
- NVIC(中断控制器)寄存器如
3. 任务堆栈和上下文切换
FreeRTOS每个任务的执行环境通常通过堆栈来保存,而任务切换时,CPU需要保存当前任务的上下文并加载下一个任务的上下文。任务的上下文包括CPU寄存器(如R0-R12, LR, PC等)的值,这些寄存器在任务切换时需要通过堆栈来保存和恢复。
- 寄存器体现:
- STM32处理器的 通用寄存器 (R0-R12)、程序计数器 (PC)、链接寄存器 (LR) 等,在每次上下文切换时,都会保存到当前任务的堆栈上。
vPortYield()
函数会触发上下文切换,具体通过操作堆栈(通常是在任务堆栈的末尾)保存和恢复任务的上下文。
4. 嵌套向量中断控制器 (NVIC)
当FreeRTOS进行任务切换时,它需要依赖NVIC来控制中断的嵌套。任务切换需要通过中断机制来管理,这就需要通过设置NVIC来控制中断的优先级和使能。
-
寄存器体现:通过设置
NVIC->IPRx
来控制中断的优先级,以及通过NVIC->ISERx
和NVIC->ICERx
来使能或禁止中断。- FreeRTOS可能会通过设置这些寄存器来确保高优先级的任务不会被低优先级任务打断。
5. 内存管理单元(MMU)或内存保护单元(MPU)
在某些STM32型号上,硬件支持 内存保护单元 (MPU),用于为每个任务提供隔离的内存区域。FreeRTOS可以通过MPU配置任务的内存保护,以增强系统的可靠性和安全性。
- 寄存器体现:
- STM32的 MPU 寄存器,如
MPU->CTRL
、MPU->RNR
、MPU->RBAR
和MPU->RASR
,可以配置每个任务的内存访问权限、起始地址和大小等。
- STM32的 MPU 寄存器,如
6. 堆栈指针(SP)
每个任务在运行时都有独立的堆栈指针(SP),在任务切换时,FreeRTOS需要将当前任务的堆栈保存到任务堆栈中,并从下一个任务的堆栈中恢复堆栈指针。
- 寄存器体现:任务堆栈指针(
SP
)是一个CPU寄存器(例如,STM32上是R13),它的值会在任务切换时通过上下文切换操作保存和恢复。
这些硬件寄存器和结构共同协作,支持FreeRTOS在STM32上的任务调度、上下文切换和资源管理等功能。