操作系统移植_第1页
操作系统移植_第2页
操作系统移植_第3页
操作系统移植_第4页
操作系统移植_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、UC/OS-II的启动过程和在ARM7上的移植主讲:王华斌一、UC/OS-II的启动过程v典型启动过程如下:1、程序进入main函数以后,首先执行OSInit()函数,来初始化OS所有的变量和数据结构。同时OSInit还创建空闲任务和统计任务。2、在初始化之后,用户至少要创建一个任务,来保证多任务系统的正确启动,另外,用户还可以在此创建其他系统资源,如信号量、邮箱等,或者可能用户还需要在此完成UC运行环境的一些初始化工作,如系统时间的设置、处理器的设置、外围器件的设置等。OS初始化OSInit()创建任务、信号量等;必要的初始化工作多任务启动OSStart() Main()v3、在上述工作完成

2、之后,程序调用OSStart函数来启动多任务操作系统,此函数将启动已经创建的任务中的处于就绪态的优先级最高的任务。 在该任务中,用户需要启动时钟节拍、可以初始化统计任务、创建其他任务、信号量、邮箱等然后进入无线循环的函数主体。启动时钟节拍创建任务、信号量等;必要的初始化工作进入函数主体TaskHighRdy()程序范例:OS_STK Task1Stk1024;OS_STK Task2Stk1024;Void main()OSInit(); /初始化UC/OS-IIOSTaskCreate(Task1, (void *)0, &Task1Stk1023, 0); /创建任务1OSTime

3、Set(0); /设置系统时间OSStart(); /启动Static void Task1(void *p_arg)INT8U err;(void) p_arg; /去除编译器报警错误System_Init(); /硬件系统设置TickTimerStart(); /启动TickOSTaskCreate(Task2, (void *)0, &Task2Stk1023, 10); /创建任务1OSStatInit() / 初始化统计任务for( ; ; ) /进入无限循环 ;二、UC/OS-II的移植v1、UC/OS-II的体系结构a、处理器无关的代码提供了OS大部分的资源,实现了任务管

4、理、时 间管理等功能;b、处理器相关的代码移植的重点,它提供了OS和硬件平台的接口, 操作系统运行过程中需要的一些操作,如任务切换时 的堆栈操作等,都在这部分代码中实现;c、系统配置代码定义了一些配置UC的选项。v2、移植条件vUC/OS-II并不是能移植到所有处理器上,它要求目标处理器必须满足一定的条件:(1)处理器的C编译器能产生可重入代码(2)支持使用C语言来打开和禁止中断(3)处理器支持中断,并且能产生定时中断(4)支持能够容纳一定数量的硬件堆栈(5)处理器有将堆栈指针和其它CPU寄存器读出并存储到堆栈或内存中的指令。 尽管目前大部分处理器都满足以上5个条件,但是在移植之前,用户有必要

5、进行仔细确认。v3、移植内容、移植内容涉及3个文件(1)OS_CPU.H 处理器相关数据类型的定义,3个宏定义(中断开关、堆栈属性和任务切换)(2)OS_CPU_C.C 主要是任务堆栈初始化和OS功能扩展等函数。(3)OS_CPU_A.ASM 编写4个汇编程序,完成任务执行、任务切换、Tick时钟、ISR的相关处理。(1)OS_CPU.Hv编译器相关的数据类型定义编译器相关的数据类型定义为了移植方便,UC/OS-II没有直接采样编译器相关的数据类型定义,如shortintlong等,而是通过typedef定义了统一的数据类型,如INT16U数据类型总是代表16位的无符号整数。 typedef

6、unsigned char BOOLEAN; typedef unsigned char INT8U; /* 无符号8位数*/ typedef signed char INT8S; /* 带符号8位数 */typedef unsigned short INT16U; /* 无符号16位数*/typedef signed short INT16S; /* 带符号16位数*/typedef unsigned int INT32U; /* 无符号32位数*/typedef signed int INT32S; /* 带符号32位数*/typedef float FP32; /* 单精度浮点数 */t

7、ypedef double FP64; /* 双精度浮点数*/typedef unsigned int OS_STK; /* 堆栈入口宽度为32位*/v堆栈生长方向堆栈生长方向UC/OS-II使用常量OS_STK_GROWTH来定义堆栈的生长方向。OS_STK_GROWTH=0 :堆栈从低往高长OS_STK_GROWTH=1 :堆栈从高往低长ARM的堆栈是从上往下长的:的堆栈是从上往下长的: #define OS_STK_GROWTH 1;v开关中断的宏定义开关中断的宏定义UC/OS-II定义了两个宏来禁止和允许中断:OS_ENTER_CRITICAL():关中断:关中断OS_EXIT_CRI

8、TICAL(): 开中断开中断在在OS_CPU.H中需要给出这两个中需要给出这两个宏定义宏定义:#define OS_CRITICAL_METHOD 2#define OS_ENTER_CRITICAL() ARMIntClose()#define OS_EXIT_CRITICAL() ARMIntOpen() ( ARMIntClose()关中断函数和关中断函数和ARMIntOpen()开中开中断函数将在断函数将在OS_CPU_A.S文件中编写文件中编写 )v任务切换任务切换OS_TASK_SW()它通常通过OS_CPU_A.S文件中任务级切任务级切换函数换函数OSCtxSw()来完成。宏定

9、义如下:宏定义如下: #define OS_TASK_SW() OSCtxSw()v除了上述的几处定义和修改外,还需要对OSCtxSw(),ARMIntClose(), ARMIntOpen()等函数进行声明,用户还可以根据需要,定义一些自己的常量、宏等。(2)OS_CPU_C.Cv最主要的函数:OSTaskStkInit(),它在任务建立的时候,用来初始化任务的堆栈结构。v其他的若干个函数都是用来扩展UC/OS-II功能的Hook程序,OS要求它们必须得到声明,但可以没有任何代码。(注意:只要当OS_CFG.H文件中的OS_CPU_HOOKS_EN为1时才会产生这些HOOK代码)vOSTas

10、kStkInit()创建任务函数通过调用OSTaskStkInit()来初始化任务的堆栈结构堆栈结构,并返回新的堆栈指针stk。当中断发生时,当前的寄存器状态将被压入堆栈,由高至低高至低依次保存程序计数器PC、链接寄存器LR、寄存器R12-R0、程序状态寄存器CPSR和SPSR。了解了ARM中断时的堆栈结构,就可以完成OSTaskStkInit()的修改:SPSRCPSRR0R12LrPCOsEnterSumR11高地址低地址增长方向由于编译器ADS仅支持堆栈从上往下长,并且必须是满递减堆栈,所以文件中用来定义堆栈增长方式的常量OS_STK_GROWTH的值应该为1.SPvoid *OSTas

11、kStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U opt) INT16U *stk; opt = opt; /* opt未使用,此处可防止编译器的警告 */ stk = ptos; /* 载入堆栈指针*/ /*建立堆栈空间的结构*/ *stk= (OS_STK) task; /* PC */ *-stk= (OS_STK) task; /* LR */ *-stk= 0; /* r12 */ *-stk= 0; /* r11 */ *-stk= 0; /* r10 */ *-stk= 0; /* r9 */ *-

12、stk= 0; /* r8 */ *-stk= 0; /* r7 */ *-stk= 0; /* r6 */ *-stk= 0; /* r5 */ *-stk= 0; /* r4 */ *-stk= 0; /* r3 */ *-stk= 0; /* r2 */ *-stk= 0; /* r1 */ *-stk= (unsigned int)pdata; /* r0 */ *-stk= (SVC32MODE|0 x0); /* CPSR IRQ */ *-stk= (SVC32MODE|0 x0); /* SPSR IRQ */ return (void *)stk); / 返回堆栈指针如果用户

13、的任务运行在SVC模式下,那么堆栈中就没有必要保存SPSR寄存器。因为任务运行在此模式时,只能被中断进入其它模式,而从不用返回到其它模式中去,SPSR寄存器并没有被使用。OSTaskCreateHook()此函数在任务建立的时候,呗此函数在任务建立的时候,呗OSTaskCreate()函数所函数所调用,以允许用户添加与移植有关的代码,或者扩展一些功调用,以允许用户添加与移植有关的代码,或者扩展一些功能。函数原型:能。函数原型:Void OSTaskCreateHook (OS_TCB *ptcb)参数参数ptcb指向已建立任务的指向已建立任务的OS_TCB的指针。的指针。OSTaskDelHo

14、ok() 在任务被删除的时候调用,其参数也是指向正被删除任务的OS_TCB指针。OSTaskSwHook()在发生任务切换的时候被调用,它允许用户进行任务运行时间的计算等一些扩展操作。此函数是在中断被禁止的条件运行的OSTaskStatHook()每秒钟都会被OSTaskStat()函数调用一次。OSTimeTickHook()在每个时钟节拍中被OSTaskTick()函数调用。(3)OS_CPU_A.ASMvOS_CPU_A.ASM文件的汇编程序是移植中的重点和难点。通常包括:OSStartHighRdy();OSCtxSw();OSIntCtxSw();OSTickISR();开启和关闭中

15、断的代码。针对不同的编译器,OS_CPU_A.ASM文件的后缀名需要改为编译器支持的汇编文件类型,如在ADS和SDT中是.s后缀。OSStartHighRdy()v此函数被操作系统启动函数OSStart()调用,来启动在启动函数运行之前已经处于就绪态的、具有最高优先级的任务。vOSStartHighRdy()的主要工作:将优先级最高的任务对应的所有处理器寄存器按顺序从任务堆栈中恢复出来,并且执行中断的返回。UC/OS-II使用变量OSTCBHighRdy指向的是优先级最高的任务的任务控制块,而堆栈地址在任务控制块的起始地址,所以OSStartHighRdy()函数可以通过这个变量获取优先级最高

16、的任务的堆栈地址。此外他还需要调用OSTaskSwHook()函数,并且调用之后,在优先级最高的任务启动之前,将变量OSRunning设为True,表示OS在运行。vOSStartHighRdy()函数的基本运行流程:函数的基本运行流程:(1)调用OSTaskSwHook()函数;(2)将变量OSRunning设为True;(3)得到优先级最高任务的堆栈指针;(4)恢复优先级最高的任务的处理器寄存器;(5)中断返回以启动优先级最高的任务。此函数的源代码如下:IMPORT OSTaskSwHook /引入相关的函数和变量IMPORT OSTCBHighRdyIMPORT OSRunning EX

17、PORT OSStartHighRdy OSStartHighRdyBLOSTaskSwHook ;调用OSTaskSwHook()LDRR4, =OSRunningMOVR5, #1STRBR5,R4 ;OSRunning=1 LDRR4, =OSTCBHighRdyLDRR4, R4LDRSP, R4 / 得到优先级最高的任务的堆栈指针/*恢复优先级最高的任务的堆栈指针恢复优先级最高的任务的堆栈指针*/LDRR4, sp, #4 /先把SP指向的地址中的数据给了 /R4,然后用SP+4 (SP指向的是栈顶SPSR)MSRSPSR_cxsf,R4 ;恢复SPSRLDRR4, sp, #4MS

18、RCPSR_cxsf,R4 ;恢复CPSRLDMFDsp! RO-R12,lr,pc ;恢复其它寄存器和PC值,启动任务OSCtxSw()任务切换函数vOSCtxSw()是一个任务级的任务切换函数,在任务需要进行切换时被OS_CPU.H文件中的宏定义OS_TASK_SW调用,由于此时的任务切换都是在非异常模式下进行的,因此区别于中断级别的任务切换。v主要工作:先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行。OSCtxSw()的基本运行流程:v保存处理器的寄存器到当前任务的堆栈中;v将当前的堆栈地址保存到该任务的任务控

19、制块OS_TCB中;v调用OSTaskSwHook()函数v设置当前任务控制块指针OSTCBCur为OSTCBHighRdyv设置当前任务优先级OSPrioCur为OSPrioHighRdyv得到新任务的堆栈指针;v从新任务堆栈中恢复所有处理器寄存器;v中断返回以启动新任务。移植到ARM上的OSCtxSw()/引入相关的函数和变量EXPORT OSCtxSwIMPORT OSTaskSwHookIMPORT OSTCBHighRdyIMPORT OSPrioCur IMPORT OSPrioHighRdy OSCtxSw;保存当前处理器的寄存器STMFDSP!, LR ;保存当前的PC,其实就

20、是任务返回地址LRSTMFDSP!, R0-R12,LR;LR和其它寄存器入栈MRSR0, CPSR STMFDSP!, R0;CPSR入栈MRSR0, SPSR STMFDSP!, R0;SPSR入栈;把SP保存在当前任务的控制块中LDRR1,=OSTCBCurLDRR1,R1STRSP,R1;调用OSTaskSwHook()BLOSTaskSwHook;设置当前任务控制块指针为OSTCBHighRdyLDRR1,=OSTCBCurLDRR2,=OSTCBHighRdy LDRR2,R2 STRR2,R1 ;R1现在存的是上面的OSTCBCur;设置当前任务优先级为 OSPrioHighRd

21、yLDRR3,=OSPrioCurLDRR4,=OSPrioHighRdy LDRBR4,R4 STRBR4,R3;得到新任务的堆栈指针LDRSP,R2;从新任务堆栈中恢复所有处理器寄存器LDRR1, sp, #4 /先把数据给R1然后用SP+4 (SP指向的是栈顶SPSR)MSRSPSR_cxsf,R1 ;恢复SPSRLDRR1, sp, #4MSRCPSR_cxsf,R1 ;恢复CPSRLDMFDsp! RO-R12,lr,pc ;恢复其它寄存器和 PC值,启动任务OSIntCtxSw()中断级任务切换函数vOSIntCtxSw()负责在中断服务程序退出时,完成必要的任务切换。v在UC/O

22、S-II中,当中断服务程序完成的时候,它会调用OSIntExit()函数来判断是否存在优先级更高的任务处于就绪态。如果存在, OSIntExit()函数就会函数就会调用调用OSIntCtxSw()来完成任务的切换来完成任务的切换。vOSIntCtxSw()函数的原理基本上和任务级的切换函数OSCtxSw()相同,但是由于进入中断时,已经保存过了被中断任务的CPU现场,因此不必再进行类似的操作,只需要调整堆栈指针。v调用调用OSIntCtxSw()函数的时候,堆栈的情况:函数的时候,堆栈的情况:堆栈的底层部分(高地址)是进入中断时保存的处理器状态寄存器、中断返回地址和其它寄存器。然后顶层部分是分

23、别调用OSIntExit()和OSIntCtxSw()函数时保存的程序返回地址和状态寄存器。因此OSCtxSw()函数只需要调整堆栈指针,保存所需的任务信息(顶层部分)即可。 OSIntCtxSw()函数的返回地址处理器状态寄存器OSIntExit()函数的返回地址CPU寄存器中断返回地址处理器状态寄存器OSIntCtxSw()函数的基本运行流程:v调整堆栈指针,清除多余信息;调整堆栈指针,清除多余信息;v将当前堆栈地址保存到该任务的任务控制块中;v调用OSTaskSwHook()函数;v设置当前任务控制块指针OSTCBCur为OSTCBHighRdy;v设置当前任务优先级OSPrioCur为

24、OSPrioHighRdyv得到新任务的堆栈指针;v从新任务堆栈中恢复所有处理器寄存器;v中断返回以启动新任务。v注: OSIntCtxSw()函数的基本运行流程除了第一步,其它与OSCtxSw()函数一致。用户可以共享其中的大部分代码。v堆栈指针的调整与编译器的属性和设置等参数有很大关系,对于堆栈指针的调整与编译器的属性和设置等参数有很大关系,对于ARM内内核来说,核来说,ARM硬件在中断时并不自动压栈任何寄存器,这样就免去了调硬件在中断时并不自动压栈任何寄存器,这样就免去了调整堆栈的工作,所以整堆栈的工作,所以OSIntCtxSw()函数实际上是函数实际上是OSCtxSw()函数的子函数的子集。集。vOSIntCtxSw()函数的代码如下:;调用钩子函数 BLOSTaskSwHook;设置当前任务控制块指针为OSTCBHighRdyLDRR1,=OSTCBCurLDRR2,=OSTCBHighRdy LDRR2,R2 STRR2,R1 ;R1现在存的是上面的 OSTCBCur;设置当前任务优先级为 OSPrioHighRdyLDRR3,=OSPrioCurLDRR4

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论