实现任务创建函数
任务的栈,任务的函数实体,任务TCB最终需要联系起来才能由系统进行统一调度。那么这个联系的工作就由任务创建函数OSTaskCreate来实现该函数在os_task.c中实现。
我们想象一下,我们创建一个任务,需要将一个任务栈以及一个任务控制块以及任务的一个函数主体给联系起来的。那么肯定是需要传递一个参数,传递这些参数。任务的栈,任务的函数主体,任务的TCB块。这些参数是必不可少的。那么我们可以来这里os_task.c中。
#include "os.h"
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);
p_tcb->StkPtr = p_sp;
p_tcb->StkSize = stk_size;
*p_err = OS_ERR_NONE;
}
这个void OSTaskCreate官方的一个函数
那么我们来看看有什么参数
OS_TCB 是任务控制块的一个形式
OS_TASK_PTR
我们摁F12进入
这个OS_TASK_PTR数据结构是任务函数的一个数据类型。
我们的这个任务函数,像我们这里app.c写的
传入一个空类型的指针。
那么
这个函数的数据结构就是一个数据指针。
那我们要把这个Task1作为一个参数传递进去。
同时呢这里这里是个任务栈的基地址。
这是任务栈的大小。
这里*p_tcb->StkSize=stk_size
任务栈指针肯定指向它的基地址
任务栈初始化 是初始化它对应的寄存器。
我们摁F12进入
这里是一个PC寄存器
任务的形参要保存在R0之中。
这个第24位必须要置1.
一个任务需要有一个独立的栈空间。
一个独立的栈空间呢,它的一个我们有个PC寄存器。LR,R0;
PC指针指向的是我们的一个运行的任务(运行的代码)。
LR是一个退出时候,通过LR寄存器来进行一个返回的。正常来说一般都是指向一个退出函数。
R0是一个形参,是任务的一个参数。进行一个传递,就第一个参数。
p_task是PC指针。
p_arg是R0形参。
–p_stk = (CPU_STK)0x14141414u; / R14 (LR)
这是LR。
F12点进去。
我们发现他的参数有这些。
第一个p_task;就是任务的一个参数。而任务的参数就是我们一个任务的一个函数指针
第二个参数p_arg是我们的一个形参。
第三个p_stk_base 初始化任务栈的基地址。
第四个 stk_size 任务栈的大小
现在我们知道了这些的含义
这个返回值为p_stk;
返回是一个任务栈顶指针。
我们之后要把控制块的信息配置起来。
因为我们说控制块就是它的一个身份(任务控制看相当于任务的身份证)
比如任务栈顶指针和任务栈大小。
sp指针有psp和msp。psp是在任务中使用的,在正常的栈中使用。
msp是在中断使用。在异常之中使用的。
大家如果是进行一个仿真的话
MSP是组栈指针。
这个函数是任务栈初始化函数。当任务第一次运行的时候,加载到CPU寄存器的参数留放在这个任务栈里面,当任务创建的时候,预先初始化好栈。
OSTaskStkInit()函数在os_cpu_c.中实现
添加它的大小。
最后要把它的一个数据错误要返回。
它是在这里被定义的。它不同的错误都会有不同的定义在里面
任务创建好之后,我们需要把任务添加到一个就绪列表里面,表示任务已就绪,系统随时可以调度。
正常来说是一个停止的状态。
以及他的一个当前任务控制块的一个指针
我快放弃了…这老师讲的真不好…我扣子扣半天了…
为了本着对大家负责的态度,我继续扣!
任务切换
当调用OSStartHighRdy()函数,触发PendSV异常后,就需要编写PendSVy异常服务函数,然后在里面进行任务切换。
PendSV异常服务中主要完成两个工作,一是保存上文,即保存当前正在运行的任务的环境参;而是切换下文,即把下一个需要运行的任务的环境参数从任务栈中加载到CPU寄存器,从而实现任务的切换。
PendSV异常服务中用到了OSTCBCurPtr和OSTCBHighRdyPtr这两个全局变量,这两个全局变量在os.h中定义
对不起各位,心态有点爆炸。可能是我学习的太少了,等我状态回归,重新好好整理一下这个UCOSIII的章节,宁愿一天听一课,一课听10遍,也不能糊弄CSDN的朋友们!