• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

实时操作系统μC/OS-II在MCF5272上的移植

作为一个实时内核,从1992年开始为人们熟悉,到现在已经发展为.最多支持56个任务,其内核为占先式,总是执行就绪态的优先级最高的任务,并支持Semaphore(信号量)、Mailbox(邮箱)、MessageQueue(消息队列)等多种常用的进程间通信机制.与大多商用RTOS不同的是,公开所有的源代码,并可以免费获得,对商业应用收取少量License费用.一般商用操作系统如VxWorks、pSOS、WinCE,购买费用动辄数万美元,而且每件产品都需要交纳运行费,开发、使用成本高昂. 目前MCF5272是Motorola公司一款集成度最高的ColdFire处理器,采用ColdFireV2可变长RISC处理器核心和DigitalDNA技术,在66MHz时钟下能够达到63Dhrystone2.1MIPS.其内部SIM(SystemIntegratedModule)单元集成了丰富的通用模块,如10/100MHz快速以太网控制器,USB1.1接口等,并且能够与常用的外围设备(如SDRAM、ISDN收发器)实现无缝连接,从而简化了外围电路设计,降低了产品成本、体积和功耗. 使用GNU工具链(包括交叉编译器GCC、汇编器AS等)进行内核的编译,Host(宿主机)环境为16MBSDRAM.在宿主机上编译出MCF5272处理器的可执行代码,通过MCF5272的BDM调试工具下载到目标板调试运行.应用程序处于整个系统的顶层,每个任务都可以认为自己独占了CPU,因而可以设计成为一个无限循环.处理器无关的代码提供的系统服务,应用程序可以使用这些API函数进行内存管理、任务间通信以及创建、删除任务等. 大部分的代码是使用ANSIC语言书写的,因此的可移植性较好.尽管如此,仍然需要使用C和汇编语言写一些处理器相关的代码.的移植需要满足以下要求: (1)处理器的C编译器可以产生可重入代码; (2)可以使用C调用进入和退出CriticalCode(临界区代码); (3)处理器必须支持硬件中断,并且需要一个定时中断源; (4)处理器需要能够容纳一定数据的硬件堆栈; (5)处理器需要有能够在CPU寄存器与内存和堆栈交换数据的指令. 移值的主要工作就是处理器和编译器相关代码以及BSP的编写. 2编写 BSP(板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作. 为编写一个简单的BSP.它首先设置CPU内部寄存器和系统堆栈,并初始化堆栈指针,建立程序的运行和调用环境;然后可以方便地使用C语言设置MCF5272片选地址(CS0~CS7)、GPIO以及SDRAM控制器,初始化串口(UART0)作为默认打印口,并向操作系统提供一些硬件相关例程和函数如dprintf(),以方便调试;在CPU、板级和程序自身初始化完成后,就可以把CPU的控制权交给操作系统了. MCF5272处理器将系统上电作为2号异常,因此需要在异常矢量表中相应位置填写第一条命令的物理地址,这可以在编译时自动完成.该矢量表必须存放在CS0对应的FLASH中供CPU上电时自动读取.如: _vectors://矢量表起始地址 .long0x0,_start,_fault,_fault,…//初始化1K字节矢量表 …… _start:nop//第一条指令 move.w#0x2700,%sr//屏蔽所有中断 move.1#_vectors,?move.c?%VBR//#vectors->VBR move.1#0x10000001,?move.c?%MBAR//SIM单元基地址0x10000000 move.1#0x20000001,?/SRAM起始地址0x20000000 move.c?%RAMBAR0//初始化内部SRAM move.1#0x20001001,?/设置堆栈指针 …… jsrcpu_init//调用cpu_init初始化SIM单元 jsrucos_start//启动 …… 其中,cpu_init函数用于初始化CPU内部SIM单元、SDRAM控制器、UART串口.值得注意的是SDRAM初始化,不同生产商的SDRAM的初始化时序有一定差异. BSP在完成片级和板级初始化后,还负责初始化程序自身,如将.data段的内容从只读的ROM复制到SDRAM中,建立运行时环境.以下是建立程序数据段的代码: memcpy(&_sdata,&_etext,(&_edata-&_sdata));//拷贝.data段 memset(&_sbss,0,(&_ebss-&_sbss));//将.bss段清零 还需要为编写4个简单的汇编函数.在每个硬件时钟到来后,会在中断服务例程中调用OSIntCtxSw()进行任务调度;另外,当某个任务因等待资源而被挂起时,没有必要等到自己的时间片全都用完,可以自己主动放弃CPU,这可以通过调用一个任务级的任务调度函数OSCtxSw()来实现.其中相对复杂的是OSIntCtxSw().由于OSTickISR()调用了OSIntExit(),OSIntExit()又再次调用了OSIntCtxSw(),如果进行任务切换,那么两次调用都不会返回,而不同的C编译器、不同的编译选项处理C调用时对堆栈的使用也不尽相同.因此OSIntCtxSw()是编译器相关的.GCC在使用2~4级优化时,在主调函数中会是一个jsr跳转指令,而被调函数以linkw%fp,#开始.这两条指令都会影响堆栈指针.为了实现任务切换,必须重新调整堆栈指针以补偿调用的影响.一个完整过程如下: OSIntCtxSw: adda.1#16,?/栈补偿,GCC-O2->-04优化 move.1(OSTCBCur),?move.1?(?//OSTCBCur->OSTCBStkPtr=SP jsrOSTaskSwHook//调和Hook钩子函数 /*OSTCBCur->OSTCBStkPtr=OSTCBHighRdy->OSTCBStkPtr*/ move.1(OSTCBHighRdy),?move.1?(OSTCBCur) move.b(OSPrioHighRdy),?move.b?(OSPrioCur)//OSPrioCur=OSPrioHighRdy move.1(?,?/SP=OSTCBCur->OSTCBStkPtr movem.1(?,????/恢复CPU寄存器,切换到新任务 lea60(?,?rte 篇幅所限,其它三个函数就不述了. 3任务堆栈初始化 中每个任务都有自己的任务堆栈,在任务创建初期由OSTaskStkInit()初始化.初始化堆栈的目的就是模拟一次中断.任务堆栈中保存了任务代码的起始地址和一些CPU寄存器(初值是无关紧要的),这样一旦条件满足,就可以执行该任务了.MCF5272在中断发生时,会自动保存程序指针PC、状态寄存器SR以及其它一些信息,为四字帧结构.除此以外,STaskStkInit()在完成堆栈初始化后,还要返回栈顶指针以用于该任务控制块TCB结构的初始化.该程序使用C语言编写. 4系统时钟 MCF5272处理器内置了4个定时器,使用TIMER0产生周期10ms的定时中断作为系统时钟.当PIVR寄存器设置为0x40时,TIMER0为69号中断,在矢量表的相应位置需填入时钟服务程序OSTickISR()的入口地址,并初始化时钟: volatileunsignedshort*pTimer; pTimer=(unsignedshort*)(0x100000000x200);//指向TIMER0 /*复位时钟*/ *pTimer&=0xFFF9;//定时器处于STOP状态 *pTimer=(*pTimer&0x00FF)|0xFA00;//预分频=250 *pTimer|=0x0018;//计数满自动清零,中断方式 pTimer[2]=165;//SetTRR=165 *pTimer=(*pTimer&0xFFF9)|0x0004;//CLK=Master/16,启动 上述程序段时钟节拍的周期为:(1/66MHz)×250×164×16=0.01秒.实时性要求高的场合可以使用更为精细的时钟.TIMER0一旦完成初始化,就开始工作,但是要让中断发生,还必须设置ICR寄存器相应字段给该中断分配IPL(InterruptPriorityLevel,中断优先级),并保证该中断没有初状态寄存器SR屏蔽. 该时钟初始化代码可以放在第一个任务中,在OSStart()后执行.一旦内核可以进行正常的任务切换,移植工作也就基本完成了. 5内核编译与下载 所有的C和汇编源文件经过编译、链接,最终形成一个二进制映像文件.由于使用了自定义的数据类型,因此必须将其转变成为GCC(GNUCCompiler)能识别的类型,如INT8U可以定义为unsignedchar.另外,还必须编写一个LD(链接脚本)文件控制编译,将程序定位到实际的ROM和RAM资源中.为了调试方便,通常是通过BDM工具将内核下载到目标板SDRAM中运行,调试通过后再固化到FLASH中. RTOS是当前嵌入式应用的特点.应用RTOS,可以使产品更可靠、功能更强大而开发周期更短.有着良好的实时性和很小的代码量,并被广泛移植到x86、68K、ColdFire、MPC8xx、ARM、MIPS、C5409等许多处理器上.
全部回复(14)
正序查看
倒序查看
hao_zi
LV.4
2
2007-12-31 02:01
上面是有关μC/OS-II的一点介绍,近段时间本人针对"luyu"工程师提出的纯软件化控制思想,正在尝试用μC/OS-II控制感应加热过程,实验的结果才是最好的解释,等待结果中.......
0
回复
luyuc
LV.7
3
2007-12-31 13:18
@hao_zi
上面是有关μC/OS-II的一点介绍,近段时间本人针对"luyu"工程师提出的纯软件化控制思想,正在尝试用μC/OS-II控制感应加热过程,实验的结果才是最好的解释,等待结果中.......
.  我用汇编语言编写几十句,都要好几个月来反复修改,平均一天写一句都不到;要是用os平台太复杂了,无论如何都无法做完软件内的 debug ,遗留的错误也许不是致命的,但是将导致意外发生;如果遗留致命的软件错误,将导致驱动变压器饱和、容性硬开通、严重的峰值闸断反复发生、可能炸管或存在炸管的风险.
0
回复
luyuc
LV.7
4
2007-12-31 13:46
@luyuc
.  我用汇编语言编写几十句,都要好几个月来反复修改,平均一天写一句都不到;要是用os平台太复杂了,无论如何都无法做完软件内的debug,遗留的错误也许不是致命的,但是将导致意外发生;如果遗留致命的软件错误,将导致驱动变压器饱和、容性硬开通、严重的峰值闸断反复发生、可能炸管或存在炸管的风险.
AT91SAM7S32 的汇编正在学习,但是连一个志同道合的朋友都找不到,大家都不赞同完全用汇编语言编写这ARM7,而且也不理解;但是我决心在2-3年内完全熟练ARM7的汇编,把所有外设的控制寄存器、状态寄存器、数据寄存器彻底理解并熟记应用;没有汇编语言就没有对控制彻底 DEBUG 的方法,诊断工作是无法深入的;就象医生要学习生理学、病理学、药理学一样,这汇编语言就是“生理学”,只要有可能弄懂就要去下功夫去做;
0
回复
elegun
LV.1
5
2008-01-04 10:59
@luyuc
AT91SAM7S32的汇编正在学习,但是连一个志同道合的朋友都找不到,大家都不赞同完全用汇编语言编写这ARM7,而且也不理解;但是我决心在2-3年内完全熟练ARM7的汇编,把所有外设的控制寄存器、状态寄存器、数据寄存器彻底理解并熟记应用;没有汇编语言就没有对控制彻底DEBUG的方法,诊断工作是无法深入的;就象医生要学习生理学、病理学、药理学一样,这汇编语言就是“生理学”,只要有可能弄懂就要去下功夫去做;
用C 好.
0
回复
elegun
LV.1
6
2008-01-04 10:59
@luyuc
AT91SAM7S32的汇编正在学习,但是连一个志同道合的朋友都找不到,大家都不赞同完全用汇编语言编写这ARM7,而且也不理解;但是我决心在2-3年内完全熟练ARM7的汇编,把所有外设的控制寄存器、状态寄存器、数据寄存器彻底理解并熟记应用;没有汇编语言就没有对控制彻底DEBUG的方法,诊断工作是无法深入的;就象医生要学习生理学、病理学、药理学一样,这汇编语言就是“生理学”,只要有可能弄懂就要去下功夫去做;
用C 好.
0
回复
2012-01-12 16:02
@luyuc
AT91SAM7S32的汇编正在学习,但是连一个志同道合的朋友都找不到,大家都不赞同完全用汇编语言编写这ARM7,而且也不理解;但是我决心在2-3年内完全熟练ARM7的汇编,把所有外设的控制寄存器、状态寄存器、数据寄存器彻底理解并熟记应用;没有汇编语言就没有对控制彻底DEBUG的方法,诊断工作是无法深入的;就象医生要学习生理学、病理学、药理学一样,这汇编语言就是“生理学”,只要有可能弄懂就要去下功夫去做;
精神可嘉,佩服。
0
回复
贴片机
LV.8
8
2012-01-12 16:20
@luyuc
AT91SAM7S32的汇编正在学习,但是连一个志同道合的朋友都找不到,大家都不赞同完全用汇编语言编写这ARM7,而且也不理解;但是我决心在2-3年内完全熟练ARM7的汇编,把所有外设的控制寄存器、状态寄存器、数据寄存器彻底理解并熟记应用;没有汇编语言就没有对控制彻底DEBUG的方法,诊断工作是无法深入的;就象医生要学习生理学、病理学、药理学一样,这汇编语言就是“生理学”,只要有可能弄懂就要去下功夫去做;

都上操作系统了,只能用C了;用汇编的话,普通8位机,做小程序可以.ARM7你还用纯汇编的话,你就慢慢写吧...

0
回复
贴片机
LV.8
9
2012-01-12 16:24
@贴片机
都上操作系统了,只能用C了;用汇编的话,普通8位机,做小程序可以.ARM7你还用纯汇编的话,你就慢慢写吧...
有时候,做事情不能一味地要求从源头做起.就拿做电源我们不可能电阻电容每个器件都自已做,一个道理.有更加快捷和高效的办法为什么不用呢,况且有些情况下是你想从源头做起都做不了的...
0
回复
stevenpe
LV.4
10
2012-01-13 08:49
@贴片机
有时候,做事情不能一味地要求从源头做起.就拿做电源我们不可能电阻电容每个器件都自已做,一个道理.有更加快捷和高效的办法为什么不用呢,况且有些情况下是你想从源头做起都做不了的...

不太认同贴片机的观点。

C和汇编相比较而言,固然C更高级,更进一步,但具体选择还是要看应用场合和自己的擅长。相对于汇编而言,C语言是更简单,更傻瓜式的语言。有些时候,不是说做事情一味的要从源头做起,只是同样的功能的程序,用汇编和C编写,运行效率和程序大小大不相同。

就感应加热控制器而言,这么简单的功能,用上16位的DSP已是足矣实现控制所需和人机界面所需的各种功能,更别说用ARM,甚至再加UCOS-II这样的小系统了。编写这样的软件,你去用C语言固然很简单,但真正在单片机里面运行的实用性确是不太理想。如果用汇编来写,那就相对较好了。

也有C和汇编互通偷懒的方法,如果不愿意用汇编来写,你可以用C先写完了,然后编译,出来相应的汇编,再在此基础上做调试修改,那就方便了。

0
回复
uuniao
LV.5
11
2012-01-15 14:52
@stevenpe
不太认同贴片机的观点。C和汇编相比较而言,固然C更高级,更进一步,但具体选择还是要看应用场合和自己的擅长。相对于汇编而言,C语言是更简单,更傻瓜式的语言。有些时候,不是说做事情一味的要从源头做起,只是同样的功能的程序,用汇编和C编写,运行效率和程序大小大不相同。就感应加热控制器而言,这么简单的功能,用上16位的DSP已是足矣实现控制所需和人机界面所需的各种功能,更别说用ARM,甚至再加UCOS-II这样的小系统了。编写这样的软件,你去用C语言固然很简单,但真正在单片机里面运行的实用性确是不太理想。如果用汇编来写,那就相对较好了。也有C和汇编互通偷懒的方法,如果不愿意用汇编来写,你可以用C先写完了,然后编译,出来相应的汇编,再在此基础上做调试修改,那就方便了。
早就有基于OS的方案了,现在的编译器编译出来的汇编代码比你自己用汇编写的好很多的……
0
回复
stevenpe
LV.4
12
2012-01-15 18:44
@uuniao
早就有基于OS的方案了,现在的编译器编译出来的汇编代码比你自己用汇编写的好很多的……
,估计是偷懒一族,你的理由是电脑比人脑好使,人编出来的编译器比人好使。
0
回复
uuniao
LV.5
13
2012-01-16 09:10
@stevenpe
[图片],估计是偷懒一族,你的理由是电脑比人脑好使,人编出来的编译器比人好使。

呵呵,做电源的兄弟硬件的居多,对软件精通的很少,小程序固守在汇编的世界里还好,大的程序就很难喽……

咱们不讨论编译器,但是有一点,如果平台更换的时候汇编和C那个更有优势呢,如果代码上几万行呢……

0
回复
stevenpe
LV.4
14
2012-01-16 15:38
@uuniao
呵呵,做电源的兄弟硬件的居多,对软件精通的很少,小程序固守在汇编的世界里还好,大的程序就很难喽……咱们不讨论编译器,但是有一点,如果平台更换的时候汇编和C那个更有优势呢,如果代码上几万行呢……
你说的没错,我们讨论的就是在电源的应用,试问你说的这个如果在电源这行业的应用里成立的有多少?当然,如果你编个交换机或者工控机的底层软件,那就另当别论了,别说用汇编来做,就是用C来做,也得累死个人啊。
0
回复
骆记123
LV.5
15
2012-04-18 17:26
@stevenpe
你说的没错,我们讨论的就是在电源的应用,试问你说的这个如果在电源这行业的应用里成立的有多少?当然,如果你编个交换机或者工控机的底层软件,那就另当别论了,别说用汇编来做,就是用C来做,也得累死个人啊。
Arm7刚开始裸奔的路过。
0
回复