uCOS在C51单片机上的移植

合集下载

uCOS在C51单片机上的移植

uCOS在C51单片机上的移植

uCOS-II 在C51 单片机上的移植(1)实时系统和前/后台系统;前/后台系统:一个大循环,循环查询各种标志位。

如果标志位置位,就执行相应的服务程序。

标志位就是标志事件的发生,事件响应延时处于不可预测状态。

最坏的情况是循环中所有其他的事件服务程序执行完,才响应当前事件。

中断服务虽然能即时/优先响应,但是它们和主循环的通讯,也是通过置主循环中相应的标志位来完成的。

实时系统(uCOS):整个程序分成一个个看起来好象是并行的任务,每个任务都在等待事件的发生。

因为uCOS不支持时间片轮转,除了最低优先级任务(在uCOS中是IDLE任务)是死循环以外,其他的任务都不能死循环,只能在驱动事件驱动下工作。

任何驱动事件的产生,都使优先级最高的就绪任务运行。

任务和任务/任务和中断的通讯,是通过相应事件驱动来完成的。

驱动事件:不论是什么系统,CPU不可能一直在工作。

CPU的工作是在各种驱动事件的驱动下工作的。

CPU在完成一次驱动事件事件服务程序以后,进入IDLE模式等待新的驱动事件的发生。

包括实时系统和前/后台系统都是在驱动事件的驱动下运行的。

按照uCOS中的观点,驱动事件分为三类:1、事件(Event)。

包括信号量(Semaphores)、事件标志组(Flag)、邮箱(Message Box)、邮箱队列(Message Queue)。

2、时间(Time Tick)。

包括时间延时和事件超时。

3、中断(Interrupt)。

可以发出各种event。

由于第1种事件,通常都是在第2、3种状态下发出的,所以其实事件的驱动只有两种:时间(定时)和中断(各种异步中断)。

时间实际上也是中断的一种,可以说程序的驱动事件只有一种,就是:中断。

前/后台系统中还有一种驱动事件的产生,在主循环中不断的查询。

有别与一般的定时查询,这种查询是为了将事件的响应时间降到最低,也可以将其归纳于定时(时间)事件。

(2)uCOS C51移植的准备工作;2004年8月份,我在书城买了一本《uCOS-Ⅱ第2版》,准备学习RTOS。

UCOSII在51单片机运行成功

UCOSII在51单片机运行成功

UCOSII在51单片机运行成功以下是我的移植过程:1、新建一个文件夹aduc845ucosii来存放整个工程,再在aduc845ucosii下建立两个目录:os和out。

os存放所有源代码,out存放编译链接产生的中间文件和最终的输出文件。

2、建立KEILC工程,芯片选择ADUC845并且加入默认的启动代码START_AD.A513、把所有用到的源文件都复制到OS文件夹内,也就是现在在OS 内所有文件。

4、在KEIL的WORKSPACE下Source Group 1右击,把OS文件夹内以下文件加入源码:uCOS_II.C、OS_CPU_C.C、OS_CPU_A.ASM、test.c、serial.c、serial.h。

然后还得把KEIL安装目录下的XX\KEIL\C51\LIB下的C51BFPC.LIB和C51L.LIB加入源码组。

这里要解释一下:uCOS_II.C是内核文件,OS_CPU_C.C、OS_CPU_A.ASM是移植文件,test.c是main函数文件,serial.c、serial.h是test.c里用到串口才把它们加进源码,而C51BFPC.LIB和C51L.LIB这两个文件据果子说是因为用到了浮点运算,要加入这两个库文件。

加入的文件最好是按顺序加入,特别是两个库文件,如果反了,就可能出现运行不了或者不正确。

5、打开Options for Target "Target 1",切换到Target选项卡,把Memory Model改为Large: variables in XDATA。

再切换到Output选项卡,点击"Select Folder for Objects",选择out文件夹,勾选Create hex File,按OK确定,再切换到Listing选项卡,点击"Select Folder for Listings",选择out文件夹,按OK确定。

uCOS51移植心得

uCOS51移植心得

uCOS51 移植心得讨论1----uCOS51 高效内核前一段时间我参与了一个SNMP 网管板的项目我负责硬件设计和单板软件开发该板的硬件由MCS51+RTL8019AS 组成有64K FLASH 和64K SRAM 软件部分有操作系统和TCPIP 协议栈硬件比较简单用了一个月就搞定了协议栈我参考了老古开发板的部分程序又上网找了SNMP 源代码也很快完成了但是测试时发现当使用较低时钟频率的CPU 时为了降低成本由于ASN.1 编解码部分过于庞大而我的程序又是一个大循环AGENT 的响应速度受到严重影响用户界面也反应迟钝更坏的消息是公司为了适应市场需求还要在上面跑PPP 和HTTP 那样的话我就得用40MHz 的AT89C51RD2 或者人为的把程序断成几部分然后用状态机的方法在运行时再把它们连接起来不过我不想增加成本也不想把程序搞乱迫不得已只好使用操作系统说实在的一开始我也不是很有把握一来我不清楚51 的FLASH 是否装得下这么多代码二来我只做过OS 应用开发对于它的移植想都不敢想不过我在BBS 上搜索了一阵儿后还是有了一些头绪我找到了几个OS 的源代码我喜欢用现成的按照代码大小实时性使用人数众人口碑等标准最后选定了uCOS2 我感觉它的实时性有保障延时可预测代码据说可小到2K 网上讨论这个话题的人也比较多而且它的网站上有针对KEIL C51 的移植实例经过一番查找我得到了5 个版本其中3 个是用KEIL 编译的本来我想直接把OS代码嵌到应用程序中但后来发现没有一个可以直接使用有的无法用KEIL 直接编译有的需要修改DLL 在软件仿真下使用而我需要的是能在串口输入输出不需要修改任何无关软件能在软件仿真和硬件上运行的实时多任务操作系统没有办法我只好硬着头皮去改编我分析了自己的劣势1 KEIL 刚开始使用不太熟悉2 混合编程以前从没有作过3 时间紧迫要在1 个月内搞定而我的优势就是有5 个移植实例可供参考可以上网查资料一开始我用堆栈混合编程汇编ucos 等关键字在C51BBS 和老古论坛上检索相关信息并逐条阅读读过之后头脑中的思路逐渐清晰了我了解到在KEIL 的HLP 目录下有A51.PDF 和C51.PDF 非常全面的介绍了汇编和C51 是KEIL 的权威用户手册SP 初始化内存清0 等操作在STARTUP.A51 文件中实现用户可以改写它KEIL 的变量子程序等的分配信息可以在.M51 文件里查到KEIL 自己的论坛里有很多疑难问题的解答通过阅读并经过思考解决了堆栈起点堆栈空间大小的设定等关键问题论坛里的问题有些是我没有想到的这使我发现了自己的疏漏在网上获得大量信息后我开始阅读uCOSII 中文版一共读了3 遍第一遍是浏览了解到uCOSII 包括任务调度时间管理内存管理资源管理信号量邮箱消息队列四大部分没有文件系统网络接口输入输出界面它的移植只与 4 个文件相关汇编文件OS_CPU_A.ASM 处理器相关C 文件OS_CPU.H OS_CPU_C.C 和配置文件OS_CFG.H 有64 个优先级系统占用8 个用户可创建56 个任务不支持时间片轮转第二遍主要是把整个工作过程在头脑里过了一下不懂的地方有针对性地查书重点是思考工作原理和流程我发现其实它的思路挺简单的就是近似地每时每刻总是让优先级最高的就绪任务处于运行状态为了保证这一点它在调用系统API 函数中断结束定时中断结束时总是执行调度算法原作者通过事先计算好数据简化了运算量通过精心设计就绪表结构使得延时可预知任务的切换是通过模拟一次中断实现的第三遍重点看了移植部分的内容对照实例研究了代码的具体实现方法前期准备用了20 几天真正编写代码只用了1.5 天调试用了2 天具体过程如下(1)拷贝书后附赠光盘sourcecode 目录下的内容到C:\YY 下删除不必要的文件和EX1L.C 只剩下p187( uCOSII )上列出的文件(2)改写最简单的OS_CPU.H数据类型的设定见C51.PDF 第176 页注意BOOLEAN 要定义成unsigned char 类型因为bit类型为C51 特有不能用在结构体里EA=0 关中断EA=1 开中断这样定义即减少了程序行数又避免了退出临界区后关中断造成的死机MCS-51 堆栈从下往上增长(1=向下0=向上) OS_STK_GROWTH 定义为0#define OS_TASK_SW() OSCtxSw() 因为MCS-51 没有软中断指令所以用程序调用代替两者的堆栈格式相同RETI 指令复位中断系统RET 则没有实践表明对于MCS-51 用子程序调用入栈用中断返回指令RETI 出栈是没有问题的反之中断入栈RET出栈则不行总之对于入栈子程序调用与中断调用效果是一样的可以混用在没有中断发生的情况下复位中断系统也不会影响系统正常运行详见uC/OS-II 第八章193 页第12 行(3)改写OS_CPU_C.CTCB 结构体中OSTCBStkPtr 总是指向用户堆栈最低地址该地址空间内存放用户堆栈长度其上空间存放系统堆栈映像即用户堆栈空间大小=系统堆栈空间大小+1SP 总是先加1 再存数据因此SP 初始时指向系统堆栈起始地址(OSStack)减 1 处(OSStkStart) 很明显系统堆栈存储空间大小=SP-OSStkStart任务切换时先保存当前任务堆栈内容方法是用SP-OSStkStart 得出保存字节数将其写入用户堆栈最低地址内以用户堆栈最低地址为起址以OSStkStart 为系统堆栈起址由系统栈向用户栈拷贝数据循环SP-OSStkStart 次每次拷贝前先将各自栈指针增1其次恢复最高优先级任务系统堆栈方法是获得最高优先级任务用户堆栈最低地址从中取出长度以最高优先级任务用户堆栈最低地址为起址以OSStkStart 为系统堆栈起址由用户栈向系统栈拷贝数据循环长度数值指示的次数每次拷贝前先将各自栈指针增1用户堆栈初始化时从下向上依次保存用户堆栈长度15 PCL PCH PSWACC B DPL DPH R0 R1 R2 R3 R4 R5 R6 R7 不保存SP 任务切换时根据用户堆栈长度计算得出OSTaskStkInit 函数总是返回用户栈最低地址操作系统tick 时钟我使用了51 单片机的T0 定时器它的初始化代码用C 写在了本文件中最后还有几点必须注意的事项本来原则上我们不用修改与处理器无关的代码但是由于KEIL 编译器的特殊性这些代码仍要多处改动因为KEIL 缺省情况下编译的代码不可重入而多任务系统要求并发操作导致重入所以要在每个 C 函数及其声明后标注reentrant 关键字另外pdata data 在uCOS 中用做一些函数的形参但它同时又是KEIL 的关键字会导致编译错误我通过把pdata 改成ppdata data 改成ddata解决了此问题OSTCBCur OSTCBHighRdy OSRunning OSPrioCur OSPrioHighRdy 这几个变量在汇编程序中用到了为了使用Ri 访问而不用DPTR 应该用KEIL 扩展关键字IDATA 将它们定义在内部RAM 中(4)重写OS_CPU_A.ASMA51 宏汇编的大致结构如下NAME 模块名;与文件名无关;定义重定位段必须按照C51 格式定义汇编遵守C51 规范段名格式为?PR?函数名?模块名;声明引用全局变量和外部子程序注意关键字为EXTRN 没有E全局变量名直接引用无参数/无寄存器参数函数FUNC带寄存器参数函数_FUNC重入函数_?FUNC;分配堆栈空间只关心大小堆栈起点由keil 决定通过标号可以获得keil 分配的SP 起点切莫自己分配堆栈起点只要用DS 通知KEIL 预留堆栈空间即可?STACK段名与STARTUP.A51 中的段名相同这意味着KEIL 在LINK 时将把两个同名段拼在一起我预留了40H 个字节STARTUP.A51 预留了1 个字节LINK 完成后堆栈段总长为41H 查看yy.m51 知KEIL 将堆栈起点定在21H 长度41H 处于内部RAM 中;定义宏宏名MACRO 实体ENDM;子程序OSStartHighRdyOSCtxSwOSIntCtxSwOSTickISRSerialISREND ;声明汇编源文件结束一般指针占3 字节+0 类型+1 高8 位数据+2 低8 位数据详见C51.PDF 第178 页低位地址存高8 位值高位地址存低8 位值例如0x1234 基址+0:0x12 基址+1:0x34(5)移植串口驱动程序在此之前我写过基于中断的串口驱动程序包括打印字节/字/长字/字符串读串口初始化串口/缓冲区把它改成重入函数即可直接使用系统提供的显示函数是并发的它不是直接显示到串口而是先输出到显存用户不必担心IO 慢速操作影响程序运行串口输入也采用了同样的技术他使得用户在CPU 忙于处理其他任务时照样可以盲打输入命令(6)编写测试程序Demo(YY.C)Demo 程序创建了3 个任务A B C 优先级分别为2 3 4 A 每秒显示一次B每3 秒显示一次C 每6 秒显示一次从显示结果看显示3 个A 后显示1 个B 显示6个A 和2 个B 后显示1 个C 结果显然正确显示结果如下AAAAAA111111 is activeAAAAAA111111 is activeAAAAAA111111 is activeBBBBBB333333 is activeAAAAAA111111 is activeAAAAAA111111 is activeAAAAAA111111 is activeBBBBBB333333 is activeCCCCCC666666 is activeAAAAAA111111 is activeAAAAAA111111 is activeAAAAAA111111 is activeBBBBBB333333 is activeAAAAAA111111 is activeAAAAAA111111 is activeAAAAAA111111 is activeBBBBBB333333 is activeCCCCCC666666 is activeDemo 程序经Keil701 编译后代码量为7-8K 可直接在KeilC51 上仿真运行编译时要将OS_CPU_C.C UCOS_II.C OS_CPU_A.ASM YY.C 加入项目以上是我这次移植uCOS51 的一些心得写出来只是让准备在51 上运行操作系统的同行们少走弯路并增强使用信心我强烈推荐大家在自己的51 系统中使用uCOS 这个简单实用的自己的操作系统它的大小应该不是问题性能上的提高却是显著的但愿此文能对朋友们有所帮助错误在所难免希望各位大虾指正诸位高手们见笑了注全部源码可来信索要(asdjf@) 以下仅为关键代码部分文件名: OS_CPU_A.ASM$NOMOD51EA BIT 0A8H.7SP DA TA 081HB DA TA 0F0HACC DATA 0E0HDPH DA TA 083HDPL DATA 082HPSW DA TA 0D0HTR0 BIT 088H.4TH0 DATA 08CHTL0 DATA 08AHNAME OS_CPU_A ;模块名;定义重定位段?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE?PR?OSCtxSw?OS_CPU_A SEGMENT CODE?PR?OSIntCtxSw?OS_CPU_A SEGMENT CODE?PR?OSTickISR?OS_CPU_A SEGMENT CODE?PR?_?serial?OS_CPU_A SEGMENT CODE;声明引用全局变量和外部子程序EXTRN IDATA (OSTCBCur)EXTRN IDATA (OSTCBHighRdy)EXTRN IDATA (OSRunning)EXTRN IDATA (OSPrioCur)EXTRN IDATA (OSPrioHighRdy)EXTRN CODE (_?OSTaskSwHook)EXTRN CODE (_?serial)EXTRN CODE (_?OSIntEnter)EXTRN CODE (_?OSIntExit)EXTRN CODE (_?OSTimeTick);对外声明4 个不可重入函数PUBLIC OSStartHighRdyPUBLIC OSCtxSwPUBLIC OSIntCtxSwPUBLIC OSTickISR;PUBLIC SerialISR;分配堆栈空间只关心大小堆栈起点由keil 决定通过标号可以获得keil 分配的SP 起点?STACK SEGMENT IDATARSEG ?STACKDS 40HOSStkStart IDATA OSStack-1;定义压栈出栈宏PUSHALL MACROPUSH PSWPUSH ACCPUSH BPUSH DPLPUSH DPHMOV A,R0 ;R0-R7 入栈PUSH ACCMOV A,R1PUSH ACCMOV A,R2PUSH ACCMOV A,R3PUSH ACCMOV A,R4PUSH ACCMOV A,R5PUSH ACCMOV A,R6PUSH ACCMOV A,R7PUSH ACC;PUSH SP ;不必保存SP 任务切换时由相应程序调整ENDMPOPALL MACRO;POP ACC ;不必保存SP 任务切换时由相应程序调整POP ACC ;R0-R7 出栈MOV R7,APOP ACCMOV R6,APOP ACCMOV R5,APOP ACCMOV R4,APOP ACCMOV R3,APOP ACCMOV R2,APOP ACCMOV R1,AMOV R0,APOP DPHPOP DPLPOP BPOP ACCPOP PSWENDM;子程序;-------------------------------------------------------------------------RSEG ?PR?OSStartHighRdy?OS_CPU_AOSStartHighRdy:USING 0 ;上电后51 自动关中断此处不必用CLR EA 指令因为到此处还未开中断本程序退出后开中断LCALL _?OSTaskSwHookOSCtxSw_in:;OSTCBCur ===> DPTR 获得当前TCB 指针详见C51.PDF 第178 页MOV R0,#LOW (OSTCBCur) ;获得OSTCBCur 指针低地址指针占3 字节+0 类型+1 高8 位数据+2 低8 位数据INC R0MOV DPH,@R0 ;全局变量OSTCBCur 在IDATA 中INC R0MOV DPL,@R0;OSTCBCur->OSTCBStkPtr ===> DPTR 获得用户堆栈指针INC DPTR ;指针占3 字节+0 类型+1 高8 位数据+2 低8 位数据MOVX A,@DPTR ;.OSTCBStkPtr 是void 指针MOV R0,AINC DPTRMOVX A,@DPTRMOV R1,AMOV DPH,R0MOV DPL,R1;*UserStkPtr ===> R5 用户堆栈起始地址内容(即用户堆栈长度放在此处) 详见文档说明指针用法详见C51.PDF 第178 页MOVX A,@DPTR ;用户堆栈中是unsigned char 类型数据MOV R5,A ;R5=用户堆栈长度;恢复现场堆栈内容MOV R0,#OSStkStartrestore_stack:INC DPTRINC R0MOVX A,@DPTRMOV @R0,ADJNZ R5,restore_stack;恢复堆栈指针SPMOV SP,R0;OSRunning=TRUEMOV R0,#LOW (OSRunning)MOV @R0,#01POPALLSETB EA ;开中断RETI;-------------------------------------------------------------------------RSEG ?PR?OSCtxSw?OS_CPU_AOSCtxSw:PUSHALLOSIntCtxSw_in:;获得堆栈长度和起址MOV A,SPCLR CSUBB A,#OSStkStartMOV R5,A ;获得堆栈长度;OSTCBCur ===> DPTR 获得当前TCB 指针详见C51.PDF 第178 页MOV R0,#LOW (OSTCBCur) ;获得OSTCBCur 指针低地址指针占3 字节+0 类型+1 高8 位数据+2 低8 位数据INC R0MOV DPH,@R0 ;全局变量OSTCBCur 在IDATA 中INC R0MOV DPL,@R0;OSTCBCur->OSTCBStkPtr ===> DPTR 获得用户堆栈指针INC DPTR ;指针占3 字节+0 类型+1 高8 位数据+2 低8 位数据MOVX A,@DPTR ;.OSTCBStkPtr 是void 指针MOV R0,AINC DPTRMOVX A,@DPTRMOV R1,AMOV DPH,R0MOV DPL,R1;保存堆栈长度MOV A,R5MOVX @DPTR,AMOV R0,#OSStkStart ;获得堆栈起址save_stack:INC DPTRINC R0MOV A,@R0MOVX @DPTR,ADJNZ R5,save_stack;调用用户程序LCALL _?OSTaskSwHook;OSTCBCur = OSTCBHighRdyMOV R0,#OSTCBCurMOV R1,#OSTCBHighRdyMOV A,@R1MOV @R0,AINC R0INC R1MOV A,@R1MOV @R0,AINC R0INC R1MOV A,@R1MOV @R0,A;OSPrioCur = OSPrioHighRdy 使用这两个变量主要目的是为了使指针比较变为字节比较以便节省时间MOV R0,#OSPrioCurMOV R1,#OSPrioHighRdyMOV A,@R1MOV @R0,ALJMP OSCtxSw_in;-------------------------------------------------------------------------RSEG ?PR?OSIntCtxSw?OS_CPU_AOSIntCtxSw:;调整SP 指针去掉在调用OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容;SP=SP-4MOV A,SPCLR CSUBB A,#4MOV SP,ALJMP OSIntCtxSw_in;-------------------------------------------------------------------------CSEG AT 000BH ;OSTickISRLJMP OSTickISR ;使用定时器0RSEG ?PR?OSTickISR?OS_CPU_AOSTickISR:USING 0PUSHALLCLR TR0MOV TH0,#70H ;定义Tick=50 次/秒(即0.02 秒/次)MOV TL0,#00H ;OS_CPU_C.C 和OS_TICKS_PER_SECSETB TR0LCALL _?OSIntEnterLCALL _?OSTimeTickLCALL _?OSIntExitPOPALLRETI;-------------------------------------------------------------------------CSEG AT 0023H ;串口中断LJMP SerialISR ;工作于系统态无任务切换RSEG ?PR?_?serial?OS_CPU_ASerialISR:USING 0PUSHALLCLR EALCALL _?serialSETB EAPOPALLRETI;-------------------------------------------------------------------------END;-------------------------------------------------------------------------文件名: OS_CPU_C.Cvoid *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos, INT16U opt) reentrant {OS_STK *stk;ppdata = ppdata;opt = opt; //opt 没被用到保留此语句防止告警产生stk = (OS_STK *)ptos; //用户堆栈最低有效地址*stk++ = 15; //用户堆栈长度*stk++ = (INT16U)task & 0xFF; //任务地址低8 位*stk++ = (INT16U)task >> 8; //任务地址高8 位*stk++ = 0x00; //PSW*stk++ = 0x0A; //ACC*stk++ = 0x0B; //B*stk++ = 0x00; //DPL*stk++ = 0x00; //DPH*stk++ = 0x00; //R0*stk++ = 0x01; //R1*stk++ = 0x02; //R2*stk++ = 0x03; //R3*stk++ = 0x04; //R4*stk++ = 0x05; //R5*stk++ = 0x06; //R6*stk++ = 0x07; //R7//不用保存SP 任务切换时根据用户堆栈长度计算得出return ((void *)ptos);}#if OS_CPU_HOOKS_ENvoid OSTaskCreateHook (OS_TCB *ptcb) reentrant{ptcb = ptcb; /* Prevent compiler warning*/}void OSTaskDelHook (OS_TCB *ptcb) reentrant{ptcb = ptcb; /* Prevent compiler warning*/}void OSTimeTickHook (void) reentrant{ }#endif//初始化定时器0void InitTimer0(void) reentrant{TMOD=TMOD&0xF0;TMOD=TMOD|0x01; //模式1(16 位定时器) 仅受TR0 控制TH0=0x70; //定义Tick=50 次/秒(即0.02 秒/次)TL0=0x00; //OS_CPU_A.ASM 和OS_TICKS_PER_SECET0=1; //允许T0 中断TR0=1;}文件名: YY.C#include <includes.h>#define MAX_STK_SIZE 64void TaskStartyya(void *yydata) reentrant;void TaskStartyyb(void *yydata) reentrant;void TaskStartyyc(void *yydata) reentrant;OS_STK TaskStartStkyya[MAX_STK_SIZE+1];//注意我在ASM 文件中设置?STACK 空间为40H 即64 不要超出范围OS_STK TaskStartStkyyb[MAX_STK_SIZE+1];//用户栈多一个字节存长度OS_STK TaskStartStkyyc[MAX_STK_SIZE+1];void main(void){OSInit();InitTimer0();InitSerial();InitSerialBuffer();OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],2);OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3);OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],4); OSStart();}void TaskStartyya(void *yydata) reentrant{yydata=yydata;clrscr();PrintStr("\n\t\t*******************************\n"); PrintStr("\t\t* Hello! The world. *\n");PrintStr("\t\t*******************************\n\n\n");for(;;){PrintStr("\tAAAAAA111111 is active.\n");OSTimeDly(OS_TICKS_PER_SEC);}}void TaskStartyyb(void *yydata) reentrant{yydata=yydata;for(;;){PrintStr("\tBBBBBB333333 is active.\n");OSTimeDly(3*OS_TICKS_PER_SEC);}}void TaskStartyyc(void *yydata) reentrant{yydata=yydata;for(;;){PrintStr("\tCCCCCC666666 is active.\n");OSTimeDly(6*OS_TICKS_PER_SEC);}}。

在Keil_C51_v7上移植UcOS_IIV251

在Keil_C51_v7上移植UcOS_IIV251

在Keil C51 v7上针对MCS51的UcOS-II V2.51移植过程钟文青(zhongwenqing@)源码参照:(1)杨屹:ucOS51,V1.1 ()(2)ucOS-II V2.51的Keil移植(johnxliu@) ,可从ucOS-II官方网站上的下载杨屹的源码可以直接使用,特别是堆栈设计正好适合MCS51,我也没有想出更好的结构,因此沿用这种堆栈结构,就是ucOS-II的堆栈检查函数在这种结构下就没有用了。

杨屹的源码是ucOS-II V2.00版的基础上移植的,v2.51版对中断嵌套作了处理,而且也增加不少Hook函数,以及其他功能。

直接使用(2)的移植并不成功,无法直接编译使用,源码部分的小毛病不少,Keil7的setjmp.h本身就有毛病,我没运行起来,估计是堆栈部分有问题(也可能是我水平有限)。

但是其用C写ISR的方式觉得不错,移植性以及可读性好。

综合(1)、(2)的优点,我按以下步骤作了一个移植(1)将ucOS-II的大部分源码作些改动,主要是函数加上reentrant定义,将使用到data, pdata等keil C关键字的地方改动,data->ddata, pdata->ppdata。

另外还根据ucOS-II 网站公布的bug改了原来源码中的3个bug。

(2)关键的OS_CPU.H, OS_CPU_C.C, OS_CPU_A.ASM使用杨屹的为主体,将源码(2)中的定义的新Hook函数,OS_CRITICAL_METHOD的功能添加到其中。

原来杨屹的源码,OS_Enter_Critical(), OS_Exit_Critical()简单的用了EA=0,EA=1来控制中断,现在用方式3可以保留原EA的状态,可以保证在调度前不发生中断,原来的方式效率高,但如果在初始化过程中调用了OS_Exit_Critical()就打开了中断,如果期间发生中断则系统会进入一个不可知的状态。

ucos-II移植到51单片机的解决办法

ucos-II移植到51单片机的解决办法

ucos-II移植到51单片机的解决办法本文主要是关于ucos-II的相关介绍,并着重对ucos-II移植到51单片机进行了详尽的阐述。

ucos-IIμC/OS-II由Micrium公司提供,是一个可移植、可固化的、可裁剪的、占先式多任务实时内核,它适用于多种微处理器,微控制器和数字处理芯片(已经移植到超过100种以上的微处理器应用中)。

同时,该系统源代码开放、整洁、一致,注释详尽,适合系统开发。

μC/OS-II已经通过联邦航空局(FAA)商用航行器认证,符合航空无线电技术委员会(RTCA)DO-178B标准。

μC/OS-II被广泛应用于微处理器、微控制器和数字信号处理器。

μC/OS-II 的前身是μC/OS,最早出自于1992 年美国嵌入式系统专家Jean brosse 在《嵌入式系统编程》杂志的5 月和6 月刊上刊登的文章连载,并把μC/OS 的源码发布在该杂志的B B S 上。

μC/OS 和μC/OS-II 是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。

CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。

用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌入到开发的产品中。

μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至2KB 。

μC/OS-II 已经移植到了几乎所有知名的CPU 上。

严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。

没有提供输入输出管理,文件系统,网络等额外的服务。

但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。

uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。

uCOS51移植心得[社区](精)

uCOS51移植心得[社区](精)

uCOS51移植心得[社区]全局变量名直接引用无参数/无寄存器参数函数FUNC带寄存器参数函数_FUNC重入函数_?FUNC;分配堆栈空间只关心大小,堆栈起点由keil 决定,通过标号可以获得keil分配的SP起点。

切莫自己分配堆栈起点,只要用DS通知KEIL预留堆栈空间即可。

?STACK段名与STARTUP.A51中的段名相同,这意味着KEIL在LINK时将把两个同名段拼在一起,我预留了40H个字节,STARTUP.A51预留了1个字节,LINK完成后堆栈段总长为41H。

查看yy.m51知KEIL将堆栈起点定在21H,长度41H,处于内部RAM中。

;定义宏宏名MACRO 实体ENDM;子程序OSStartHighRdyOSCtxSwOSIntCtxSwOSTickISRSerialISREND ;声明汇编源文件结束一般指针占3字节。

+0类型+1高8位数据+2低8位数据详见C51.PDF 第178页低位地址存高8位值,高位地址存低8位值。

例如0x1234,基址+0:0x12 基址+1:0x34(5)移植串口驱动程序在此之前我写过基于中断的串口驱动程序,包括打印字节/字/长字/字符串,读串口,初始化串口/缓冲区。

把它改成重入函数即可直接使用。

系统提供的显示函数是并发的,它不是直接显示到串口,而是先输出到显存,用户不必担心IO慢速操作影响程序运行。

串口输入也采用了同样的技术,他使得用户在CPU忙于处理其他任务时照样可以盲打输入命令。

(6)编写测试程序Demo(YY.C)Demo程序创建了3个任务A、B、C优先级分别为2、3、4,A每秒显示一次,B每3秒显示一次,C每6秒显示一次。

从显示结果看,显示3个A后显示1个B,显示6个A和2个B后显示1个C,结果显然正确。

显示结果如下:AAAAAA111111 isactiveAAAAAA111111 is activeAAAAAA111111 is activeBBBBBB333333 is activeAAAAAA111111 is activeAAAAAA111111 isactiveAAAAAA111111 is activeBBBBBB333333 is activeCCCCCC666666 is activeAAAAAA111111 is activeAAAAAA111111 isactiveAAAAAA111111 is activeBBBBBB333333 is activeAAAAAA111111 is activeAAAAAA111111 is activeAAAAAA111111 isactiveBBBBBB333333 is activeCCCCCC666666 is activeDemo程序经Keil701编译后,代码量为7-8K,可直接在KeilC51上仿真运行。

UCOS-II在51单片机上的移植

UCOS-II在51单片机上的移植

UCOS-II在51单片机上的移植做操作系统的移植首先明白什么是移植,操作系统是一种鱼硬件(处理器)相关的软件,根据某一种处理器来设计的操作系统通常不能运行在那其他处理器。

所谓的移植是指修改操作系统,然后加载到一个处理器上。

本文只讲解步骤,至于理论知识,需要大家自己学习。

步骤:1,在UCOS-II的官网上下载,操作系统。

2,在网上找到或者自己建三四个文件:OS_CPU_A.ASSMOS_CPU.HOS_CPU_C.COS_CFG.H以上文件需要修改3,移植源码的编写和修改❖OS_CPU.H1)定义与编译器有关的数据类型typedef unsigned char BOOLEAN; /* 不能使用bit定义,结构中无法使用*/typedef unsigned char INT8U; /* 无符号8位数*/typedef unsigned char INT8S; /* 有符号8位数*/typedef unsigned int INT16U; /* 无符号16位数*/typedef signed int INT16S; /* 有符号16位数*/typedef unsigned long INT32U; /* 无符号32位数*/typedef signed long INT32S; /* 有符号32位数*/typedef float FP32; /* 单精度浮点数*/typedef double FP64; /* 双精度浮点数*/typedef unsigned char OS_STK; /* 定义堆栈入口宽度为8位*/typedef unsigned char OS_CPU_SR; /* 定义CPU状态字的宽度为8位*/2)定义堆栈增长方向#define OS_STK_GROWTH 0 /* MCS-51堆栈从下往上增长,1=向下,0=向上*/3)定义任务级的任务切换宏#define OS_TASK_SW() OSCtxSw() /* 任务级的任务切换宏*/4)定义临界段宏:#define OS_ENTER_CRITICAL() EA=0#define OS_EXIT_CRITICAL() EA=1❖OS_CPU_C.C①初始化任务栈void *OSTaskStkInit(void(*task)(void *pd), void *ppdata, void *ptos, INT16U opt) REENTRANT{O S_STK *stk;p pdata=ppdata; //pata data 为52文件关键字o pt =opt; /* opt没被用到,保留此语句防止警告产生 */s tk =(OS_STK *)ptos; /* 任务堆栈最低有效地址*/*stk++=15; /* 任务堆栈长度*/ *stk++=(INT16U)task & 0xFF; /* 任务代码地址低8位*/*stk++=(INT16U)task >> 8; /* 任务代码地址高8位*//* 处理器是按特定的顺序将寄存器存入堆栈的,所以用户在将寄存器存入堆栈的时候也要依照这一顺序 */*stk++=0x00; /* PSW*/*stk++=0x0A; /* ACC*/*stk++=0x0B; /* B */ *stk++=0x00; /* DPL*/*stk++=0x00; /* DPH*/*stk++=0x00; /* R0 */ *stk++=0x01; /* R1 */ *stk++=0x02; /* R2 */ *stk++=0x03; /* R3 */ *stk++=0x04; /* R4 */ *stk++=0x05; /* R5 */ *stk++=0x06; /* R6 */ *stk++=0x07; /* R7 */ /* 不用保存SP,任务切换时根据用户堆栈长度计算得出*/*stk++=(INT16U)(ptos+MAX_STK_SIZE) >> 8; /* ?C_XBP 仿真堆栈指针高8位 */*stk++=(INT16U)(ptos+MAX_STK_SIZE) & 0xFF; /* ?C_XBP 仿真堆栈低8位*/r eturn ((void *)ptos); /* 返回最低地址,这里不用弹出栈顶指针是为了提高计算效率 */}②初始化定时器void InitTimer0(void) REENTRANT{TMOD=TMOD&0xF0; //屏蔽高四位TMOD=TMOD|0x01; /* 模式1(16位定时器),仅受TR0控制 */ TH0=TIMER_20MS_TH0;TL0=TIMER_20MS_TL0;E A=0; /* EA和ET0,51上电缺省值为0,EA将在OSStartHighRdy()中打开*/ET0=0; /* 满足在OSStart()前不产生时钟中断的要求,系统启动后第一时间开定时器T0中断 */TR0=1;}❖OS_CPU_A.ASM编写4个函数OSStartHighRdy()OSCtxSw()OSIntCtxSw()OSTickISR()❖OS_CFG.H主要为参数和使能的宏定义#define MAX_STK_SIZE 1024 /* 最大堆栈大小为1k*/#define OS_MAX_EVENTS 5 /* 应用程序中事件控制块的最大数量(必须大于零)*/#define OS_MAX_FLAGS 2 /* 应用程序中事件标志组的最大数目(必须大于零)*/#define OS_MAX_MEM_PART 5 /* 内存分区的最大数目(必须大于零)*/#define OS_MAX_QS 2 /* 应用程序中队列控制块的最大数目(必须大于零)*/#define OS_MAX_TASKS 11 /* 应用程序中任务的最大数目(必须大于2)*/#define TASK_START_PRIO 2 /* 应用程序开始优先级*/#define OS_LOWEST_PRIO 12 /* 定义可分配的最低优先级(必须大于63)*/#define TASK_STK_SIZE 512 /* 默认任务堆栈大小*/#define OS_TICKS_PER_SEC 50 /* 设置每秒节拍数*/#define TIMER_20MS_TH0 0x70 /* CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TH0=0x70 */#define TIMER_20MS_TL0 0x00 /* CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TL0=0x00 */晶振频率为22.1184MHz时才有OS_TICKS_PER_SEC=50,OS_TICKS_PER_SEC=50。

uCOS-II在51单片机上的移植

uCOS-II在51单片机上的移植

功能
处理临界段方式选择 堆栈增长方向 进入临界区 退出临界区 就绪态最高优先级任务运行 任务级任务切换 中断级任务切换 时钟节拍 任务堆栈初始化
表7-1 需要修改的关键函数和宏定义
6
7.1.6 INCLUDES.H

* * * * * * 文件名 : INCLUDES.H * 作者 : Jean J. Labrosse ****************************************************************************/
9
7.1.8 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()
临界代码的概念。 uC/OS-II定义的两个宏。
{ OS_ENTER_CRITICAL(); /* µC/OS-II 临界代码段 */ OS_EXIT_CRITICAL(); }
#define OS_ENTER_CRITICAL() EA=0 #define OS_EXIT_CRITICAL() EA=1 #define OS_ENTER_CRITICAL() \
例如,任务A和任务B都要调用函数Swap(), 而该函数又使用了全局变量temp。于是当任 务A调用Swap()函数期间,系统发生了任务 切换而使任务B也调用了Swap(),那么任务B 将要改变全局变量temp的值,使任务A传递 给全局变量temp的值丢失而出现错误。
一般来说,一个可重入函数应该在函数中只 使用局部变量,因为函数的局部变量存储在 任务的堆栈中,所以可保证不同的任务在调 用同一个函数时不会发生冲突。
/ ******************* 与处理器相关的代码 ********************/ #define OS_CRITICAL_METHOD ?? #if OS_CRITICAL_METHOD = = 1 #define OS_ENTER_CRITICAL() ?? #define OS_EXIT_CRITICAL() ?? #endif

_C_OS_在51系列单片机上的移植

_C_OS_在51系列单片机上的移植

2004年第6期总第273期 导弹与航天运载技术M ISSIL ES AND SPACE V EHICL ES No.62004Sum No.273文章编号:100427182(2004)0620036207收稿日期:2003207209作者简介:董余红(19792),男,硕士研究生,研究方向为导弹与运载火箭信息系统总体设计μC/OS -Ⅱ在51系列单片机上的移植董余红,阎俊武(北京宇航系统工程设计部,北京,100076)摘要:介绍了嵌入式实时操作系统内核μC/OS -Ⅱ在51系列单片机上的移植的详细步骤。

关键词:单片机;嵌入式实时操作系统;内核;μC/OS -Ⅱ;移植中图分类号:TP316.2 文献标识码:APorting μC/OS -Ⅱto 512Family MicroprocessorDong Yuhong ,Yan J unwu(Beijing Institute of Astronautical Systems Engineering ,Beijing ,100076)Abstract :The steps to porting the embedded real time operating system kernel μC/OS -Ⅱto 512family microprocessor are described detailedly and relevant source code are provided in this paper.K ey Words :microprocessor ;Embedded real time operating system ;K ernel ;μC/OS -Ⅱ;Port1 简 介μC/OS -Ⅱ由美国工程师Jean brosse 设计,是一个优秀的源代码公开的嵌入式实时操作系统内核,可以比较容易地移植到各种不同的微处理器上。

现在,μC/OS -Ⅱ的2.52版已经通过了非常严格的测试,并且得到了美国航空管理局(Federal Aviation Administration )的安全认证,可以用在飞行器上。

uCOS-II在51单片机上的移植

uCOS-II在51单片机上的移植

uC\OS-II在51单片机上的移植戴国强、史培杰(安阳工学院计算机科学与信息工程系)摘要:uC\OS-II以其结果清晰、性能稳定、源码公开等特点,受到广大嵌入式开发人员的青睐,已作为嵌入式实时操作系统被移植到许多微处理器上,在国防、航空航天、交通、能源、工业控制、通信以及人们日常生活等各个领域得到了广泛应用。

关键字:嵌入式实时操作系统、uC\OS-II、移植、MCS-51单片机Abstract: Based on the advantage of clear structure,stable capability and free sound code,the uC\OS-II comes in for lots of people's like who empolder the embedded system.As a embedded real-time operation system,the uC\OS-II has been repoted on lots of MCU,and has widely used an plays a very important role in many fields, such as national defence,spacenavigation,traffic,energy sources,industry control,communications,and civil living.Key words: the embedded real-time operationsystem,uC\OS-II,transplant,Single Chip Computer of MCS-51随着电子技术与软件技术的飞速发展,嵌入式系统技术已经成了最热门的技术之一。

嵌入式实时操作系统是嵌入式应用软件的基础和开发平台,其中涉及到软件和硬件两方面的问题。

51单片机上移植ucos-II

51单片机上移植ucos-II

嵌入式实时操作系统实验报告 51单片机上移植μC/ OS-II系别计算机与电子系专业班级电子0901班学生姓名高傲指导教师黄向宇提交日期 2012 年 4 月 17 日一、实验目的理解移植μC/OS-II的一般原理及基本方法。

掌握在51单片机上移植μC/ OS-II的方法及步骤,掌握在51单片机上基于μC/ OS-II系统构建应用程序的基本原理及方法。

二、实验内容1.建立并熟悉编译及仿真调试环境(keil + proteus)。

2.下载已移植好的软件包,在开发环境下建立工程编译并运行观察运行结果,使用Keil自带的仿真调试工具观察程序运行情况(内存的分配、变量及CPU 寄存器的动态变化、任务的切换运行状态等);比较移植前和移植后的相关文件,分析移植过程中做了哪些改动工作。

3.结合前两次实验内容,在移植软件包的基础上尝试增加用户任务,并利用信号量、消息邮箱等建立任务之间的通信联系;同时尝试采用动态内存分配的方法为任务分配内存,使用Keil仿真工具观察程序运行情况并记录运行结果。

4.输入课本P220的例子程序,编译运行并观察运行结果。

5. 将以上调试好的软件移植到proteus开发环境中去,利用proteus的硬件仿真环境创建几个实际任务(如键盘、显示器、LED点阵、数码管、时钟或温度传感器等)给每个赋以适当的优先级,配置合适的堆栈容量,编译运行并观察运行情况,显示信息可以用液晶显示器或虚拟终端来显示。

三.实验原理1. 移植的概念所谓移植,就是使一个实时内核能在某个微处理器或微控制器上运行。

为了方便移植,大部分的µC/OS-Ⅱ代码是用C语言写的;但仍需要用C和汇编语言写一些与处理器相关的代码,这是因为µC/OS-Ⅱ在读写处理器寄存器时只能通过汇编语言来实现。

由于µC/OS-Ⅱ在设计时就已经充分考虑了可移植性,所以µC/OS-Ⅱ的移植相对来说是比较容易的。

要使µC/OS-Ⅱ正常运行,处理器必须满足以下要求:1. 处理器的C编译器能产生可重入代码。

uCOS-II移植51的汇编部分原理

uCOS-II移植51的汇编部分原理

原理:
由于51单片机RAM比较小,所以各个任务堆栈的内容放在片外RAM,而只在片内设了一个公有堆栈,一旦一个任务被选中,则在任务切换时把该任务在片外的RAM存储的堆栈内容复制到片内公用堆栈,而公用堆栈中的被终止运行任务的堆栈内容复制到该任务片外堆栈中。

程序实现:
在51单片机的外部RAM中设置任务堆栈,任务堆栈的最低地址空间用来存放用户堆栈的长度,并使该任务的TCB中的OSTCBStkPtr指针变量指向该地址。

任务切换时,应该先把当前任务在公用堆栈(即片内RAM中的)的内容复制保存在本身任务堆栈(片外)中。

即用SP-OSStkStart得出保存字节数,将其写入用户堆栈最低地址内,以用户堆栈最低地址为起址,以OSStkStart为系统堆栈起址,由系统栈向用户栈拷贝数据,循环SP-OSStkStart次,每次拷贝前先将各自栈指针增1。

将就绪优先级最高任务的任务堆栈复制到系统堆栈。

方法是:获得最高优先级任务用户堆栈最低地址,从中取出“长度”,以最高优先级任务用户堆栈最低地址为起址,以OSStkStart为系统堆栈起址,由用户栈向系统栈拷贝数据,循环“长度”数值指示的次数,每次拷贝前先将各自栈指针增1。

程序注释见OS_CPU_A.asm内的中文注释,可用记事本打开该文件。

ucos51移植

ucos51移植

在51系列单片机上移植uCOS-II引言:随着各种应用电子系统的复杂化和系统实时性需求的提高,并伴随应用软件朝着系统化方向发展的加速,在16位/32位单片机中广泛使用了嵌入式实时操作系统。

然而实际使用中却存在着大量8位单片机,从经济性考虑,对某些应用场合,在8位MCU上使用操作系统是可行的。

从学习操作系统角度,uC/OS-II for 51即简单又全面,学习成本低廉,值得推广。

结语:μC/OS-II具有免费、简单、可靠性高、实时性好等优点,但也有缺乏便利开发环境等缺点,尤其不像商用嵌入式系统那样得到广泛使用和持续的研究更新。

但开放性又使得开发人员可以自行裁减和添加所需的功能,在许多应用领域发挥着独特的作用。

当然,是否在单片机系统中嵌入μC/OS-II应视所开发的项目而定,对于一些简单的、低成本的项目来说,就没必要使用嵌入式操作系统了。

uC/OS-II原理:uCOSII包括任务调度、时间管理、内存管理、资源管理(信号量、邮箱、消息队列)四大部分,没有文件系统、网络接口、输入输出界面。

它的移植只与4个文件相关:汇编文件(OS_CPU_A.ASM)、处理器相关C文件(OS_CPU.H、OS_CPU_C.C)和配置文件(OS_CFG.H)。

有64个优先级,系统占用8个,用户可创建56个任务,不支持时间片轮转。

它的基本思路就是“近似地每时每刻总是让优先级最高的就绪任务处于运行状态” 。

为了保证这一点,它在调用系统API函数、中断结束、定时中断结束时总是执行调度算法。

原作者通过事先计算好数据,简化了运算量,通过精心设计就绪表结构,使得延时可预知。

任务的切换是通过模拟一次中断实现的。

uCOSII工作核心原理是:近似地让最高优先级的就绪任务处于运行状态。

操作系统将在下面情况中进行任务调度:调用API函数(用户主动调用),中断(系统占用的时间片中断OsTimeTick(),用户使用的中断)。

调度算法书上讲得很清楚,我主要讲一下整体思路。

ucos2操作系统在51单片机上的移植

ucos2操作系统在51单片机上的移植

μC/OS-Ⅱ在51单片机上的移植姓名:学号:目录1 绪论 (2)1.1 嵌入式实时操作系统 (2)1.2 μC/OS-Ⅱ嵌入式操作系统 (2)1.3 μC/OS-Ⅱ原理 (2)2 μC/OS-Ⅱ内核结构 (3)2.1 临界区 (3)2.2 任务及任务控制块 (3)2.3 任务状态 (4)2.4 任务调度 (5)2.5 中断处理 (5)2.6 时钟节拍 (5)2.7 μC/OS-Ⅱ初始化与启动 (6)3 μC/OS-Ⅱ在51单片机上的移植 (6)3.1 OS_CPU.H文件的移植 (6)3.2 OS_CPU_A.ASM文件的移植 (8)3.3 OS_CPU_C.C文件的移植 (20)4 移植结果测试 (23)4.1 设计原理 (23)4.2 应用程序设计 (23)4.3 结果分析 (25)1 绪论1.1嵌入式实时操作系统大多数的操作系统只注重平均性能,如对于整个系统来说,所有任务的平均响应时间是关键,而不关心单个任务的响应时间。

而嵌入式实时操作系统最主要的特征是性能上的实时性,从这个角度上看,可以把嵌入式实时操作系统定义为“当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统”。

目前大多数嵌入式操作系统提供以下管理功能:1.任务管理所有嵌入式操作系统都是多任务的,目前所说的多任务大都是指多线程方式或多进程方式,两者的运行机制不完全一样。

以多进程为例,调度程序的好坏直接影响到系统的性能。

和一般的操作系统一样,嵌入式操作系统的作用也是决定在特定的某一时刻系统应该运行哪一个进程,对嵌入式系统中的运行软件进行描述和管理,并完成处理机资源的分配与调度。

2.存储管理在嵌入式系统中,一般不采用虚拟内存管理,而采用动态内存管理方式,即当程序的某一部分需要使用内存时,利用操作系统提供的分配函数来处理,一旦使用完,可通过释放函数来释放所占用的内存,这样内存就可以重复使用,这样提高了内存的利用率,方便了用户的使用,并提供了足够的存储空间。

uCOSⅡ内核在80C51系列单片机上的移植

uCOSⅡ内核在80C51系列单片机上的移植

;以下代码完成第①步操作
万方数据
·——2097·——
PUSHALL:用户定义的宏,将全部CPU寄存器保存到 3.2实验的过程和结果
系统堆栈
实验过程主要镪括以下3个步骤:@创建两个任务Taskl
MOV A,SP;淤下3匍蜜现获褥堆筏戆长度
秘Task2,验涯OSTaskStldnit袭OSStartHighRdyoi蕊数;◇刳建
save_stack: ;以下实现从系统堆棱到用户堆栈豹拷贝 INC DFFR:撵自惩产臻筏
巍输出的不同结聚,验证OSIntCtxSw鞠OSTicklSR函数。 主要测试健弱黧下:
0引言
近年来,嵌入式系统已成为后PC时代一个广阔的研发领 域,其应用范围越来越广。实际应用中,由于移植所花费代价 最小,原有操作系统无法支持新增应用功能时,常会采用系统 移植来解决问题。uC/OS.II作为一个高可靠,开源的嵌入式实 时操作系统,具有广泛的应用;而利用廉价的80C51实现众多 传感器、控制器等电子设备的网络互联,更是具有先天优势。 因此在80C51上移植uC/OS.II具有重要的意义。本文以uC/ OS.II为移植对象,以80C51为移植目标来详细讨论移植的过 程,其中自己设计了一个堆栈结构;最后给出移植测试实验, 分析了移植中要注意的一些问题,总结了移植的一般方法。
1移植前的准备工作
移植前首先要对移植对象,移植目标及其结构,以及移植 的编译环境进行了解。这样才会起到事半功倍的效果。以下 便是从这几个方面进行简单分析。 1.1 移植对象——uc,os.Ⅱ

uC/OS.II具有很强的可移植性,可以广泛应用于各类8 位,16位,32位微控制器或DSP中。它具有完全可剥夺型的 实时内核,其核心工作原理是让最高优先级的就绪任务处于 运行状态;它具有多任务的特点,可以管理64个任务,其中56

51单片机对μC-OS-II实时操作系统的移植

51单片机对μC-OS-II实时操作系统的移植

51单片机对μC/OS-II实时操作系统的移植μC/OS-II是一种公开源代码、结构小巧、具有可剥夺实时内核的嵌入式开发系统,代码简短、条理清晰、实时性及安全性能很高,绝大部分代码用C编写,现已被移植到多种处理器的构架中。

随着51单片机片内资源的日益丰富,在51单片机上移植μC/OS-II已成为可能,植入系统后,由系统来管理软件与硬件资源,简化应用程序的设计,并且使应用系统功能更加完善。

因此在51单片机上移植μC/OS-II具有十分重要的意义。

1 μC/OS实时操作系统概述μC/OS-II实时操作系统是一种可移植、可固化、可裁剪即可剥夺型的多任务实时内核,适用于各种微处理器和微控制器。

μC/OS-II主要包括任务调度、时间管理、内存管理、事件管理(信号量、邮箱、消息队列)4大部分。

它的移植与4个文件相关:汇编文件(OS_CPU_A.A SM)、处理器相关C文件(OS_CPU.H、OS_CPU_C.C)和配置文件(OS_CFG.H)。

有64个优先级,系统占用8个,用户可创建56任务,不支持时间片轮转。

它的基本思路就是“近似地每时每刻总是让优先级最高的就绪任务处于运行状态”。

为了保证这一点,它在调用系统函数、中断结束、定时中断结束时总是执行调度算法。

原作者通过事先计算好数据,简化了运算量,通过精心设计就绪表结构,使得延时可预知。

任务的切换是通过模拟一次中断实现的。

2 任务调度的实现原理任务调度是μC/OS-II的重要部分,和具体的微处理器关系紧密。

必须移植的5个函数有4个都和任务有关。

任务调度就是保存当前任务的寄存器和PC指针(即当前任务的断点),然后把将要执行的任务的寄存器值返回给寄存器并把PC指向将要执行任务的断点。

这些的实现要借助于堆栈和中断,为了简便起见,先看函数调用时堆栈的使用情况。

在函数调用时,堆栈的一个重要功能就是保存被调函数的断点地址。

若有4个函数,Fun1调用Fun2,Fun2调用Fun3,Fun3调用Fun4,Fun4为叶子程序(无子程序调用)。

在51系列单片机上移植uCOS

在51系列单片机上移植uCOS

μC/OS II在MCS51单片机上的移植2008-05-29 12:07摘要:嵌入式系统融合了微电子、计算机软/硬件、通信和电子工程等多种技术、广泛应用于各种工业和民用领域,是科技集成创新的主要手段。

嵌入式操作系统也由于编程方式比传统方式有着明显的优越性,在越来越多的场合得到广泛的应用。

在中国,单片机具有相当广泛的使用基础,虽然51系列单片机功能相对较低,但是针对某些任务较简单、要求具备较高实时性的场合,研究嵌入式系统的移植还是具有重要的现实意义。

本文从探讨嵌入式系统移植的意义开始,通过阐述嵌入式系统在过去几十年期间的发展过程以及当今的发展现状,总结出嵌入式系统的发展趋势,并简要的描述μC/OS II在MCS51单片机上的移植方法,综合讲述了嵌入式系统移植这一课题的技术和背景。

关键词:μC/OS II 移植意义现状发展1 引言:单片机是电子信息行业最杰出的作品之一,由于它具有出色的面向控制能力,因此在工业控制、智能仪器仪表、家用电器、外设控制、机器人和军事装置等方面都得到了广泛的应用。

但是当面对多任务的应用场合时,如果没有精心复杂的设计以及丰富的后期维护调试经验,采用传统的编程方式设计往往会发生不可预料的错误且难以弥补。

此外,在这种条件下应用程序对硬件具有很强的依赖性,硬件只要稍微发生变化,软件就必须要作大量的变更和调试工作。

这也是限制单片机应用进一步发展的重要原因。

在电子技术迅猛发展的当今,随着实用电子系统的复杂化和系统实时性需求的提高,以及应用软件的系统化发展,嵌入式实时操作系统(Embedded Real-time Operating System)已经广泛地使用在各式各样的以单片机为代表的硬件平台上,从而很大程度的解决了多任务使用环境的需求问题。

在实际的生产生活中,使用着大量以MCS51为代表的8位单片机,虽然性能及存储空间有限,但是从经济方面考虑,对于某些应用场合,在8位MCU上使用操作系统依然是可行的。

嵌入式实时操作系统μC/OS在C51平台上的移植及应用

嵌入式实时操作系统μC/OS在C51平台上的移植及应用

嵌入式实时操作系统μC/OS在C51平台上的移植及应用娄小平【摘要】Embedded operating system play an increasingly important role because of its simple, efficient. We choose the μC / OS-II whose source code is public, small and portable can be cut, and select the C51 microprocessor application plat-form.We migrate μC / OS%嵌入式操作系统以其简洁、高效等优点扮演了越来越重要的角色。

选择了源代码公开、体积小且可裁剪移植性好的μC/OS—II,选择C51微处理器为应用平台,根据实际项目要求把μC/OS—II移植到C51单片机上。

移植的过程主要集中在三个文件的重新编写上:一个头文件OS—CPU.H、一个C代码文件OS—CPU_C.C和一个汇编文件OS_CPU_A.ASM文件。

还针对C51的小内存所做的优化,对可重入问题的进行了分析与解决,基本达到应用的需要。

【期刊名称】《电脑与信息技术》【年(卷),期】2011(019)004【总页数】4页(P54-57)【关键词】嵌入式系统;μC/OS;C51平台;移植【作者】娄小平【作者单位】[1]湖南文理学院计算机科学与技术学院,湖南常德415000;[2]中南大学信息科学与工程学院,湖南长沙410000【正文语种】中文【中图分类】TP316.2作为嵌入式系统(包括硬、软件系统)极为重要的组成部分的嵌入式操作系统,通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。

嵌入式操作系统具有通用操作系统的基本特点,如:能够有效管理越来越复杂的系统资源;能够把硬件虚拟化,使得开发人员从繁忙的驱动程序移植和维护中解脱出来;能够提供库函数、驱动程序、工具集以及应用程序。

OS在C51平台上的移植及应用的开题报告

OS在C51平台上的移植及应用的开题报告

嵌入式实时操作系统μC/OS在C51平台上的移植及应用的开题报告一、选题背景及研究目的嵌入式实时操作系统(RTOS)是嵌入式系统中广泛使用的操作系统,它为具有实时性要求的应用程序提供了资源管理、任务调度、通信机制等功能,大大提高了嵌入式系统的可靠性、可维护性和可扩展性。

其中,μC/OS是一个功能强大、可靠性高、开放式的RTOS,广泛应用于微处理器、嵌入式网络和控制系统等领域。

C51是一种广泛使用的8位单片机,具有成本低、易于使用等优点,广泛应用于消费电子、家电、汽车电子等领域。

本文旨在通过在C51平台上移植μC/OS,分析实现的过程、开发工具、硬件平台及移植后的应用效果,为嵌入式系统的开发提供技术支持和参考。

二、研究内容和方法本文的主要研究内容包括以下几个方面:1.μC/OS的介绍及功能特点2.C51平台的介绍及特点,以及μC/OS在C51平台上的需求分析3.μC/OS在C51平台上的移植过程,包括内存管理、任务调度、消息队列等4.移植后的测试和应用,包括任务执行时间、系统资源占用率、通信效率、可靠性等指标的测试,以及在实际应用中的效果5.总结与展望,对移植过程中遇到的问题进行总结,对嵌入式操作系统未来的发展趋势进行展望在研究方法上,本文采用了理论分析和实验验证相结合的方法。

首先,对μC/OS 的功能特点、内核原理等进行理论分析;其次,结合C51平台的特点进行需求分析和移植实现;最后,利用实验验证对移植后的系统进行实测和分析。

三、预期成果及意义本文的预期成果包括以下几个方面:1.基于C51平台成功移植μC/OS,并在实验中进行了测试和分析2.验证了在C51平台上利用μC/OS构建实时嵌入式系统的可行性和可靠性3.提出了在移植μC/OS时需要注意的问题和经验,为相关研究提供了参考本文的意义在于:1. 为嵌入式系统开发人员提供技术支持和经验总结,提高嵌入式系统开发的效率和可靠性;2. 推广μC/OS在C51平台上的应用,扩展其应用范围,促进嵌入式系统的发展;3. 贡献一份力量,推动嵌入式操作系统的发展,为自动化、智能化等领域的发展提供支撑和保障。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

uCOS-II 在C51 单片机上的移植(1)实时系统和前/后台系统;前/后台系统:一个大循环,循环查询各种标志位。

如果标志位置位,就执行相应的服务程序。

标志位就是标志事件的发生,事件响应延时处于不可预测状态。

最坏的情况是循环中所有其他的事件服务程序执行完,才响应当前事件。

中断服务虽然能即时/优先响应,但是它们和主循环的通讯,也是通过置主循环中相应的标志位来完成的。

实时系统(uCOS):整个程序分成一个个看起来好象是并行的任务,每个任务都在等待事件的发生。

因为uCOS不支持时间片轮转,除了最低优先级任务(在uCOS中是IDLE任务)是死循环以外,其他的任务都不能死循环,只能在驱动事件驱动下工作。

任何驱动事件的产生,都使优先级最高的就绪任务运行。

任务和任务/任务和中断的通讯,是通过相应事件驱动来完成的。

驱动事件:不论是什么系统,CPU不可能一直在工作。

CPU的工作是在各种驱动事件的驱动下工作的。

CPU在完成一次驱动事件事件服务程序以后,进入IDLE模式等待新的驱动事件的发生。

包括实时系统和前/后台系统都是在驱动事件的驱动下运行的。

按照uCOS中的观点,驱动事件分为三类:1、事件(Event)。

包括信号量(Semaphores)、事件标志组(Flag)、邮箱(Message Box)、邮箱队列(Message Queue)。

2、时间(Time Tick)。

包括时间延时和事件超时。

3、中断(Interrupt)。

可以发出各种event。

由于第1种事件,通常都是在第2、3种状态下发出的,所以其实事件的驱动只有两种:时间(定时)和中断(各种异步中断)。

时间实际上也是中断的一种,可以说程序的驱动事件只有一种,就是:中断。

前/后台系统中还有一种驱动事件的产生,在主循环中不断的查询。

有别与一般的定时查询,这种查询是为了将事件的响应时间降到最低,也可以将其归纳于定时(时间)事件。

(2)uCOS C51移植的准备工作;2004年8月份,我在书城买了一本《uCOS-Ⅱ第2版》,准备学习RTOS。

因为以前没有玩过RTOS,在工作之余断断续续的看了3、4章。

一直到12月初的时候,公司要重新设计一个项目,恰好要把uCOS移植到c51上。

我的RTOS学习才正式开始。

因为对OS向往以久,我并不想在网上Down一个现成的移植OS程序,做一个OS的应用者。

揭开OS的神秘面纱,了解OS的内部运行机制,这才是我想要做的。

本文的主要目的是讨论uCOS的移植,希望对即将进行uCOS c51移植的兄弟有些帮助。

对于OS的内部运行机制,由于东西比较多,在这里不想太展开。

如果以后有时间,也想写一篇文章来讨论讨论。

最开始,我的计划就是看书,看《uCOS-Ⅱ第2版》。

看完这本几百页的大本本,花了我2个半星期。

因为是工作需要,我才可以这样心安理得的在那里看呀看书^_^,辛苦呀9。

在这期间,为了自己的思想不受别人的影响,我坚决没有从网上下任何uCOS的资料,我手头的资料就是uCOS-Ⅱ的书和附带光盘,这些就是最权威的资料了。

在看书的时候,我都坚持做笔记,把每天的重点,明白的东西和心中的疑问都随时记录下来。

对付这种大本本,前后的知识又相互关联,光靠我们的大脑是搞不定啊。

弄懂了uCOS的内核,下一本书应该是《单片机高级语言C51Windows环境编程与应用》。

对于Keil C我还是很熟的,还是花了2、3天来复习。

这里的重点是C51对汇编的转换结构,例于数据/系统堆栈的使用,C&Asm混合编程。

我想对于任何CPU的uCOS移植,C语言的实现机制,你都是要了解的。

这里也是要花大把时间的。

《uCOS-Ⅱ第2版》和《单片机高级语言C51Windows环境编程与应用》这两本书网上都可以下电子档的,我这里也有(大家需要可以来信索取)。

uCOS和C51的书都看完了。

我就下载了一堆uCOS的C51移植资料。

其中的源程序有很多个版本的,不过详细的移植文档只有一个版本:巨龙一位大虾的"uCOS C51移植心得",相信很多人都看过。

这些资料的作者都是我移植过程中的老师,有了这些资料,我才能把心中的朦胧想法变成源程序。

但是我也发现这些资料中大多都有一些错误和遗漏,当然这是难免的。

这也正是驱使我写这篇文章的原因,希望在前辈的基础上有所进步。

欢迎大家来批评!真正的源代码移植,我花了大概一个星期时间。

(3)uCOS C51的移植概况;1、工具:uCOS 2.52版;Keil C V6.23a。

2、uCOS V2.52的文件结构与移植所需要的修改:A、与处理器无关的文件:OS_CORE.COS_FLAG.COS_MBOX.COS_MEM.COS_MUTEX.COS_Q.COS_SEM.COS_TASK.COS_TIME.CuCOS_II.CuCOS_II.H这些文件在c51的移植过程中,只需要给函数加上重入属性即可。

B、与应用相关的文件:INCLUDES.H:包含C51的标准库头文件;对"pdata"等c51关键字的重定义OS_CFG.H:"OS_TICKS_PER_SEC"、" OS_FLAGS"注意可能需要修改。

C、与处理器相关的文件:OS_CPU.H:数据类型、关中断方法、任务堆栈方向、任务切换的宏定义都需要修改。

OS_CPU_A.ASM:OSTickISR()、OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()这几个函数的编写,是整个移植的关键。

OS_CPU_C.C:OSTaskStkInit()函数的编写。

(4)uCOS C51具体的移植过程;1、C51的堆栈结构;这是整个移植过程中的重中之重,所以特别详细介绍。

A、系统堆栈;c51中,系统堆栈的栈底地址是"?STACK",栈顶指针就是"SP"拉,栈的生长方向是向上的,栈空间分配在51的内部RAM(idata)中。

"?STACK"分配在所有内部RAM数据段的最后面,所以系统堆栈的范围是从?STACK到内部RAM的最高位(0x80或者0xFF)。

B、数据堆栈;c51中,由于我们使用OS,采用的LARGE编译模式,所以数据堆栈的指针是"?C_XBP",栈的生长方向是向下的,栈空间分配在51的外部RAM(xdata)中。

C、C51中断中堆栈的保护;研究中断中堆栈的保护的意义在于,因为uCOS中的任务切换,本身就是模拟一次中断的发生:保护Task1的CPU寄存器,SP切换到Task2的堆栈,弹出Task2的CPU寄存器。

用C51写中断函数的时候,编译器会自动保护CPU的寄存器,所以中断返回时任务调度OSIntCtxSw(),就不用重新保护寄存器。

C51中断中调用函数可以分为四种情况(中断函数本身不设为reentrant):一、没有函数调用;二、调用非reentrant函数,函数中没有嵌套调用其他函数;三、调用非reentrant函数,函数中嵌套调用其他函数;四、调用reentrant函数。

t0_isr:PUSH ACCPUSH BPUSH DPHPUSH DPLPUSH PSWMOV PSW,#00HPUSH AR0PUSH AR1PUSH AR2PUSH AR3PUSH AR4PUSH AR5PUSH AR6PUSH AR7用户代码POP AR7POP AR6POP AR5POP AR4POP AR3POP AR2POP AR1POP AR0POP PSWPOP DPLPOP DPHPOP BPOP ACCRETI因为uCOS中所有的函数都必须是重入函数,因此我们只需要研究第四种情况下的堆栈保护,对于其他情况有兴趣可以在c51中看看。

(注意:可能因为c51编译器的版本不同,上述压栈的顺序可能不同。

)2、uCOS C51任务切换时的堆栈操作;每个任务都有一个独立的数据堆栈,系统堆栈是公用空间。

保护Task1的CPU寄存器:首先将CPU寄存器按上例压进Task1系统堆栈,再将整个Task1系统堆栈压进Task1数据堆栈;SP切换:?C_XBP = Task2 的数据堆栈栈顶地址。

弹出Task2的CPU寄存器:从Task2的数据堆栈重新恢复整个系统堆栈,然后再从Task2系统堆栈中恢复CPU寄存器值。

实现的方法有很多种,只要遵循uCOS任务切换的原理就可以了。

3、INCLUDES.H的移植;重点:"pdata"是C51关键字,所以要重新定义源代码:#i nclude#i nclude#i nclude#i nclude#i nclude#i nclude#define TASK_REENTRANT large reentrant #define KCREENTRANT large reentrant #i nclude "os_cpu.h"#i nclude "os_cfg.h"#define data ucos51_data#define idata ucos51_idata#define pdata ucos51_pdata#define xdata ucos51_xdata#i nclude "ucos_ii.h"4、OS_CPU.H的移植;typedef unsigned char BOOLEAN;typedef unsigned char INT8U;typedef signed char INT8S;typedef unsigned int INT16U;typedef signed int INT16S;typedef unsigned long INT32U;typedef signed long INT32S;typedef float FP32;typedef unsigned char OS_STK;#define BYTE INT8S#define UBYTE INT8U#define WORD INT16S#define UWORD INT16U#define LONG INT32S#define ULONG INT32UC51编程:uCOS51移植心得uCOS51移植心得asdjf@ 2002/10/03前一段时间,我参与了一个SNMP网管板的项目,我负责硬件设计和单板软件开发。

该板的硬件由MCS51+RTL8019AS组成,有64K FLASH 和64K SRAM。

软件部分有操作系统和TCPIP协议栈。

硬件比较简单,用了一个月就搞定了,协议栈我参考了老古开发板的部分程序又上网找了SNMP源代码也很快完成了,但是测试时发现当使用较低时钟频率的CPU时(为了降低成本),由于ASN.1编解码部分过于庞大,而我的程序又是一个大循环,AGENT的响应速度受到严重影响,用户界面也反应迟钝。

相关文档
最新文档