2478ucostouchOK总体思路.docx

上传人:b****7 文档编号:15687135 上传时间:2023-07-06 格式:DOCX 页数:21 大小:23.47KB
下载 相关 举报
2478ucostouchOK总体思路.docx_第1页
第1页 / 共21页
2478ucostouchOK总体思路.docx_第2页
第2页 / 共21页
2478ucostouchOK总体思路.docx_第3页
第3页 / 共21页
2478ucostouchOK总体思路.docx_第4页
第4页 / 共21页
2478ucostouchOK总体思路.docx_第5页
第5页 / 共21页
2478ucostouchOK总体思路.docx_第6页
第6页 / 共21页
2478ucostouchOK总体思路.docx_第7页
第7页 / 共21页
2478ucostouchOK总体思路.docx_第8页
第8页 / 共21页
2478ucostouchOK总体思路.docx_第9页
第9页 / 共21页
2478ucostouchOK总体思路.docx_第10页
第10页 / 共21页
2478ucostouchOK总体思路.docx_第11页
第11页 / 共21页
2478ucostouchOK总体思路.docx_第12页
第12页 / 共21页
2478ucostouchOK总体思路.docx_第13页
第13页 / 共21页
2478ucostouchOK总体思路.docx_第14页
第14页 / 共21页
2478ucostouchOK总体思路.docx_第15页
第15页 / 共21页
2478ucostouchOK总体思路.docx_第16页
第16页 / 共21页
2478ucostouchOK总体思路.docx_第17页
第17页 / 共21页
2478ucostouchOK总体思路.docx_第18页
第18页 / 共21页
2478ucostouchOK总体思路.docx_第19页
第19页 / 共21页
2478ucostouchOK总体思路.docx_第20页
第20页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

2478ucostouchOK总体思路.docx

《2478ucostouchOK总体思路.docx》由会员分享,可在线阅读,更多相关《2478ucostouchOK总体思路.docx(21页珍藏版)》请在冰点文库上搜索。

2478ucostouchOK总体思路.docx

2478ucostouchOK总体思路

uC/OS-II移植到ARM7

1.OS_CPU.H的相应修改

OS_CPU.H包括了与编译器相关的数据类型定义和与微处理器相关的常数、宏以及类型。

不同微处理器中有不同的字长,所以必须定义一系列数据类型以确保移植的正确性;同时针对ARM7体系结构的特点,利用2个宏,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL)选择了开/关中断方式。

2.OS_CPU_C.C的相应修改

OS_CPU_C.C包括了10个与操作系统相关的用C语言编写的函数:

OSTaskStklnit(),OSTaskCre-ateHook(),OSTaskDelHook(),OSTaskSwHook(),OSTaskIdleHook(),OSTaskStatHook(),OS-TimeTickHook),OSInitHookBegin),OSInitHook-End(),OSTCBInitHook()。

OSTaskStklnit()函数是系统运行时必须调用的,初始化任务的栈结构,

针对ARM7体系结构的特点进行初始化栈,将所有寄存器保存在堆栈中;后9个函数是钩子函数,可以不加代码,只需声明即可。

3.OS_CPU_ASM.S的相应修改

OS_CPU_ASM.S包括了4个与操作系统和微处理器硬件相关的用汇编语言编写的函数:

OS-StartHighRdy),OSCtxsw(),OSIntCtxSw),0-STickISR()。

OSStartHighRdy)函数使系统运行优先级最高的就绪任务;因为使用了软中断指令SWI,所以可将OSCtxsw)函数和OSIntCtxSw)函数用一段代码实现,完成中断任务的堆栈操作;OSTickISR()函数提供一个周期性的时钟源,实现时间的延迟和超时功能。

UCOS软件工程

思路分析

(一)从main函数开始,UC/OS-IImain函数的大致流程如下:

main(){

BSP_IntDisAll();

 OSInit();

 TaskCreate();

 OSStart();

}

首先调用BSP_IntDisAll()关闭所有中断和OSInit进行初始化,然后使用TaskCreate创建几个进程/Task,最后调用OSStart,操作系统就开始运行了。

OSInit

OSInit完成以下初始化:

voidOSInit(void)

{

OSInitHookBegin();/*Callportspecificinitializationcode*/

OS_InitMisc();/*Initializemiscellaneousvariables*/

OS_InitRdyList();/*InitializetheReadyList*/

OS_InitTCBList();/*InitializethefreelistofOS_TCBs*/

OS_InitEventList();/*InitializethefreelistofOS_EVENTs*/

(OS_FLAG_EN>0)&&(OS_MAX_FLAGS>0)

OS_FlagInit();/*Initializetheeventflagstructures*/

#endif

#if(OS_MEM_EN>0)&&(OS_MAX_MEM_PART>0)

OS_MemInit();/*Initializethememorymanager*/

#endif

#if(OS_Q_EN>0)&&(OS_MAX_QS>0)

OS_QInit();/*Initializethemessagequeuestructures*/

#endif

OS_InitTaskIdle();/*CreatetheIdleTask*/

#ifOS_TASK_STAT_EN>0

OS_InitTaskStat();/*CreatetheStatisticTask*/

#endif

#ifOS_TMR_EN>0

OSTmr_Init();/*InitializetheTimerManager*/

#endif

OSInitHookEnd();/*Callportspecificinit.code*/

#ifOS_DEBUG_EN>0

OSDebugInit();

#endif

}

逐一分析:

1.OSInitHookBegin(void)在OS_CPU_C.C中

功能:

被OSInit()在开始的时候调用,是系统初始化开始接口函数

2.OS_InitMisc(void)在OS_CORE.C中

功能:

完成的是一些其他变量的初始化:

   OSIntNesting =0;                                    

   OSLockNesting=0;                                    

   OSTaskCtr    =0;                                    

   OSRunning    =OS_FALSE;                                

   OSCtxSwCtr   =0;                                    

   OSIdleCtr    =0L;                                   

其中包括:

中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS标志OSRunning等。

OSRunning在这里设置为OS_FALSE,在后面(OS_CPU_A.ASM内)OSStartHighRdy中会被设置为TRUE表示OS开始工作。

3.OS_InitRdyList(void)在OS_CORE.C中

功能:

初始化就绪Task列表

staticvoidOS_InitRdyList(void)

{

INT8Ui;

#ifOS_LOWEST_PRIO<=63

INT8U*prdytbl;

#else

INT16U*prdytbl;

#endif

OSRdyGrp=0;/*Clearthereadylist*/

prdytbl=&OSRdyTbl[0];

for(i=0;i

*prdytbl++=0;

}

OSPrioCur=0;

OSPrioHighRdy=0;

OSTCBHighRdy=(OS_TCB*)0;

OSTCBCur=(OS_TCB*)0;

}

首先将OSRdyTbl[]数组中全部初始化0,同时将OSPrioCur/OSTCBCur初始化为0,OSPrioHighRdy/OSTCBHighRdy也初始化为0。

4.OS_InitTCBList(void)在OS_CORE.C中

功能:

初始化TCB列表

static void OS_InitTCBList(void)

{

   INT8U   i;

   OS_TCB *ptcb1;

   OS_TCB *ptcb2;

   OS_MemClr((INT8U*)&OSTCBTbl[0],    sizeof(OSTCBTbl));     

   OS_MemClr((INT8U*)&OSTCBPrioTbl[0],sizeof(OSTCBPrioTbl)); 

   ptcb1=&OSTCBTbl[0];

   ptcb2=&OSTCBTbl[1];

   for(i=0;i<(OS_MAX_TASKS+OS_N_SYS_TASKS-1);i++){ 

       ptcb1->OSTCBNext=ptcb2;

#ifOS_TASK_NAME_SIZE>1

       ptcb1->OSTCBTaskName[0]='?

';                          

       ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;

#endif

       ptcb1++;

       ptcb2++;

   }

   ptcb1->OSTCBNext=(OS_TCB*)0;                             

#ifOS_TASK_NAME_SIZE>1

   ptcb1->OSTCBTaskName[0]='?

';                              

   ptcb1->OSTCBTaskName[1]=OS_ASCII_NUL;

#endif

   OSTCBList              =(OS_TCB*)0;                      

   OSTCBFreeList          =&OSTCBTbl[0];

}

首先把整个数组使用OSTCBNext指针连接成链表链起来,然后将OSTCBList初始化为0,也就是还没有TCB,因为还没有Task产生,OSTCBFreeList指向OSTCBTbl[]数组的第一个表示所有TCB都处于Free状态。

5.OS_InitEventList()在OS_CORE.C中

功能:

初始化Event列表。

static void OS_InitEventList(void)

{

#ifOS_EVENT_EN&&(OS_MAX_EVENTS>0)

#if(OS_MAX_EVENTS>1)

   INT16U    i;

   OS_EVENT *pevent1;

   OS_EVENT *pevent2;

   OS_MemClr((INT8U*)&OSEventTbl[0],sizeof(OSEventTbl));

   pevent1=&OSEventTbl[0];

   pevent2=&OSEventTbl[1];

   for(i=0;i<(OS_MAX_EVENTS-1);i++){            

       pevent1->OSEventType   =OS_EVENT_TYPE_UNUSED;

       pevent1->OSEventPtr    =pevent2;

#ifOS_EVENT_NAME_SIZE>1

       pevent1->OSEventName[0]='?

';                     

       pevent1->OSEventName[1]=OS_ASCII_NUL;

#endif

       pevent1++;

       pevent2++;

   }

   pevent1->OSEventType           =OS_EVENT_TYPE_UNUSED;

   pevent1->OSEventPtr            =(OS_EVENT*)0;

#ifOS_EVENT_NAME_SIZE>1

   pevent1->OSEventName[0]        ='?

';                 

   pevent1->OSEventName[1]        =OS_ASCII_NUL;

#endif

   OSEventFreeList                =&OSEventTbl[0];

#else

   OSEventFreeList                =&OSEventTbl[0];      

   OSEventFreeList->OSEventType   =OS_EVENT_TYPE_UNUSED;

   OSEventFreeList->OSEventPtr    =(OS_EVENT*)0;

#ifOS_EVENT_NAME_SIZE>1

   OSEventFreeList->OSEventName[0]='?

';                 

   OSEventFreeList->OSEventName[1]=OS_ASCII_NUL;

#endif

#endif

#endif

}

将EventTbl[]数组中的OSEventType都初始化为OS_EVENT_TYPE_UNUSED。

OS_InitTaskIdle()

跳过其他的如Mem等的初始化,看看IdleTask的初始化。

   (void)OSTaskCreateExt(OS_TaskIdle,

                         (void*)0,                                

                         &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE-1],

                         OS_IDLE_PRIO,                             

                         OS_TASK_IDLE_ID,

                         &OSTaskIdleStk[0],                        

                         OS_TASK_IDLE_STK_SIZE,

                         (void*)0,                                

                         OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);

IdleTask的初始化是调用OSTaskCrete系列的函数创建一个Task

初始化StateTask也是类似调用OSTaskCreate系列函数创建StatTask。

这里只是创建了该Task的各个结构还没有真正运行该Task,直到OSStart中才依据优先级调度运行。

6.OS_FlagInit()

OS_FlagInit()是uc/os内部函数,应用程序不得调用该函数

7.OS_MemInit()

OS_MemInit()作用是初始化动态内存

(二)

OSTaskCreateExt 

OSTaskCreateExt负责创建Task所需的数据结构,该函数原形如下所示:

OSTaskCreateExt((void(*)(void*))App_TaskStart,/*指向任务代码指针*/

(void*)0,/*指向一个传递参数的数据块*/

(OS_STK*)&App_TaskStartStk[APP_CFG_TASK_START_STK_SIZE-1],/*指向堆栈栈顶*/

(INT8U)APP_CFG_TASK_START_PRIO,/*任务优先级*/

(INT16U)APP_CFG_TASK_START_PRIO,/*任务标示(暂时不用的)*/

(OS_STK*)&App_TaskStartStk[0],/*指向栈底*/

(INT32U)APP_CFG_TASK_START_STK_SIZE,/*堆栈大小*/

(void*)0,/*定义数据指针*/

(INT8U)(OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR));/*进行任务堆栈检查,清空堆栈*/

OSTaskCreateExt函数的执行流程:

(在OS_TASK.C中)

#ifOS_ARG_CHK_EN>0

   if(prio>OS_LOWEST_PRIO){            

       if(prio>OS_LOWEST_PRIO);

   }

#endif

   OS_ENTER_CRITICAL();

   if(OSIntNesting>0){                 

       OS_EXIT_CRITICAL();

       return(OS_ERR_TASK_CREATE_ISR);

   }

   if(OSTCBPrioTbl[prio]==(OS_TCB*)0){

       OSTCBPrioTbl[prio]=(OS_TCB*)1;   

                                            

       OS_EXIT_CRITICAL();

       psp=OSTaskStkInit(task,p_arg,ptos,0);

       err=OS_TCBInit(prio,psp,(OS_STK*)0,0,0,(void*)0,0);

       if(err==OS_ERR_NONE){

           if(OSRunning==OS_TRUE){        

               OS_Sched();

           }

       }else{

           OS_ENTER_CRITICAL();

           OSTCBPrioTbl[prio]=(OS_TCB*)0;

           OS_EXIT_CRITICAL();

       }

       return(err);

   }

   OS_EXIT_CRITICAL();

   return(OS_PRIO_EXIST);

OS_LOWEST_PRIO在ucos-ii.h中被定义为63,表示Task的优先级从0到63,共64级。

首先判断prio是否超过最低优先级,如果是,则返回OS_PRIO_INVALID错误。

然后调用OS_ENTER_CRITICAL(),进入临界段,在临界段中的代码执行不允许被中断。

这个宏是自定义的,一般是进行关中断操作。

这个宏和OS_EXIT_CRITICAL()相对应,这个宏表示离开临界段。

OSTaskCreate不允许在中断中调用,因此会判断OSIntNesting是否大于0,如果大于0,表示正在中断嵌套,返回OS_ERR_TASK_CREATE_ISR错误。

接着判断该prio是否已经有Task存在,由于uC/OS-II只支持每一个优先级一个Task,因此如果该prio已经有进程存在,OSTaskCreate会返回OS_PRIO_EXIST错误。

相反,如果该prio先前没有Task存在,则将OSTCBPrioTbl[prio]置1,表示该prio已被占用,然后调用OSTaskStkInit初始化堆栈,调用OS_TCBInit初始化TCB,如果OSRunning为TRUE表示OS正在运行,则调用OS_Sched进行进程调度;否则返回。

关于OSTaskStkInit和OS_TCBInit这两个函数。

OSTaskStkInit是一个用户自定义的函数,因为uC/OS-II在设计时无法知道当前处理器在进行进程调度时需要保存哪些信息,OSTaskStkInit就是初始化堆栈,让Task看起来就好像刚刚进入中断并保存好寄存器的值一样,当OS_Sched调度到该Task时,只需切换到该堆栈中,将寄存器值Pop出来,然后执行一个中断返回指令IRET即可。

OSTaskStkInit的原型如下:

OS_STK*OSTaskStkInit(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT16Uopt)

和OSTaskCreate类似,task是进程入口地址,pdata是参数地址,ptos是堆栈指针,而opt只是作为一个预留的参数Option而保留。

返回的是调整以后的堆栈指针。

在OSTaskStkInit中,一般是将pdata入栈,flag入栈,task入栈,然后将各寄存器依次入栈。

OS_TCBInit初始化TCB数据结构,下面只提取主要部分来看:

INT8U OS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt)

{

   OS_TCB   *ptcb;

  #ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr=0;

#endif

   OS_ENTER_CRITICAL();

   ptcb=OSTCBFreeList;                                 

   if(ptcb!

=(OS_TCB*)0){

       OSTCBFreeList       =ptcb->OSTCBNext;           

       OS_EXIT_CRITICAL();

       ptcb->OSTCBStkPtr   =ptos;                      

       ptcb->OSTCBPrio     =prio;                      

       ptcb->OSTCBStat     =OS_STAT_RDY;               

       ptcb->OSTCBStatPend=

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2