版权信息
warning
本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
开发进度
- [ ] RTOS最基本的功能
- [x] 任务静态创建与TCB
- [x] 任务栈的初始化
- [ ] 动态创建任务
- [x] SVC中断启动内核和第一个任务
- [x] 在PendSV中断里上下文切换
- [x] 任务主动发起的上下文切换函数
- [x] Systick中断触发上下文切换
- [x] 中断屏蔽宏函数
- [x] Delay函数
- [x] Idle空闲任务
- [ ] 一些基本的进程间同步功能
DAY1 26-03-29
正式开始 suipidRTOS 项目。根据前面学习的FreeRTOS的内部机制进行开发。
完成了任务创建与TCB、任务栈的初始化、SVC中断的实现。
DAY2 26-03-30
完成任务主动让出CPU、PendSV中断的汇编逻辑。Bug1:只会触发一次上下文切换
问题出在 stm32f4xx_it.c 中的中断函数嵌套调用。
在 stm32f4xx_it.c 中,我是这么写的:
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
srtos_PendSV_Handler(); // 你在这里调用了汇编函数!
/* USER CODE END PendSV_IRQn 0 */
}
PendSV_Handler 是一个标准的 C 函数。当内核进入这个函数时,编译器为了遵守 C 语言调用约定,会生成压栈指令(Prologue),并用 bl(分支并链接)指令去调用 srtos_PendSV_Handler()。bl 指令覆盖掉了 LR 寄存器!此时 r14 不再是 0xFFFFFFFD,而是变成了 PendSV_Handler 函数内部的下一条指令地址。导致PendSV中断不能正常返回到应该被切换到的任务函数,而是返回到 PendSV_Handler(void),进一步返回到原先的函数。只能切换一次是因为首次运行时手动设置了LR寄存器的值。
Fix:上下文切换的汇编函数必须是中断向量表的直接入口,绝对不能被其他 C 函数包装或调用。
DAY3 26-04-02
完成Systick和中断屏蔽宏函数。
Q1:行为寄存器的写入规则
不同于数据寄存器,行为寄存器的写入规则不应该用 |= (或等于)来赋值,而是直接用等于号赋值。例如ARM Cortex-M 内核的 ICSR(Interrupt Control and State Register,中断控制和状态寄存器) 就是一个行为寄存器。
写入规则:“写 0 无效”。硬件会直接无视 0,原来是什么状态,就是什么状态。
Q2:终于理解了为什么要为OS单独设置一个时基而不是和MCU共用一个时基
OS和MCU时钟(HAL库依赖的时钟)解耦的妙处——确保这两个系统不受对方的影响。两个系统完全控制自己的时钟。
如果在多任务运行期间,需要临时挂起调度器(vTaskSuspendAll())去执行一段极其关键的裸机代码,或者发生严重 Fault 需要在不依赖 OS 的情况下用 HAL 库保存错误日志到 Flash,SysTick 此时的状态是不可控的。
时钟解耦,能保证无论 OS 处于未启动、运行中、还是崩溃状态,MCU(HAL库)永远有一颗正常跳动的心脏。
DAY4 26-04-04
清明前夕苦逼营业中…
初步实现了Delay函数的逻辑还有空闲任务。一遍调通没啥大问题。