移植μCOS-Ⅱ.ppt

上传人:ga****84 文档编号:453291 上传时间:2018-10-08 格式:PPT 页数:32 大小:540.50KB
下载 相关 举报
移植μCOS-Ⅱ.ppt_第1页
第1页 / 共32页
移植μCOS-Ⅱ.ppt_第2页
第2页 / 共32页
移植μCOS-Ⅱ.ppt_第3页
第3页 / 共32页
移植μCOS-Ⅱ.ppt_第4页
第4页 / 共32页
移植μCOS-Ⅱ.ppt_第5页
第5页 / 共32页
点击查看更多>>
资源描述

1、移植C/OS-,C/OS-的移植,移植就是使一个实时内核能在某个微处理器或微控制器上运行。为了方便移植,大部分的C/OS-代码是用C语言写的;但仍需要用C和汇编语言写一些与处理器相关的代码,这是因为C/OS-在读写处理器寄存器时只能通过汇编语言来实现。由于C/OS-在设计时就已经充分考虑了可移植性,所以C/OS-的移植相对来说是比较容易的。,C/OS-的移植,要使C/OS-正常运行,处理器必须满足以下要求:1.处理器的C编译器能产生可重入代码。2.用C语言就可以打开和关闭中断。3. 处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)。4. 处理器支持能够容纳一定量数据(可能是几千

2、字节)的硬件堆栈。5.处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。像Motorola 6805系列的处理器不能满足上面的第4条和第5条要求,所以C/OS-不能在这类处理器上运行。,C/OS-的结构以及与硬件的关系,C/OS-的移植,移植工作包括以下几个内容:用#define设置一个常量的值(OS_CPU.H)声明10个数据类型(OS_CPU.H)用#define声明三个宏(OS_CPU.H)用C语言编写六个简单的函数(OS_CPU_C.C)编写四个汇编语言函数(OS_CPU_A.ASM)根据处理器的不同,一个移植实例可能需要编写或改写50至300行的代码。,C/OS-的

3、移植,一旦代码移植结束,下一步工作就是测试。测试一个象C/OS-一样的多任务实时内核并不复杂。甚至可以在没有应用程序的情况下测试,就是让内核自己测试自己。这样做有两个好处:第一,避免使本来就复杂的事情更加复杂;第二,如果出现问题,可以知道问题出在内核代码上而不是应用程序。开始测试的时候可以运行一些简单的任务和时钟节拍中断服务例程。一旦多任务调度成功地运行了,再添加应用程序的任务就是非常简单的工作了。,移植开发工具,移植C/OS-需要一个C编译器,并且是针对用户用的CPU的。因为C/OS-是一个可剥夺型内核,用户只有通过C编译器来产生可重入代码;C编译器还要支持汇编语言程序。绝大部分的C编译器都

4、是为嵌入式系统设计的,它包括汇编器、连接器和定位器。连接器用来将不同的模块(编译过和汇编过的文件)连接成目标文件,定位器则允许用户将代码和数据放置在目标处理器的指定内存映射空间中。所用的C编译器还必须提供一个机制来从C中打开和关闭中断。,移植目录结构和文件,各个微处理器的移植源代码必须在以下两个或三个文件中找到:OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM。汇编语言文件OS_CPU_A.ASM是可选择的,因为某些C编译器允许用户在C语言中插入汇编语言,所以用户可以将所需的汇编语言代码直接放到OS_CPU_C.C中。一个放置移植实例的目录结构如表所示。这样的目录结构,使用户更

5、容易找到目标处理器的文件。,INCLUDES.H文件,INCLUDES.H是一个头文件,它在所有.C文件的第一行被包含。#include includes.hINCLUDES.H使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。使用INCLUDES.H的唯一缺点是它可能会包含一些实际不相关的头文件,这样每个文件的编译时间可能会增加,但是它增强了代码的可移植性。用户可以通过编辑INCLUDES.H来增加自己的头文件,但是用户的头文件必须添加在头文件列表的最后。,OS_CPU.H文件,#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT#else#defi

6、ne OS_CPU_EXT extern#endif/* 数据类型 (与编译器相关)*/typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /* 无符号8位整数 (1)/整型数据结构既是可移植的又是直观的 typedef signed char INT8S; /* 有符号8位整数typedef unsigned int INT16U; /* 无符号16位整数typedef signed int INT16S; /* 有符号16位整数typedef unsigned long INT32U; /* 无符号32位整数typedef

7、signed long INT32S; /* 有符号32位整数typedef float FP32; /* 单精度浮点数 (2)/浮点数据类型 typedef double FP64; /* 双精度浮点数 typedef unsigned int OS_STK; /* 堆栈入口宽度为16位,用户所必须要做的就是查看编译器手册,并找到对应于C/OS-的标准C数据类型。,OS_CPU.H文件(续),/* 与处理器相关的代码*/#define OS_ENTER_CRITICAL() ? /* 禁止中断 */ (3)#define OS_EXIT_CRITICAL() ? /* 允许中断 */#def

8、ine OS_STK_GROWTH 1 /* 定义堆栈的增长方向: 1=向下, 0=向上 */(4)/绝大多数的微处理器和微控制器的堆栈是从上往下长的,但是某些处理器是用另外一种方式工作的。C/OS-被设计成两种情况都可以处理。#define OS_TASK_SW() ? (5)/C/OS-从低优先级任务切换到最高优先级任务时调用OS_TASK_SW() 。任务切换只是简单的将处理器寄存器保存到将被挂起的任务的堆栈中,并且将更高优先级的任务从堆栈中恢复出来。,上述代码中的?部分,对于不同的微处理器来说,都不一样。例如通过执行STI命令在Intel 80186上禁止中断,并用CLI命令来允许中断

9、。#define OS_ENTER_CRITICAL() asm CLI#define OS_EXIT_CRITICAL() asm STI,OS_CPU_A.ASM文件,C/OS-的移植实例要求用户编写四个简单的汇编语言函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OSTickISR()如果用户的编译器支持插入汇编语言代码的话,用户就可以将所有与处理器相关的代码放到OS_CPU_C.C文件中,而不必再拥有一些分散的汇编语言文件。,OSStartHighRdy(),void OSStartHighRdy (void) Call user definabl

10、e OSTaskSwHook(); Get the stack pointer of the task to resume: Stack pointer = OSTCBHighRdy-OSTCBStkPtr; OSRunning = TRUE; Restore all processor registers from the new tasks stack; Execute a return from interrupt instruction; ,要想运行最高优先级任务,用户所要做的是将所有处理器寄存器按顺序从任务堆栈中恢复出来,并且执行中断的返回。,注意:OSStartHighRdy()必

11、须调用OSTaskSwHook(),因为用户正在进行任务切换的部分工作用户在恢复最高优先级任务的寄存器。而OSTaskSwHook()可以通过检查OSRunning来知道是OSStartHighRdy()在调用它(OSRunning为FALSE)还是正常的任务切换在调用它(OSRunning为TRUE)。OSStartHighRdy()还必须在最高优先级任务恢复之前和调用OSTaskSwHook()之后设置OSRunning为TRUE。,OSCtxSw(),任务级的切换问题是通过发软中断命令或依靠处理器执行陷阱指令来完成的。中断服务例程,陷阱或异常处理例程的向量地址必须指向OSCtxSw()。

12、如果当前任务调用C/OS-提供的系统服务,并使得更高优先级任务处于就绪状态,C/OS-就会借助上面提到的向量地址找到OSCtxSw()。在系统服务调用的最后,C/OS-会调用OSSched(),并由此来推断当前任务不再是要运行的最重要的任务了。OSSched()先将最高优先级任务的地址装载到OSTCBHighRdy中,再通过调用OS_TASK_SW()来执行软中断或陷阱指令。注意:变量OSTCBCur早就包含了指向当前任务的任务控制块(OS_TCB)的指针。软中断 (或陷阱) 指令会强制一些处理器寄存器(比如返回地址和处理器状态字)到当前任务的堆栈中,并使处理器执行OSCtxSw()。,OSC

13、txSw()的原型程序,void OSCtxSw(void) 保存处理器寄存器; 将当前任务的堆栈指针保存到当前任务的OS_TCB中: OSTCBCur-OSTCBStkPtr = Stack pointer; 调用用户定义的OSTaskSwHook(); OSTCBCur = OSTCBHighRdy; OSPrioCur = OSPrioHighRdy; 得到需要恢复的任务的堆栈指针: Stack pointer = OSTCBHighRdy-OSTCBStkPtr; 将所有处理器寄存器从新任务的堆栈中恢复出来; 执行中断返回指令; ,上述这些代码必须写在汇编语言中,因为用户不能直接从C中

14、访问CPU寄存器。注意在OSCtxSw()和用户定义的函数OSTaskSwHook()的执行过程中,中断是禁止的。,OSIntCtxSw(),OSIntExit()通过调用OSIntCtxSw()来从ISR中执行切换功能,所有的处理器寄存器都被正确地保存到了被中断的任务的堆栈之中。实际上除了我们需要的东西外,堆栈结构中还有其它的一些东西。OSIntCtxSw()必须要清理堆栈,这样被中断的任务的堆栈结构内容才能满足我们的需要。,在ISR执行过程中的堆栈内容,当中断来临的时候,处理器会结束当前的指令,识别中断并且初始化中断处理过程,包括将处理器的状态寄存器和返回被中断的任务的地址保存到堆栈中(1

15、)。接着,CPU会调用正确的ISR,要求用户的ISR在开始时要保存剩下的处理器寄存器(2)。C/OS-要求用户的ISR在完成中断服务的时候调用OSIntExit(),导致调用者的返回地址被保存到被中断的任务的堆栈中(3)。处理器的状态寄存器会被保存到被中断的任务的堆栈中(4)。调用OSIntCtxSw()使返回地址被保存到被中断的任务的堆栈中(5)。,OSIntCtxSw()的原型程序,void OSIntCtxSw(void) 调整堆栈指针来去掉在调用: OSIntExit(), OSIntCtxSw()过程中压入堆栈的多余内容; 将当前任务堆栈指针保存到当前任务的OS_TCB中: OSTC

16、BCur-OSTCBStkPtr = 堆栈指针; 调用用户定义的OSTaskSwHook(); OSTCBCur = OSTCBHighRdy; OSPrioCur = OSPrioHighRdy; 得到需要恢复的任务的堆栈指针: 堆栈指针 = OSTCBHighRdy-OSTCBStkPtr; 将所有处理器寄存器从新任务的堆栈中恢复出来; 执行中断返回指令; ,这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。,OSTickISR(),C/OS-要求用户提供一个时钟资源来实现时间的延时和期满功能。时钟节拍应该每秒钟发生10100次。可以使用硬件时钟,也可以从交流电中获得

17、50/60Hz的时钟频率。用户必须在开始多任务调度后(调用OSStart()后)允许时钟节拍中断。即用户应该在OSStart()运行后,C/OS-启动运行的第一个任务中初始化节拍中断。,时钟节拍ISR的原型程序,void OSTickISR(void)保存处理器寄存器; 调用OSIntEnter()或者直接将 OSIntNesting加1; 调用OSTimeTick(); 调用OSIntExit(); 恢复处理器寄存器; 执行中断返回指令; ,这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。,OS_CPU_C.C文件,C/OS-的移植实例要求用户编写六个简单的C函数:O

18、STaskStkInit()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook()、OSTimeTickHook()唯一必要的函数是OSTaskStkInit(),其它五个函数必须得声明但没必要包含代码。,OSTaskStkInit(),OSTaskCreate()和OSTaskCreateExt()通过调用OSTaskStkInit()来初始化任务的堆栈结构,因此,堆栈看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。,假定pdata会被编译器保存到堆栈中,OSTaskStkInit()就会简单的模仿

19、编译器的这种动作,将pdata保存到堆栈中(1)。处理器至少得将程序计数器的值(中断返回地址)和处理器的状态字存入堆栈(2)。接着,用户需要将剩下的处理器寄存器保存到堆栈中(3)。一旦用户初始化了堆栈,OSTaskStkInit()就需要返回堆栈指针所指的地址(4)。,OSTaskCreateHook(),当用OSTaskCreate()或OSTaskCreateExt()建立任务的时候就会调用OSTaskCreateHook(),该函数允许用户或使用用户的移植实例的用户扩展C/OS-的功能。当C/OS-设置完了自己的内部结构后,会在调用任务调度程序之前调用OSTaskCreateHook()

20、。该函数被调用的时候中断是禁止的,因此用户应尽量减少该函数中的代码以缩短中断的响应时间。,OSTaskDelHook(),当任务被删除的时候就会调用OSTaskDelHook()。该函数在把任务从C/OS-的内部任务链表中解开之前被调用。当OSTaskDelHook()被调用的时候,它会收到指向正被删除任务的OS_TCB的指针,这样它就可以访问所有的结构成员了。,OSTaskSwHook(),当发生任务切换的时候调用OSTaskSwHook()。不管任务切换是通过OSCtxSw()还是OSIntCtxSw()来执行的都会调用该函数。OSTaskSwHook()可以直接访问OSTCBCur 和O

21、STCBHighRdy,因为它们是全局变量。OSTCBCur指向被切换出去的任务的OS_TCB,而OSTCBHighRdy指向新任务的OS_TCB。注意在调用OSTaskSwHook()期间中断一直是被禁止的。因为代码的多少会影响到中断的响应时间,所以用户应尽量使代码简化。,OSTaskStatHook(),OSTaskStatHook()每秒钟都会被OSTaskStat()调用一次。用户可以用OSTaskStatHook()来扩展统计功能。例如,用户可以保持并显示每个任务的执行时间,每个任务所用的CPU份额,以及每个任务执行的频率等等。,OSTimeTickHook(),OSTaskTime

22、Hook()在每个时钟节拍都会被OSTaskTick()调用。实际上,OSTaskTimeHook()是在节拍被C/OS-真正处理,并通知用户的移植实例或应用程序之前被调用的。,OSTaskCreateHook(),void OSTaskCreateHook(OS_TCB *ptcb),OSTaskDelHook(),void OSTaskDelHook(OS_TCB *ptcb),OSTaskSwHook(),void OSTaskSwHook(void),OSTaskStatHook(),void OSTaskStatHook(void),OSTimeTickHook(),void OSTimeTickHook(void),

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文资料库 > 毕业论文

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。