收藏 分享(赏)

μCOS-II在S12单片机上的移植.doc

上传人:jinchen 文档编号:6612975 上传时间:2019-04-18 格式:DOC 页数:9 大小:206.10KB
下载 相关 举报
μCOS-II在S12单片机上的移植.doc_第1页
第1页 / 共9页
μCOS-II在S12单片机上的移植.doc_第2页
第2页 / 共9页
μCOS-II在S12单片机上的移植.doc_第3页
第3页 / 共9页
μCOS-II在S12单片机上的移植.doc_第4页
第4页 / 共9页
μCOS-II在S12单片机上的移植.doc_第5页
第5页 / 共9页
点击查看更多>>
资源描述

1、http:/C/OS-II 在 S12 单片机上的移植1 引言在采用前后台系统软件设计模式的嵌入式系统中,主程序是一个无限循环,单任务顺序执行,通过设置一个或多个中断来处理异步事件。这种系统对于简单的应用是可以的,但对于实时性要求比较高的、处理任务较多的应用,就会暴露出实时性差、系统可靠性低、稳定性差等缺点。C/OS-II 是一个源代码公开、可移植、可裁剪的实时多任务操作系统,具有低成本、稳定可靠、实时性好等优点,是专门针对微处理器和微控制器设计的实时内核,它的内核可以做到很小,很适合在单片机系统上移植。移植了 C/OS-II 的嵌入式系统可以使各个任务独立工作,互不干涉,很容易实现准时而且无

2、误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。本文选用飞思卡尔(Freescale)公司的 16 位单片机MC9S12DG128 作为硬件平台,针对 MC9S12DG128 的存储器组织和体系结构,对 C/OS-II 源代码作了相应的改写,最终实现了 C/OS-II 操作系统在 MC9S12DG128 上的移植。通过 C/OS-II 在MC9S12DG128 上的移植,可以掌握移植和测试 C/OS-II 的实质内容,同时也很容易将其移植到其它的CPU 平台上。2 MC9S12DG128 的体系结构(存储器的组织 )作者认为深刻理解 MC9S12DG128 微控制器的

3、体系结构和存储器组织是移植成功的一个关键步骤。MC9S12DG128 是 16 位的高性能单片机,它具有极低的电源功耗和可高达 25MHz 的内部总线频率,片内资源包括 1KB 的内部寄存器、8KB RAM、128KB FLASH、2KBEEPROM。MC9S12DG128 采用普林斯顿总线结构,程序存储器、数据存储器和 I/O 端口为统一编址方式,总的寻址空间为 64 KB,但DG128 内部有 128KB Flash,显然存储空间超过了 S12MCU 可寻址的 64KB 空间,因此引入了页面访问机制,S12CPU 在内存的$8000$BFFF 这一段开了一个窗口,这里有 8 个 16KB

4、的页面(其中$3E 和$3F 有固定地址 ),可以通过页面寄存器(PPAGE) 选择其中的一页。对于 64KB 以外的存储区,应用专用指令 CALL 调用子程序,然后通过 RTC 指令返回。http:/微控制器内部不同的存储器占用不同的存储空间,也就是说,不同的地址范围,它们均占据特定的地址空间,这些存储器和内部集成模块的地址分配并不是固定不变的,用户自己可以重新分配,但建不要轻易改动默认的映射空间,应直接采用默认地址映射空间。图 1 是 MC9S12DGl28 复位后的内存空间分配情况。其中,地址$0000$03FF 为 1KB 寄存器空间; $0000$1FFF 为 8KB RAM(可见

5、7KB);$0000$07FF 为2KBEEPROM(不可见 )。http:/图 1 MC9S12DGl28 复位后的内存空间分布情况可以通过设置 INITRG,INITRM ,INIteE 寄存器来重新分配各存储器的位置。这些寄存器只能写一次,建议在初始化时分配存储器的位置。如果映射出现地址重叠时,S12CPU 内部的优先级控制逻辑会自动屏蔽级别较低的资源,保留级别最高的资源。寄存器具有最高优先级,与其重叠的 RAM 和 EEPROM 此时无效。存储器的优先级如下表所列。3 C/OS-II 在 MC9S12DG128 上的移植C/OS-II 运行时要占用一部分 ROM 和 RAM 空间,但

6、C/OS-II 操作系统内核目标代码最小可以裁剪到小于 2KB,MC9S12DG128 有 8KB 的 RAM 存储器和 128KB 的 Flash 存储器,所以 C/OS-II 操作系统完全可以移植并运行在 MC9S12DG128 上。C/OS-II 的 95%代码是由 ANSI C 写成的,具有很好的移植性。要实现 C/OS-II向 S12 的移植,主要是做两方面的工作,一是重新定义内核的大小和功能;二是为内核编写与硬件相关的代码。C/OS-II 的文件结构如图 2 所示。http:/图 2 C/OS-II 的文件结构可以看到,C/OS-II 与 CPU 类型无关的 C 代码文件包括很多文

7、件,它们是 C/OS-II的内核和很多功能函数,其中 OS_CORE.C、OS_TIME.C 和 OS_TASK.C 这三个文件是一定要用的,其他几个文件用于任务间通信,应用程序中可能只用到其中的几个,不用的可以不包含进去,以避免编译时生成没有代码。这部分代码与 CPU 类型无关,在移植时,这些文件一个也不要动。与 CPU 类型有关的代码文件主要有:OS_CFG.H 、OS_CPU.H 、OS_CPU_A.ASM 和OS_CPUC.C。OS_CFG.H 是配置文件,需要根据应用配置,主要作用是确定用户应用程序使用 C/OS-II 提供的哪些系统功能函数,这个文件移植时要修改。OS_CPU.H

8、文件定义用于特定 CPU 的数据类型、定义相关的宏。OS_CPU_A.ASM 是用汇编语言写的硬件有关的代码,OS_CPUC.C 文件是用 C 语言写的与硬件有关的代码。如果移植使用的 C 交叉编译工具在 C 代码中可以插入汇编语句,那么在移植中,可以将 OS_CPU_A.ASM 合到 S_CPUC.C 文件中。3.1 重新定义内核的大小和功能公共头文件 INCLUDES.H,这个文件会被所有的 C 源程序引用。在本例中此文件的代码如下。#include #include #include #include #include http:/#include #include 前四个头文件是 C

9、函数库、预定义的类型等,和移植没有关系,是否一定要加取决于所用的编译器。后三个头文件必须被引用,用户可以添加自己的头文件,但一定要放在最后面。需要根据应用修改的文件是 OS_CFG.H,这个文件用于配置内核的属性。用于设置与微控制器 CPU 核心相关的属性,包括各种数据类型对应的存储长度等等。OS_CPU.H 包括了用#define 语句定义的、与处理器相关的常数、宏及类型等。因为不同的处理器有不同的字长,所以 C/OS-II 的移植包括的一系列数据类型定义,以确保其可移植性。C/OS-II 代码不使用语言中的 short,int ,及 long 等数据类型,因为它们是与编译器相关的,是不可移

10、植的。采用定义的整形数据结构等既是可移植的,又很直观。typedef unsigned char BOOLEAN; /* 布尔变量*/typedef unsigned char INT8U; /* 无符号 8 位整型变量*/typedef signed char INT8S; /* 有符号 8 位整型变量 */typedef unsigned int INT16U; /* 无符号 16 位整型变量*/typedef signed int INT16S; /* 有符号 16 位整型变量*/用户还必须将任务堆栈的数据类型告诉给 C/OS-II。S12CPU 的是堆栈是 16 位的,所以定义 OS_

11、STK 为 INT16U。所有的任务堆栈都必须用 OS_STK 来声明数据类型。#define OS_STK INT16U /* 堆栈是 16 位宽度*/对于不同的处理器而言,数据入堆栈时堆栈指针的增长方向也是不一样的,MC9S12DG128 单片机的堆栈指针是由高地址向低地址增长的,所以,要预先设定堆栈的增长方向:#define OS_STK_GROWTH 1 /*堆栈指针由高地址向低地址增长*/C/OS-II 需要先禁止中断再访问代码的临界段,并且在访问完毕后重新允许中断。这就使得 C/OS-II 能够保护临界段代码免受多任务或中断服务例程的破坏。禁止和允许中断的宏是 OS_ENTER_C

12、RITICAL()和 OS_EXIT_CRITICAL(),定义这两个宏的有三种方法,移植时采用的是方法 1,进入临界代码前关中断,脱离临界代码后开中断2。方法 1 在 OS_CPU.H 中是这样定义的:http:/#if OS_CRITICAL_METHOD = 1 /方法一#define OS_ENTER_CRITICAL( ) asm SEI#defien OS_EXIT_CRITICAL () asm CLI#endif3.2 编写与硬件相关的代码接下来需要编写与硬件相关的代码。这部分代码可以用 C 语言,也可以用汇编语言。移植中与硬件相关的文件中最主要的是 OS_CPU_C.C 和汇

13、编文件 OS_CPU_A.ASM。由于移植使用的是 Metrowerks 公司提供的 CodeWarrior CW12 V4.6 版本的 C 交叉编译工具,而 CW12 V4.6 允许在 C 代码中插入汇编语句,所以可以把 OS_CPU_A.ASM 这个文件合并到 OS_CPU_C.C 文件中去。以下是具体的移植过程。3.2.1 中断服务子程序 OSTickISR()中断服务子程序所使用的中断可以用实时时钟产生,也可以用单片机片内的定时器模块来产生。本次移植采用的是用模数计数器产生精确时钟节拍中断,用 S12 的模数计数器可以实现任意时间的精确中断,这里的中断为每秒 30 次。时钟节拍中断发生

14、时,CPU12 会自动 CPU 把 CPU 寄存器推入堆栈,然后是清中断标志。但是页面寄存器 PPAGE 并没有被推入堆栈,如果 CPU12 的寻址范围超过了 64KB,则要把 PPAGE 也推入堆栈,本文中没有用到 PPAGE 寄存器。时钟节拍中断服务子程序可能激活一个优先级高于当前被中断任务的优先级的任务。时钟节拍中断服务子程序要连续调用:OSIntEnter()、OSTimerTick()和 OSIntExit()这三个函数。OSIntEnter()通知 C/OS-II 进入中断服务子程序了。OSTimerTick()给要求延迟若干时钟节拍的任务延迟计数器减 1,减 1 后为 0 则该任

15、务进入就绪态。OSIntExit()函数告诉 C/OS-II 时钟节拍中断服务子程序结束了,如果这时有更高优先级的任务进入了就绪态,OSIntExit() 就会调用中断级的任务切换函数 OSIntCtxSw()做任务切换,以便让更高的优先级的任务运行。以下是函数代码:void OSTickISR(void)/*根据需要决定是否保存 PPAGE 寄存器,此处没有保存*/OSIntEnter();MCFLG_MCZF=1; /清除模计数器中断标志位OSTimeTick();http:/OSIntExit(); /退出中断并进行任务切换3.2.2 任务堆栈初始化函数 OSTaskStkInit()这

16、个 C 语言写的函数是与 CPU 硬件相关的。这个函数初始化任务的堆栈,由建立任务的函数OSTaskCreate()或扩展的建立任务函数 OSTaskCreatExit()调用。建立任务的函数带有 4 个形式参数,扩展的建立任务的函数有 8 个参数。其中 pdata 用于向任务传递参数。利用了这个参数将页面寄存器 PPAGE 参数传给建立的任务。在改写该函数的时候一定要深刻了解 S12CPU 在中断发生时各个 CPU 寄存器的入栈的顺序,否则,C/OS-II 是运行不起来的。中断发生时 S12CPU 各个寄存器入栈的顺序如图 3 所示。由于该函数是被建立任务的函数所调用的,所以各个 CPU 寄

17、存器的初始值并不重要。但要 CCR 寄存器的内容需要注意:如果选择任务启动后允许中断发生,则所有的任务运行期间中断都允许;同样,如果选择任务启动后禁止中断,则所有的任务都禁止中断发生,而不能有所选择。本文选择在任务启动时开启中断。以下是函数代码:void *OSTaskStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U opt)INT16U *stk;pt = opt; / opt未使用,此处可防止编译器的警告stk = (INT16U *)ptos; /载入堆栈指针*-stk = (INT16U)(pdata);

18、/放置向函数传递的参数 pdata*-stk = (INT16U)(task); /函数返回地址 PC*-stk = (INT16U)(0x1122); /寄存器 Y*-stk = (INT16U)(0x3344); /寄存器 X(INT8U *)stk)-; / 寄存器 A 仅需要 1 个字节*(INT8U *)stk = (INT8U)(0x55); /寄存器 A(INT8U *)stk)-; / 寄存器 B 仅需要 1 个字节*(INT8U *)stk = (INT8U)(0x66); /寄存器 B(INT8U *)stk)-; / 寄存器 CCR 仅需要 1 个字节*(INT8U *)

19、stk = (INT8U)(0x00); /寄存器 CCR,开中断http:/return (void *)stk);3.2.3 让优先级最高的就绪态任务开始运行 OSStartHightRdy()OSStartHighRdy()是在多任务启动时被 OSStart()调用的,C/OS-II 做完所有的初始化工作之后,OSStart()就启动运行多任务,而 OSStart()调用 OSStartHighRdy()函数运行多个就绪任务中优先级最高的任务。注意,堆栈指针总是储存在任务控制块的开头。图 3 中断发生时 S12CPU 寄存器入栈的顺序OSStartHighRdy()将 CPU 的堆栈指针

20、 SP 的值,改成优先级最高的就绪态任务的堆栈指针的值,然后将该任务的状态字由非运行态“FALSE”,改为运行态“TRUE”,然后执行中断返回指令 RTI 以开始运行这个任务。以下是详细代码:void OSStartHighRdy(void)OSTaskSwHook(); /调用钩子函数asmldx OSTCBCur / 加载 OSTCBCur 的地址到 xlds 0,x /把 OSTCBStrPtr 载入堆栈指针 spldaa OSRunninghttp:/inca / SRunning = TRUEstaa OSRunningrti3.2.4 任务级任务切换函数 OSCtxSw()和中断级

21、任务切换函数 OSIntCtxSw()任务级的切换是通过执行软中断指令来实现的。OSCtxSw()实际上就是软中断服务子程序,软中断服务子程序的向量地址指向 OSCtxSw()。如果当前任务调用 C/OS-II提供的功能函数,并使更高优先级任务进入了就绪状态,则 C/OS-II 就会借助上面提到的向量地址找到 OSCtxSw()。在系统服务调用的最后,C/OS-II 会调用任务调度函数 OSSched(),并由此推断出当前任务不再是需要运行的最重要的任务。OSIntCtxSw()函数中的绝大多数代码同 OS_TASK_SW()函数是一样的。而中断退出函数则是通过函数OSIntCtxSw()来从

22、 ISR 中执行切换功能,区别只是因为 ISR 已经保存了 CPU 的寄存器,而不再需要在OSIntCtxSw()函数中保存 CPU 的寄存器。以下只给出任务级任务切换函数 OSCtxSw()的代码:void OSCtxSw(void)asmldx OSTCBCur / 加载当前任务的堆栈指针sts 0,x / 保存到当前任务的 TCB 中OSTaskSwHook(); /调用钩子函数STCBCur = OSTCBHighRdy; / 改变任务的 OSTCBCur 和 OSPrioCurSPrioCur = OSPrioHighRdy;asmldx OSTCBCur / 得到新任务的堆栈指针l

23、ds 0,x / 加载新任务的堆栈指针到 sprtihttp:/4 移植代码的测试为了验证移植结果是否正确,对移植后 C/OS-II 代码进行了测试,这是移植中很重要的一个环节。首先对内核自身的运行情况进行了测试,待内核自身的运行正常工作后,又创建三个任务:任务 1 通过PORTA 口点亮 LED 灯,该任务每秒运行一次;任务 2 和任务 3 都通过串输出字符串,这两个任务都是每2 秒运行一次,并通过信号量来实现互斥,以使得每个任务每次运行时均可完成所有字符的输出。实验测试证明在 C/OS-II管理与调度下,使得这三个任务都能正确、可靠地相继运行。5 小结通过 C/OS-II在 MC9S12D

24、G128 上的移植,加深了对 C/OS-II内核工作原理和任务调度实现方法的理解,掌握了 C/OS-II移植的一般方法,测试结果表明移植代码可以稳定可靠的运行,实现了多任务的管理和调度。C/OS-II 实时操作系统的引入,不但可以提高系统的实时性、可靠性和稳定性,还提高了应用软件的可移植性,降低了开发人员的工作量。成都嵌入式培训哪里好?选择达内嵌入式培训开启企业定制就业直通车,达内科技满足你高薪就业梦想!找 成都 IT 培训 100%推荐就业的软件测试培训机构,请咨询达内在成都嵌入式培训的老师!达内培训费用?达内好不好?达内怎么样?达内就业?这些问题都可以在达内的网站上找到答案。在达内科技学习可以申请先就业后付款的方式让刚毕业大学生免除在达内培训费用上的担忧。100%推荐就业更是解决学员培训后的就业问题!达内咨询官网:

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

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报