本节课程主要进行就绪列表、优先级知识点的练习。创建3个任务task1 task2 task3优先级分别为1 2 3
基本逻辑顺序为,进行关中断、systick中断配置、系统初始化、任务创建、启动任务。任务启动后执行任务1(优先级最高),在阻塞延时函数中将任务1优先级列表中标志位清除,但是在就绪列表中不清除。之后进行任务调度,执行现行优先级最高任务任务2(此时任务1优先级已经在优先级表中清除,不再最高优先级任务查找序列之内)。同理执行任务3,最后任务3在优先级表中对应优先级也会被清除,现在只剩闲时任务优先级最高了,一直执行闲时任务。直到systick中断到来,在systick中断服务程序中对就绪列表中任务遍历,将延时时间--;然后看下是否有延时到期的,到期了则进行将其在优先级表中优先级位回复(置位),并进行任务调度,执行该任务。
仿真结果为
1main()
1)CPU_Init() cpu初始化,和时间戳有关 本节课未进行相关代码演示 可以不用管
2)CPU_IntDis() 关中断
3)OS_CPU_SysTickInit() systick定时器配置
4)OSInit() 系统初始化
5)创建3个任务 优先级分别为1 2 3
6)OSStart() 启动任务
任务2 3定义同1
1.4OSInit() 在前节课的基础上加入优先级相关的东西,初始化OSTCBCurPtr、OSTCBHighRdyPtr、OSPrioCur、OSPrioHighRdy 变量;调用OS_PrioInit();OS_RdyListInit(),OS_IdleTaskInit()函数
1.4.1 OS_PrioInit() 优先级表初始化 将优先级数组OSPrioTbl[]各元素初始化为0 宏 OS_CFG_PRIO_MAX=32;CPU_CFG_DATA_SIZE=4u;DEF_OCTET_NBR_BITS=8u
1.4.2OS_RdyListInit()就绪列表成员初始化NbrEntries,HeadPtr、TailPtr
1.4.3OS_IdleTaskInit()闲时任务初始化,闲时任务创建,加入优先级相关代码
1.4.3.1 OSTaskCreate()任务创建需要更改
OS_TaskInitTCB()任务控制块初始化:将各变量初始化为0;任务控制块Prio、StkPtr、StkSize变量赋值;临界代码段进行优先级表中任务优先级置位,并将任务查到就绪列表尾部。
1.5task1、2、3创建。创建完闲时任务OSPrioTbl[0]=0x0000 0001闲时任务优先级最低;创建完task1,OSPrioTbl[0]=0x4000 0001;创建完task2,OSPrioTbl[0]=0x6000 0001;创建完task3,OSPrioTbl[0]=0x7000 0001;
1.6OSStart()启动任务
1)获取高优先级任务OSPrioHighRdy = OS_PrioGetHighest();2)任务控制块高优先级指针设置OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;3)启动任务永不返回OSStartHighRdy()
// OSTCBCurPtr = OSTCBHighRdyPtr;没必要加,因为在PendSv_Handler中会将这一句写入
1.6.1OS_PrioGetHighest() 获取高优先级任务指针的方式是先找优先级列表OSPrioTbl[]中第一个不为零的元素,即该元素优先级最高,前面的元素为0也就是说前面的任务没有就绪,优先级未使能。然后计算该非零优先级数组元素的前导零个数,查前导零数组对应其优先级。计算前导零个数函数CPU_CntLeadZeros(),可以用汇编写也可以用c语言写。注意只能用一种方式定义,用汇编时要把c定义的函数用宏屏蔽。
1.6.1.1CPU_CntLeadZeros()函数定义
汇编代码,在cpu_a.asm重定义 要在cpu.h中声明,并在本函数头部 EXPORT
c语言版本
1.6.1.2OSStartHighRdy() 在开头添加PROC 结尾改成ENDP
执行完1.6.1.2执行中断任务
1.7 执行完1.6,跳转到任务1,执行任务1中OSTimeDly() 在临界段中进行操作
1.7.1CPU_SR_ALLOC()定义一个变量,用于临界代码前后cpu状态保存/恢复,定义在cpu.h中
1.7.2 OS_CRITICAL_ENTER()进入临界段 保存cpu状态到cpu_sr中;OS_CRITICAL_EXIT()从cpu_sr中回复cpu原先状态
1.7.3 临界代码段内容1)TaskDelayTicks--;2)OS_PrioRemove()清除当前任务在OSPriTbl[i]中的优先级位,任务1执行完这步后OSPrioTbl[0] = 0x3000 0001;其OSPrioTbl中优先级位恢复则在systick中断处理中。
1.7.4 OSSched()任务调度 需要进行修改 ,最后别忘了一定加上OS_TASK_SW(),触发异常中断,进行任务切换。
这里将执行代码加入到临界段内。临界段内主要进行获取高优先级指针OSPrioHighRdy = OS_PrioGetHighest();,高就绪任务指针OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; 由于task1的优先级在OSPrioTbl[0]中已清除,此时任务2优先级最高,执行任务2。之后执行任务3,之后所有任务优先级在OSPrioTbl[0]中优先级都被清除,只剩下闲时任务有优先级,一直执行闲时任务,指导systick触发中断,判断是否进行任务切换。
2 systick中断处理函数,执行OSTimeTick(); 在临界代码段内执行动作。遍历优先级范围内所有就绪列表中任务,阻塞时间--;若时间为0,说明延时到了,OS_PrioInsert()将该任务在OSPrioTbl[0]中优先级置位。并进行任务切换,执行该任务。
、