一、UC/OS II代码:
①与硬件无关的内核代码
②与处理器有关的代码移植
③用户配置文件
二、主要函数
(1)OSInit()
(2)OSStart
(3)OSTaskCreate
(4)OSTimeDly
(5)OSTimeTick
(6)OSTaskDel
(7)OSIntEnter
(8)OSIntExit
(9)OS_ENTER_CRITICAL和OS_EXIT_CRITICAL
(10)OSSemCreate
(11)OSSemPend
(12)OSSemPost
(13)OSSemDel
三、最小内核
1.任务
①任务之间不能直接调用,也不能进行数据交换,需要通过内核进行任务调度和数据交换。
②任务状态:睡眠状态、就绪状态、运行状态、等待状态、被中断状态
2.OS初始化:调用OS-InitMisc()、OS-InitRdyList()[创建空闲任务]、OS-InitTCBList()、OS-InitTaskldle()四个函数。
3.获取并初始化TCB
4.启动OS
void OSStart (void)
{
INT8U y;
INT8U x;
if (OSRunning == FALSE) { //判断系统是否运行
y = OSUnMapTbl[OSRdyGrp]; /* Find highest priority's task priority number */
x = OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy = (INT8U)((y << 3) + x);
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
OSTCBCur = OSTCBHighRdy; //更变TCB指针
OSStartHighRdy(); /* Execute target specific code to start task */
}
}
5.中断初始化
μC/OS-Ⅱ要求在多任务环境启动之前不允许产生中断,所以通常会在第一个执行的任务中调用函数TargetInit()初始化中断系统和能够产生中断的外设。
void TargetInit(void)
{
OS_ENTER_CRITICAL();
VICInit(); //中断优先级初始化
Timer0Init(); //定时器初始化,用于时钟节拍中断,检测任务超时
OS_EXIT_CRITICAL();
}
6.延时任务切换
①延时函数
void OSTimeDly (INT16U ticks)
{
if (ticks > 0)
{
OS_ENTER_CRITICAL();
if ((OSRdyTbl[OSTCBCur->OSTCBY] &=
~OSTCBCur->OSTCBBitX) == 0) /任务脱离就绪状态/
{
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly = ticks; //设置延时的时间
OS_EXIT_CRITICAL();
OS_Sched(); //任务切换
}
}
②任务切换
void OS_Sched (void)
{
INT8U y;
OS_ENTER_CRITICAL(); // 关闭中断
if (OSIntNesting == 0) { //判断是否处于中断状态
y = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); //获取就绪态任务的最高优先级
if (OSPrioHighRdy != OSPrioCur) { //判断当前任务是否为最高优先级
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; // 就绪态优先级最高,获取TCB
OS_TASK_SW(); //任务切换
}
}
OS_EXIT_CRITICAL();
}
③OS_TASK_SW(); //
TASK_SW
MRS R3, SPSR
MOV R2, LR //获取软中断产生时的状态和返回地址
MSR CPSR_c, #(NoInt | SYS32Mode) //状态切换
STMFD SP!, {R2}
STMFD SP!, {R0-R12, LR} //保护现场,寄存器入栈
B OSIntCtxSw_0 //调用子函数
LDR R4, =OSPrioCur
LDR R5, =OSPrioHighRdy
LDRB R6, [R5]
STRB R6, [R4] //修改OSPrioCur
LDR R6, =OSTCBHighRdy
LDR R6, [R6]
LDR R4, =OSTCBCur
STR R6, [R4] //修改OSTCBCur
7.时钟节拍
void OSTimeTick (void)
{
OS_TCB *ptcb;
if (OSRunning == TRUE) ; // 是否系统运行
{
ptcb = OSTCBList; //获取TCB列表表头指针
while (ptcb->OSTCBPrio != OS_IDLE_PRIO) { //判断是否处于表尾
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0); //任务在等待时间事件
{
if (--ptcb->OSTCBDly == 0); //减少等待时间
{
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; //使任务进入就绪态
}
}
ptcb = ptcb->OSTCBNext; //处理下一个任务
OS_EXIT_CRITICAL();
}
}
}
8.删除任务
INT8U OSTaskDel (INT8U prio) //uc/os ii 没有时间轮转片,一个优先级对应一个任务,删除优先级就是删除任务
{
OS_TCB *ptcb;
if (OSIntNesting > 0) {
return (OS_TASK_DEL_ISR);
}
if (prio == OS_IDLE_PRIO) { // 是否删除空闲任务
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { // 是否删除自身
return (OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) {
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb != (OS_TCB *)0) {
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { //任务从就绪表中删除
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
ptcb->OSTCBDly = 0;
ptcb->OSTCBStat = OS_STAT_RDY;
OSTCBPrioTbl[prio] = (OS_TCB *)0;
if (ptcb->OSTCBPrev == (OS_TCB *)0) { //任务从优先级列表中删除,tcb从tcb列表中删除
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
} else {
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList;
OSTCBFreeList = ptcb;
OS_EXIT_CRITICAL();
OS_Sched();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_TASK_DEL_ERR);
}