uCOS-Ⅲ学习笔记:任务定义与切换
1. 创建任务
1.1 定义任务堆栈
1.栈是RAM内一段连续内存
2.定义任务栈就是给函数定义一个数组:
static CPU_STK Task1Stk[TASK1_STK_SIZE] ;
- 1
1.2 定义任务函数
每个任务函数必须是一个死循环,其内必须有阻塞延时函数以进行任务调度!!!
1.3 定义任务控制块
定义一个结构体,里面可以存放每个任务的堆栈,名称,形参等等参数,对任务的操作都可以通过这个TCB来实现
struct os_tcb
{
CPU_STK *STKPTR
CPU_STK_SZIE StkSize
}
- 1
- 2
- 3
- 4
- 5
1.4 实现任务创建函数
把任务堆栈、任务实体、任务的TCB联系起来的函数
void OSTaskCreate
(
OS_TCB *p_tcb,
OS_TASK_PTR p_task,
void *p_arg,
CPU_STK *p_stk_base,
CPU_STK_SIZE stk_size,
OS_ERR *p_err
);
{
CPU_STK *p_sp;
p_sp=OSTaskStkInit(//返回的栈顶指针
p_task,
p_arg,
p_stk_base,
stk_size
);
//把栈顶指针和栈大小给到tcb里面
p_tcb->StkPtr = p_sp;
p_tcb->StkSize= stk_size;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
参数介绍:
OS_TCB -任务TCB
OS_TASK_PTR -任务指针
*p_arg -参数指针
CPU_STK -堆栈基地址
CPU_STK_SIZE -堆栈大小
OS_ERR -错误枚举
1.5 任务堆栈初始化函数
该函数第一次运行时使用,把堆栈的数据预加载到CPU的寄存器
CPU_STK *OSTaskStkInit
(
OS_TASK_PTR p_task,
void *arg,
CPU_STK *p_stk_base,
CPU_STK_SIZE stk_size);
{
CPU_STK *p_stk;
p_stk = &p_stk_base[stk_size];
以下只适合Coterx-M3
/* 异常发生时自动保存的寄存器 */
*--p_stk = (CPU_STK)0x01000000u; /* xPSR的bit24必须置1 */
*--p_stk = (CPU_STK)p_task; /* 任务的入口地址 */
*--p_stk = (CPU_STK)0x14141414u; /* R14 (LR) */
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
*--p_stk = (CPU_STK)0x01010101u; /* R1 */
*--p_stk = (CPU_STK)p_arg; /* R0 : 任务形参 */
/* 异常发生时需手动保存的寄存器 */
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
return (p_stk);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
1.6 就绪列表
该列表存放已经就绪的列表,表示其中的任务可以进行调度
struct os_rdy_list
{
OS_TCB *HeadPtr;
OS_TCB *TailPtr;
};
- 1
- 2
- 3
- 4
- 5
2. OS系统初始化
OSRuning存放系统任务运行状态
OSTCBCurPtr和OSTCBHighRdyPtr是当前任务指针以及最高任务指针
本函数主要初始化清零,初始化就绪列表(清零列表)和空闲任务
void OSInit (OS_ERR *p_err)
{
OSRunning = OS_STATE_OS_STOPPED;
OSTCBCurPtr = (OS_TCB *)0;//当前任务控制块指针
OSTCBHighRdyPtr = (OS_TCB *)0;//最高优先级指针
OS_RdyListInit();//就绪列表初始化,列表清零
//初始化空闲任务
OS_IdleTaskInit(p_err);
*p_err = OS_ERR_NONE;//执行到这无报错
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3. 启动系统
系统启动,配置最高任务TCB指针,在下一个TICK中切换
void OSStart (OS_ERR *p_err)
{
if( OSRunning == OS_STATE_OS_STOPPED )
{
/* 手动配置任务1先运行 */
OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
/* 启动任务切换,不会返回 --汇编.s文件里面*/
OSStartHighRdy();
/* 不会运行到这里,运行到这里表示发生了致命的错误 */
*p_err = OS_ERR_FATAL_RETURN;
}
else
{
*p_err = OS_STATE_OS_RUNNING;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
4. 任务切换
该函数把就绪列表最高任务赋给下一个最高就绪优先级
(OS_TASK_SW()函数用于把PENDSV异常在中断标志中置位,使之进入PENDSV中断,开启上下文切换)
OS_CRITICAL_ENTER() 开启屏蔽中断—使进入上下文切换不被打断
void OSSched (void)
{
CPU_SR_ALLOC();
OS_CRITICAL_ENTER();
OSPrioHighRdy = OS_PrioGetHighest();
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
if(OSTCBCurPtr == OSTCBHighRdyPtr)
{
OS_CRITICAL_EXIT();
return;
}
OS_CRITICAL_EXIT();
//任务切换
OS_TASK_SW();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
5. MAIN函数
1—初始化相关变量
2—创建任务
3—任务添加到就绪列表
4—启动OS
6. 参考资料教程
野火UCOS-Ⅲ教程
UCOS-Ⅲ内核实现与应用开发实战指南-基于STM32
正点原子开发板
文章来源: blog.csdn.net,作者:JeckXu666,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_45396672/article/details/109278913
- 点赞
- 收藏
- 关注作者
评论(0)