ucos-II 任务调度源码分析(二)
在ucos-II中最主要的函数是:
INT8U OSTaskCreate (void (*task)(void *p_arg),void *p_arg,OS_STK *ptos, INT8U prio)
*task:任务函数的钩子;*p_arg:任务的参数;ptos:指向任务的堆栈;prio:任务的优先级。
在OSTaskCreate中主要完成了以下工作:
- OSTCBPrioTbl[prio] = OS_TCB_RESERVED;设置OSTCKPrioTbl为有效;
- OSTaskStkInit;初始化任务堆栈;将下列信息存入ptos指向的堆栈区,如任务函数、任务函数参数、特殊寄存器、工作寄存器
- OS_TCBInit;初始化TCB,在初始化TCB函数中:
- 初始化OS_TCB;
- 根据优先级,更新OSTCBPrioTbl、OSTCBList、OSRdyGrp、OSRdyTbl;
- 如果初始化OS_TCB正常,则调用OS_Sched:
- 通过OSRdyGrp、OSUnMapTbl查找当前最高优先级的就绪任务(详见ucos-II任务调度(一)),并赋值给全局变量OSPrioHighRdy;
- 调用OS_TASK_SW,该函数在OS_CPU_A.ASM中实现,与具体的CPU强相关。
注:以STC单片机为例,CPU通过执行PC寄存器指向的地址实现跳转,在51系列的MCU中PC寄存器是不可寻址的,因此ucos采用这样的方法。在OSTaskStkInit时任务地址被压栈:
void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, OS_STK *ptos, INT16U opt) { OS_STK *stk; ppdata = ppdata; opt = opt; stk = ptos; *stk++ = 15; *stk++ = (INT16U)task & 0xFF; //任务地址低8位 *stk++ = (INT16U)task >> 8; //任务地址高8位 *stk++ = 0x0A; //ACC *stk++ = 0x0B; //B *stk++ = 0x00; //DPH
然后当需要跳转时首先执行POPA,将所有的寄存器出栈,此时SP的指针指向ACC保存的地址。然后调用RETI,通过RETI指令对PC寄存器赋值。RETI指令定义如下:
PC高8位 = (SP);(SP)<-(SP-1);PC低8位=(SP);(SP)<-(SP-1)
ucos的任务管理中还实现了其他一些函数如任务优先级的修改、任务的挂起、任务的恢复等。从原理上都大同小异,通过修改全局变量实现。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)