动手写简单的嵌入式操作系统一
作者:网络转载 发布时间:[ 2013/8/14 11:30:19 ] 推荐标签:
OSCurTCB和OSNewTCB分别是当前运行任务的堆栈指针和要运行的新任务的堆栈指针。
下一步是任务的创建了,任务是如何创建的。每个任务都有自己的堆栈空间,像是单独占用CPU一样,所以创建任务还需完成任务堆栈的初始化。
需要知道CPU是如何出栈压栈的,保存了哪些寄存器,顺序是什么,堆栈的增长方向是什么。参考《cortexM3权威指南》,书中有详细的介绍。
以下是c语言写的任务堆栈的初始化函数,位于文件OS_CPU.c中,如果需要移植,除了汇编部分OS_CPU_A.asm文件修改外,OS_CPU.c和OS_TYPE.h等文件也需要修改。仅这几个文件。
OS_STK实际上是int32,因为stm32上堆栈指针是32位长度。第一个参数是任务的地址,即函数的地址,第二个参数是任务的堆栈指针。
OS_STK *OSTaskStkInit (void (*task),OS_STK *ptos)
{
OS_STK *stk;
stk = ptos; /* get stack point */
*(stk) = (uint32)0x01000000L; /* xPSR */
*(--stk) = (uint32)task; /* Entry Point */
*(--stk) = (uint32)0xFFFFFFFEL; /* R14 (LR) */
*(--stk) = (uint32)0x12121212L; /* R12 */
*(--stk) = (uint32)0x03030303L; /* R3 */
*(--stk) = (uint32)0x02020202L; /* R2 */
*(--stk) = (uint32)0x01010101L; /* R1 */
*(--stk) = (uint32)0; /* R0 : argument */
/* Remaining registers */
*(--stk) = (uint32)0x11111111L; /* R11 */
*(--stk) = (uint32)0x10101010L; /* R10 */
*(--stk) = (uint32)0x09090909L; /* R9 */
*(--stk) = (uint32)0x08080808L; /* R8 */
*(--stk) = (uint32)0x07070707L; /* R7 */
*(--stk) = (uint32)0x06060606L; /* R6 */
*(--stk) = (uint32)0x05050505L; /* R5 */
*(--stk) = (uint32)0x04040404L; /* R4 */
return (stk);
}
/*
* 创建新的任务
*/
TCB* OSTaskCreate(void* task, OS_STK *stack,PRIO_TYPE prio)
{
TCB *pTCB;
OS_CPU_SR cpu_sr = 0;
OS_ENTER_CRITICAL();
pTCB = OSGetFreeTCB(prio);
if (NULL == pTCB)
{
OS_EXIT_CRITICAL();
return NULL;
}
pTCB->pStackTop = OSTaskStkInit(task, stack);
pTCB->CurPriority = prio;
pTCB->TCBDelay = 0;
TaskNUM++;
OS_EXIT_CRITICAL();
return pTCB;
}
创建新任务函数很简单,只要懂了OSGetFreeTCB(prio);这个函数没啥问题。创建的任务,是一个有序的表,是一个存储元素为
TCB类型的数组TCB OSTCBTable[MAX_TASK_NUM];在这个数组中,先在OSTCBTable[0]中创建一个任务,如果再创建一个任务,这个任务比上个任务的优先级高,那么OSTCBTable[0]中存储优先级高的任务,那个之前先创建的低优先级的任务搬移到OSTCBTable[1]中。如果再创建一个任务,任务优先级会与前两个任务对比,若比前两个都低,放在第三个位置OSTCBTable[2]中,否则重新排序,总之,使OSTCBTable数组中的任务始终是按优先级从高到低的顺序排列。
以下是这种思想实现的OSGetFreeTCB(prio)函数:
/*在TCB表中取一个空闲的节点,给新任务使用*/
/*对OSTCBTable表这个有序表进行插入排序*/
/*将优先级高的任务放在前面*/
TCB* OSGetFreeTCB(PRIO_TYPE prio)
{
TCB *pTCB;
int32 index=0,orgIndex;
pTCB = &(OSTCBTable[0]);
for (index = 0;index < TaskNUM+1;index++)
{
pTCB = OSTCBTable+index;
/*已经是空闲TCB了,直接使用*/
if (NULL == pTCB->pStackTop)
{
return (TCB*)pTCB;
}
/*若新任务优先级比较低或相等,则向后继续找*/
if (pTCB->CurPriority >= prio)
{
continue;
}
else /*pTCB->CurPriority < prio 找到了该插入的位置了*/
{
/*保存当前位置*/
orgIndex = index;
/*从当前节点遍历到后一个使用了的节点*/
for( index = TaskNUM ; index > orgIndex ; index-- )
{
pTCB = OSTCBTable+index;
/*将前一个节点的数据,保存到当前节点*/
_mem_copy((uint8 *)(pTCB),(uint8 *)(pTCB-1),sizeof(TCB));
}
_mem_clr((uint8 *)(pTCB-1),sizeof(TCB)) ;
return (TCB*)(pTCB-1);
}
}
return (TCB*)NULL;
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11