FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中)
本帖最后由 gentleman 于 2024-3-3 15:03 编辑FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中)
任务轮询
2.1 调整中断堆栈内容
上次我们成功启动了 第一个任务
如果 任务中,它不挂起自己,或进入延时状态。 (正常不会这么干,下期会讲)
那么 任务会执行到 1tick后
cpu进入定时器0中断
配置定时器0 中断函数
vTimer0ISR()
跳进去
180行 portNORMALIZE_INTERRUPT_STACK();
再跳进去
发现 它执行了一系列 出栈 入栈 操作
目的是什么
因为中断的栈 格式是不一样的
我们可通过对比 RETI 与 ERET 来比较
很明显 中断栈顶元素 是PC15~8
而函数栈顶元素是PC7~0
所以这里 将几个栈元素都 弹出来
按照函数栈 顺序 重新入一遍栈
2.2寄存器入栈 配置Tick计数器
将寄存器入栈
继续看代码
接下来进入到这个函数
const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
将tick计数器+1
freeRTOS 就是靠这个计数器计时的
xConstTickCount == ( TickType_t ) 0U
计数器什么时候==0
溢出的时候
切换 延时任务列表 (看过之前的文章知道,这列表有两个)
关于延时任务部分 下期再说
这期主要看轮询
2.3保存当前任务堆栈指针
阅读过之前内容
就知道 DR60 是SP指针指向堆栈的栈顶
这里把 SP指针 保存到了当前任务TCB(pxTopOfStack)中
DR0 与WR2 ,DR4 与WR6 的关系大家应该都清楚吧,不多解释了
2.4取出下个任务
返回去
跳入这个函数
判读了一下 任务调度是否启动
启动了就执行这个函数
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{ \
configASSERT( uxTopPriority ); \
--uxTopPriority; \
} \
优先级列表空就看下个优先级列表
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );
取出下一个任务的PCB这块展开讲内容也有点多,后面我会画张图,补充在本贴下面3L
2.5恢复到新任务栈顶指针
好的,现在已经获取到了下个任务的TCB
回到这里
portRESTORE_SPX()
这里和上期一样, 修改SP 为 新任务的TCB(pxEndOfStack)
让SP指向新任务的(堆)栈
2.6出(新任务)栈
弹出新任务用的寄存器
2.7压入RETI需要的栈元素 ,调用RETI退出中断
$ 指当前行
$+10 指的是哪一行
我们来分析一下
这是PUSH
指令长度3 (因为立即数也要占一个)
3条PUSH 长度9
而RETI 长度1
所以$+10 就是 RETI 的下一条指令
同理 +7 +4 也是
最后调用RETI 退出中断
至于为啥要这么干,用RETI 清楚标志位,退出中断。不然下次就不进中断了,CPU认为还在中断内部。
2.8ERET 进入新任务函数
这部分也和上期一样
通过ERET 修改PC指针
让PC指针指向新的任务入口
到此完成了新任务的切换
本帖最后由 gentleman 于 2024-3-28 10:50 编辑
上期:任务调度 (上) FreeRTOS for STC32G12K128内核代码解读(二)任务调度(上) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
下期:
5.任务调度(中下)FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中下) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
本帖最后由 gentleman 于 2024-3-4 10:47 编辑
补充 FreeRTOS (xLIST)链表结构内容
便于大家理解在任务就绪链表取出下个任务TCB过程
下图为FreeRTOS 三个链表的定义
xLIST 中包含 xMINI_LIST_ITEM与xLIST_ITEM
即
pxReadyTasksLists]中 包含pxIndex 与xListEnd
而在任务就绪链表链表初始化时
可以看到初始化 时把pxIndex 设为了 xListEnd
新建任务时
插入链表尾部的函数
把 新项 的下一项 设为 pxIndex (初始化时为xListEnd)
前项 设为 pxIndex(初始化时为xListEnd)的前一项(就是上个任务)
这里可以看第一张图 去理解
取出下个任务
还是对照图来看
很清晰的看出 pxIndex 的pxNext 是哪一项
当pxNext 为 xListEnd 时 就再取pxNext一遍
3L 用了补充了一些内容
再占一楼
页:
[1]