|
对于TCB控制块我的理解是:
任务控制块是记录任务的优先级,状态,堆栈指针等参数的一个链表,这个链表分为两部分,一个叫做空闲链表,一个叫做当前任务链表,空闲链表是人物创建的时候去申请,得到后设置参数,设置完了就把这个链表加载到当前链表中,下面看看任务建立的时候是怎么做的!!
、、部分代码,不相关的略去
psp = (void DT_XDATA *)OSTaskStkInit(task, ppdata, ptos, 0); /* Initialize the task's stack
err = OSTCBInit(prio, psp, (void DT_XDATA *)0, 0, 0, (void DT_XDATA *)0, 0);
第一个是用来获得任务堆栈的基地址,任务堆栈这个东西,在开始的时候就建好了,其实就是个大数组,每个任务都有一个,当任务切换时这个数组用来存CPU相关的寄存器,比如累加器和8个寄存器,返回指针,任务的切换说白了就是人为的模仿了一次软件中断,
第二个用来获取任务的TCB控制块,并加载到当前任务控制块列表,
主要看第二个函数,第一个就是对堆栈的一个分配,决定那个字节些什么,初始化,关键是第二个TCB的创建
程序如下:
OS_TCB DT_XDATA * ptcb;//定义一个TCB的结构指针
OS_ENTER_CRITICAL();//进入临界代码区
/* Get a free TCB from the free TCB list */
ptcb = OSTCBFreeList; //获取一个空的TCB块给PTCB
//判断TCB是否用完?用完了返回错误70
if (ptcb != (OS_TCB DT_XDATA *)0) {
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
OS_EXIT_CRITICAL();//开中断
ptcb->OSTCBStkPtr = ptos;//任务堆栈指针写入 /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = (INT8U)prio; //任务优先级 /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY;//任务状态这个表示准备好了 /* Task is ready to run */
ptcb->OSTCBDly = 0; //任务延时 /* Task is not delayed */
/* Pre-compute X, Y, BitX and BitY */
//把优先级分解,计算出在就绪表中的位置
ptcb->OSTCBY = prio >> 3;
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = prio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
OS_ENTER_CRITICAL();
/* OSTCBPrioTbl */
OSTCBPrioTbl[prio] = ptcb; //写入OSTCBPrioTbl数组中对应的优先级的TCB指针地址
/* Link into TCB chain. insert to the first of chain */
ptcb->OSTCBNext = OSTCBList; //装载下一个链表地址
ptcb->OSTCBPrev = (OS_TCB DT_XDATA *)0; //装载先前指针
//如果 OSTCBList不为0 那么上一个指针就是当前的ptcb
if (OSTCBList != (OS_TCB DT_XDATA *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
//优先级写入就绪表
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
这里面的就是TCB的创建!大体上分为以下几个部分:
1,申请空链表
2.对申请到的空链表进行初始化,
3加载空链表到当前链表
4释放下一个链表的位置,
这里又有4个结构指针是核心分别是
OS_TCB DT_XDATA * ptcb
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBFreeList;
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBList;
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBPrioTbl[OS_LOWEST_PRIO + 1];
第一个是中间指针变量,第二个是空链表,第三个是当前TCB表,第四个是对应优先级的TCB表位置
对他们的操作如下:
第一歩:
ptcb = OSTCBFreeList;
表示把指向空闲链表指针的地址给PTCB这个中间人
第二部:
ptcb->OSTCBStkPtr = ptos;//任务堆栈指针写入 /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = (INT8U)prio; //任务优先级 /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY;//任务状态这个表示准备好了 /* Task is ready to run */
ptcb->OSTCBDly = 0;
表示对空闲链表初始化操作
第三部:
OSTCBPrioTbl[prio] = ptcb;
表示把申请到的当前TCB控制块的地址放到优先级里这样使得优先级和对应的TCB对应起来,比如优先级是20,那么他就在20那个结构数组里
存入优先级为20的任务TCB控制块,
第四部:
ptcb->OSTCBNext = OSTCBList;
ptcb->OSTCBPrev = (OS_TCB DT_XDATA *)0;
if (OSTCBList != (OS_TCB DT_XDATA *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
这一步表示下一个链表的地址是OSTCBList当前地址
并且吧当前申请到的TCB表写回到当前链表中,这是个加载,而上一个是释放
最后加载到入任务就绪表中就OK乐!!!!
|
|