uC/OS-II在ARM系统上的移植与实现

发布者:大泉人家最新更新时间:2006-09-14 来源: 电子设计应用关键字:堆栈  函数  移植  寄存 手机看文章 扫描二维码
随时随地手机看文章

0  引言
  在开发嵌入式系统时,一般选择基于ARM 和uC/ OS - II 的嵌入式开发平台,因为ARM 微处理器具有处理速度快、超低功耗、价格低廉、应用前景广泛等优点[1 ] . 将uC/ OS - II 移植到ARM 系统之后,可以充分结合两者的优势. 如果一个程序在一个环境里能工作,我们经常希望能将它移植到另一个编译系统、处理器或者操作系统上,这就是移植技术.移植技术可以使一种特定的技术在更加广泛的范围使用,使软件使用更加灵活,不局限于某一条件.uC/OS - II 是由Jean J . Labrosse 先生编写的完整的可移植、固化、裁剪的占先式实时多任务内核.uC/ OS - II 的源代码完全开放,这是其他商业实时内核无法比拟的[2 ] . 它是针对嵌入式应用设计的,在设计之初就充分考虑了可移植性,它的大部分源代码都是用高可移植性的ANSIC 编写的[3 ] . uC/ OS - II可以移植到从8 位到64 位的不同类型、不同规模的嵌入式系统,并能在大部分的8 位、16 位、32 位、甚至64 位的微处理器和DSP 上运行. 由于uC/ OS - II是一个实时操作系统,所以如果将它嵌入到ARM处理器上,就能够进一步简化ARM系统的开发.

图1  uC/ OS - II 文件体系结构

1  uC/ OS - II 的移植
  uC/OS - II 的文件系统结构包括核心代码部分、设置代码部分、与处理器相关的移植代码部分[4 ] . 结构如图1 所示.其中最上边的软件应用层是uC/ OS - II 上的代码. 核心代码部分包括7 个源代码文件和1 个头文件. 功能分别是内核管理、事件管理、消息队列管理、存储管理、消息管理、信号量处理、任务调度和定时管理. 设置代码部分包括2 个头文件,用来配置事件控制块的数目以及是否包含消息管理相关代码. 而与处理器相关的移植代码部分则是进行移植过程中需要更改的部分,包括1 个头文件OS CPU. H ,1 个汇编文件OS CPU A. S 和1 个C 代码文件.实际上将uC/ OS - II 移植到ARM 处理器上,需要完成的工作主要是以下三个与体系结构相关的文件:OS CPU. H ,OS CPU. C 以及OS CPU A. S[5 ] .

1. 1  OS CPU. H 的移植
  文件OS CPU. H 中包括了用# define 语句定义的与处理器相关的常数、宏以及类型. 移植时主要修改的内容有:与编译器相关的数据类型的设定;用#define 语句定义2 个宏开关中断;根据堆栈的方向定义OS STK GROWTH等.

  在将uC/ OS - II 移植到ARM 处理器上时,首先进行基本配置和数据类型定义. 重新定义数据类型是为了增加代码的可移植性,因为不同的编译器所提供的同一数据类型的数据长度并不相同,例如int型,在有的编译器中是16 位,而在另外一些编译器中则是32 位. 所以,为了便于移植,需要重新定义数据类型,如INT32U 代表无符号32 位整型. typedefunsigned int INT8U ,就是定义一个8 位的无符号整型数据类型. 其次就是对ARM 处理器相关宏进行定义,如ARM处理器中的退出临界区和进入临界区的宏定义,退出临界区宏定义[5 ] : # define OS EXITCRITICAL () ARMDisable Int ( ) / / 关中断,进入临界区宏定义# define OS ENTER CRITICAL ( ) AR2MEnableInt () / / 开中断. 最后就是堆栈增长方向的设定. 当进行函数调用时,入口参数和返回地址一般都会保存在当前任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会决定堆栈的增长方向[6 ] ,定义为# define OS STK GROWTH 1.


图2  堆栈增长方向
1. 2  OS CPU. C 的移植
  OS CPU. C 的移植包括任务堆栈初始化和相应函数的实现. 在这里,共有6 个函数:OSTaskStkInit( ) , OSSTaskCreateHook ( ) , OSTaskDelHook ( ) , OS2TaskSwHook( ) ,OSTaskStatHook ( ) , OSTimeTickHook () . 其中后面的5 个HOOK函数又称为钩子函数,主要是用来对uC/ OS - II 进行功能扩展. 这些函数为用户定义函数,由操作系统调用相应的HOOK函数去执行,在一般情况下,他们都没有代码,所以实现为空函数即可. 而函数OSTaskStkInit ( ) 对堆栈进行初始化,在ARM 系统中,任务堆栈空间由高到低依次为PC ,LR ,R12 ,R11 , ,R1 ,R0 ,CPSR ,SPSR. 在进行堆栈初始化以后,OSTaskStkInit ( ) 返回新的堆栈栈顶指针.

1. 3  OS CPU A. S 的移植
  OS CPU A. S 文件的移植需要对处理器的寄存器进行操作,所以必须用汇编语言来编写. 这个文件的实现集中体现了所要移植到处理器的体系结构和uC/ OS - II 的移植原理[6 ] . 它包括4 个子函数:OSStartHighRdy() , OSCtxSw() , OSIntCtxSw() ,OSTick2ISR() . 其中难点在于OSIntCtxSw() 和OSTickISR() 函数的实现,因为这两个函数的实现与移植者的移植思路以及相关硬件定时器、中断寄存器的设置有关.在实际的移植工作中,这两处也是比较容易出错的地方.

  OSIntCtxSw( ) 函数由OSIntExit ( ) 函数调用,而OSIntExit () 函数又由OSTickISR() 调用. OSIntCtxSw()函数最重要的作用就是它完成在中断ISR 中直接进行任务切换,从而提高了实时响应的速度. 它发生的时机是在ISR 执行到OSIntExit ( ) 时,如果发现有高优先级的任务因为等待time tick 的到来获得了执行? 7 2 ? 第4 期李学桥等:uC/ OS - II 在ARM系统上的移植与实现的条件,就可以马上被调度执行,而不用返回被中断的那个任务之后再进行任务切换. 实现OSIntCtxSw() 的方法大致也有两种情况[7 ] :一是通过调整SP 堆栈指针的方法,根据所用的编译器对于函数嵌套的处理,通过精确计算出所需要调整的SP 位置来使得进入中断时所作的保护现场的工作可以被重用. 二是设置需要切换标志位的方法,在OSIntCtxSw( ) 里面不发生切换,而是设置一个需要切换的标志,等函数嵌套从进入OSIntExit ( ) = > OS ENTER CRITI2CAL() = > OSIntCtxSw( ) = > OS EXIT CRITICAL() = > OSIntExit ( ) 退出后,再根据标志位来判断是否需要进行中断级的任务切换.

  其次是对OSTickISR() 修改.OSTickISR() 首先在被中断任务堆栈中保存CPU 寄存器的值,然后调用OSIntEnter () . 随后调用OSTimeTick() ,检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务. 最后调用OSIntExit ( ) . 如果在中断中(或其他嵌套的中断) 有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,OSIntExit ( ) 将进行任务调度. 如果进行了任务调度,OSIntExit () 将不再返回调用者,而是用新任务的堆栈中的寄存器数值恢复CPU 现场,然后实现任务切换. 如果当前中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态, OSIntExit ( ) 将返回调用者OSTickISR ( ) ,OSTickISR() 返回被中断的任务. 最后就是退出临界区和进入临界区函数. 进入临界区时,必须关闭中断,用ARMDisableInt () 函数实现. 在退出临界区的时候恢复原来的中断状态,通过ARMEnableInt ( ) 函数来实现[7 ] . 至于进行任务级上下文切换,则是由汇编子程序OSCtxSw 实现.

2  在ARM系统上的实现
  以跑马灯和数码管为例,说明uC/ OS - II 的移植过程:跑马灯是4 个小灯轮流变明变暗,很方便看出效果. 跑马灯在日常中使用很多,比如状态栏跑马灯、文字跑马灯、图片跑马灯、单片机跑马灯等[8 ] . 本文采用的是单片机跑马灯. 实现单片机跑马灯的程序中,只有地址口为低电平(接地) 时,发光管才会亮. 所以只要循环控制地址口的各个引脚的电平高低变化就可使LED 循环点亮:首先是全不亮,接着第1 个灯亮,第2 个灯亮,第3 个灯亮,第4 个灯亮,第5 个灯亮,最后所有的灯一起亮.

  笔者使用6 个共阳极LED 数码管来实现在7 段数码管上循环显示0~9 ,A~F 字符. 每个显示位的段选线与一个8 位并行口线对应相连,只要在显示位上的段选线上保持段码电平不变,则该位就能保持相应的显示字符. 这里的8 位并行口可以直接采用并行I/ O 口,也可以采用串入/ 并出的移位寄存器或是其他具有三态功能的锁存器等. 当采用动态显示接口时,在多位LED 显示时,为了简化电路,降低成本,将所有位的段选线并联在一起,由一个8 位I/ O口控制. 而共阴(或共阳) 极公共端分别由相应的I/ O 线控制,实现各位的分时选通. 由于各个数码管是共用同一个段码输出口分时轮流通电的,从而大大简化了硬件线路,降低了成本.

  对于数码管的实现分为3 个步骤:
1) 制作LED 字符与码段对应表
2) 扫描控制3 ( (U8 3 ) 0x02000006) = 0x3E; / 3 使能第一个数码管3 /
3) 段码输出( (U8 3 ) 0x02000004) = seg7table[0 ] ;

  根据上面的LED 字符与码段对应表,控制相应的数字进行输出. 数码管扫描控制地址为0x02000006 ,8 位访问,比如Bit0 控制数码管0 ,并且低电平有效,Bit5 控制数码管5 ,低电平有效,数码管显示试验系统中采用的是动态显示接口,其中数码管扫描控制地址为0x02000006 ,位0 —5 分别对应一个数码管,将其中每位清0 来选择相应的数码管;地址0x02000004 为数码管的数据寄存器,控制数码管的段码输出.

3  多任务应用程序
  uC/OS - II 的移植及跑马灯和数码管的实现如下[9 ] :首先是C 语言入口函数Main (所有C 程序的入口) . 它里面包括调用函数ARMTargetInit () 初始化ARM处理器,调用OSInit ( ) 进行uC/ OS - II 操作系统初始化,然后调用OSTaskCreate ( ) 函数创建任务TaskLED 和TaskSEG,最后调用ARMTargetStart () 函数启动时钟节拍中断,并且调用OSStart ( ) 启动系统任务调度,由于在程序当中使用for ( ; ;) ,这是一个永无止境的回路,所以装置可以一直进行下去,直到关闭装置.
  void Main(void)
  {ARMTargetInit () ;
  uHALr printf (″uC/ OS - II # n″) ;
  OSInit () ;
  Sem1 = OSSemCreate(0) ;
  Sem2 = OSSemCreate(1) ;
  OSTaskCreate(TaskLED , (void 3 ) &IdLED , (OS STK 3 )
&StackLED[ STACKSIZE - 1 ] , 5) ;
  OSTaskCreate(TaskSEG, (void 3 ) &IdSEG, (OS STK 3 )
&StackSEG[ STACKSIZE - 1 ] , 6) ;
  ARMTargetStart () ;OSStart () ;
  return ;}

4  结语
  使用创建好的模板Temp 新建一个工程Temp ,并将模板中的Core 和Assemble 文件夹中的文件加入到工程Temp 中. 1) 新建一个文件Temp. c ,并将其添加到Temp 工程的App 文件夹中. 2) 打开Temp. c文件,添加两个任务,它们的任务处理函数分别为TaskLED() 和TaskSEG() . 3) 在TaskLED( ) 函数中每隔50 个时钟节拍使所有跑马灯闪烁一次(即按顺序亮,然后全亮,最后全灭,顺序循环) . 4) 在TaskSEG() 函数中每隔50 个时钟节拍切换一次数码管显示(循环从0~F 显示) . 5) 编译工程Temp ,如果出错,则进行修改后再编译. 6) 将Temp 下载并运行,看结果. 正确的结果是将每隔1/ 2 s 切换一次数码管显示,每隔1/ 2 s使所有跑马灯闪烁一次. 经持续了2 h试验,没有出现错误,跑马灯和数码管正常运转,结果证明移植成功.

参考文献:
[1 ]  雷必成, 吴高标, 吴永良. 嵌入式实时操作系统uC/ OS
- II 的移植探讨[J ] . 自动化技术与应用,2003 , (5) :1 —3.
[2 ]  邵贝贝. 嵌入式实时操作系统uC/ OS - II[M] . 第2 版.
北京:北京航空航天大学出版社,2003. 2 —30.
[3 ]  叶丰桥,黄海. uC/ OS - II 在51XA 上的移植应用[J ] .
工业控制计算机,2002 , (10) :1 —2.
[4 ]  田泽. 嵌入式开发与应用实验教程[M] . 北京: 北京航
空航天大学出版社,2004. 264 —270.
[5 ]  陈赜. ARM嵌入式技术实践教程[M] . 北京:北京航空
航天大学出版社,2005. 189 —203.
[6 ]  王田苗. 嵌入式系统设计与实例开发[M] . 北京: 清华
大学出版社,2003. 62 —89.
[7 ]  朱华军. uC/ OS - II 操作系统在ARM处理器上的技巧
[J ] . 计算机工程,2004 , (S1) :2 —3.
[8 ]  苏中义,杨宇. 嵌入式系统[J ] . 嵌入系统,2004 , (3) :11
[9 ]  曾鸣. uC/ OS - II 实时操作系统在嵌入式平台上进行
移植的一般方法和技巧[ J ] . 今日电子, 2004 , (11) :2 —3.

关键字:堆栈  函数  移植  寄存 引用地址:uC/OS-II在ARM系统上的移植与实现

上一篇:PPCBoot在MPC8250上的移植方法
下一篇:双内核嵌入式处理器BCM1250及其应用

推荐阅读最新更新时间:2024-05-13 18:14

IAR调试STM8S遇到函数返回值错误的问题
出现问题是在stm8s003上调试EEPROM操作的时候,从逻辑分析仪抓取IIC通讯数据,看到读取和写入都正常,正常情况下操作成功会直接返回0x00;但是这次总是返回0x37,单步跟踪看到return的的确是0,但是返回值赋给一个变量后就变成0x37,这个驱动以前使用过没有问题,这次不知道怎么抽风了 IIC驱动是在独立C文件中,调用是在另一个文件里面,通过头文件extern声明引用,和以前的程序交叉对比后发现IIC.h里的函数声明被注释掉了,相当于没有声明就直接调用了,最后去掉注释后便恢复正常了
[单片机]
CubeMX 5.5 修改HAL库库函数版本
最初我是按照软件推荐,自动按安装的1.15的。 为了和正点原子的例程统一库函数版本,就下载了1.11。 但是在工程配置界面始终没有办法修改 hal库 版本的选择: 关闭CubeMX,使用记事本打开工程文件: 修改版本号: 重新打开工程,库版本修改成功: 工程生成成功:
[单片机]
CubeMX 5.5 修改HAL库库<font color='red'>函数</font>版本
单片机的存储器 寄存器概述
单片机的存储器有程序存储器ROM与数据存储器RAM两种。 这两种存储器在使用上是严格区分的,不得混用。 程序存储器存放程序指令,以及常数,表格等;而数据存储器则存放缓冲数据。 MCS-51单片机存储器的结构共有3部分:一是程序存储器 二是内部数据存储器 三是外部数据存储器MCS-51单片机的存储器可分为5类:程序存储器、内部数据存储器、特殊功能寄存器、位地址空间、外部数据存储器 程序存储器 程序是控制计算机动作的一系列命令,单片机只认识由“0”和“1”代码构成的机器指令。如前述用助记符编写的命令MOV A,#20H,换成机器认识的代码74H、20H:(写成二进制就是01110100B和00100000B)。在单片机处理问题之
[单片机]
低容量STM8 Modbus协议移植与裁剪
1.freeModbus开源包的下载 一般STM8用的开发环境是IAR,所以这里我们就讲在IAR下移植FreeModbus, 下载freemodbus-v1.5.0,官方下载地址http://www.freemodbus.org/找到Download 点击freemodbus-v1.5.zip即可下载。 2.freeModbus开源包的简介 打开文件夹的目录如下 然后我们打开主要的文件夹modbus 我们可以看到有ascii、functions、include、rtu、tcp以及mb.c源文件 Ascii Modbus ascii通信方式相关文件夹, Rtu Modbus Rtu 通信方式和CRC校验
[单片机]
低容量STM8 Modbus协议<font color='red'>移植</font>与裁剪
移植Linux-3.4.2到TQ2440上
开发环境 主机开发环境:ubuntu12.04 BootLoader:u-boot-2012.04.01 kernel:linux-3.4.2 CPU:s3c2440 开发板:TQ2440 步骤 之前已经移植过linux-2.6.30.4内核,这次尝试移植更高版本的内核Linux-3.4.2 1、内核源码下载 下载地址:内核下载地址 拷贝到虚拟机里,解压内核 tar -jxvf linux-3.4.2.tar.bz2 2、在系统中添加对ARM的支持 3、修改平台输入时钟 不修改的话会出现启动内核会出现乱码 在内核源码中找到对应的单板文件为archarmmach-s3c24xxmach-smdk2440.c文件,
[单片机]
<font color='red'>移植</font>Linux-3.4.2到TQ2440上
移植无人驾驶技术方案开发的扫地机器人
移植无人驾驶的一些技术方案来开发扫地机器人,这些年逐渐成为一个看起来比较新鲜的现象。 其实这两者本身就是相通的——毕竟“无人驾驶”汽车同样可以被看作“轮式移动机器人”,通过车载传感器建立高清地图,并自动规划行车路线,从而达到“无人驾驶”的目的。 而且“无人驾驶”还是一个比较宽泛的定义,按照国际自动机械工程师学会(SAE)的标准,目前有L0-L5共六个级别: L1代表辅助驾驶,预警类ADAS功能,比如偏离车道预警;L2代表部分自动驾驶,辅助干预ADAS功能,比如ACC自适应巡航、紧急自动刹车、车道保持辅助;L3代表有条件自动驾驶,在辅助干预的基础上增加了自动加速、自动刹车以及自动转向等; L4代表高度自动驾驶,这个级别能实现完全没有
[机器人]
STM32入门系列-使用库函数点亮LED,LED初始化函数
要点亮LED,需要完成LED的驱动, 在工程模板上新建一个led.c和led.h文件,将其存放在led文件夹内。这两个文件需要我们自己编写。 通常xxx.c文件用于存放编写的驱动程序,xxx.h文件用于存放xxx.c内的stm32头文件、管脚定义、全局变量声明、函数声明等内容。 因此在led.c文件内编写如下代码: #include led.h /******************************************************************************* * 函 数 名 : LED_Init * 函数功能 : LED 初始化函数 * 输 入 : 无 * 输 出 : 无
[单片机]
uC/OS-II实时操作系统移植的一般方法和技巧
引言 实时操作系统的使用,能够简化嵌入式系统的应用开发,有效地确保稳定性和可靠性,便于维护和二次开发。 μC/OS-II是一个基于抢占式的实时多任务内核,可固化、可剪裁、具有高稳定性和可靠性,除此以外,μC/OS-II的鲜明特点就是源码公开,便于移植和维护。 在μC/OS-II官方的主页上可以查找到一个比较全面的移植范例列表。但是,在实际的开发项目中,仍然没有针对项目所采用芯片或开发工具的合适版本。那么,不妨自己根据需要进行移植。 本文则以在TMS320C6711 DSP上的移植过程为例,分析了μC/OS-II在嵌入式开发平台上进行移植的一般方法和技巧。μC/OS-II移植的基本步骤 在选
[嵌入式]
小广播
最新应用文章
换一换 更多 相关热搜器件

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 安防电子 医疗电子 工业控制

词云: 1 2 3 4 5 6 7 8 9 10

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved