这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 实时操作系统uCOS-Ⅱ在196KC上的移植[下载]

共3条 1/1 1 跳转至

实时操作系统uCOS-Ⅱ在196KC上的移植[下载]

工程师
2003-02-17 23:40:55     打赏
[upload=doc]uploadImages/200321715394347027.doc[/upload] 实时操作系统uC/OS-Ⅱ在196KC上的移植 作 者:西安交通大学电器教研室 王巍 南京因泰莱电器股份有限公司 刘唯 摘 要: 主要讨论了ucos在196KC单片机上的移植,编译器为Tasking c,并给出了一个实例,经实测与理论分析一致,说明移植成功。 关键词: 196KC ucos Tasking c 移植 Abstact: This paper discusses porting ucos RTOS to 196KC chip by using Tasking c compiler,and also gives the instance which is proved successful through practice. Keywords: 196KC ucos Tasking c porting 引 言 INTEL的80196KC系列单片机在国内有很大一批用户,且已有很长一段历史。支持196KC的c编译器生产厂商主要有Tasking和IAR。但国内使用Tasking公司的C编译器用户较多。ucos为源码公开的实时操作系统。在嵌入式系统中采用实时操作系统已成为当前嵌入式系统开发的主要方法。在ucos网站上没有现成的移植案例。有必要进行一次移植。操作系统为ucos,处理器为80196KC,编译器为Tasking c 196. 1 ucos的工作原理 ucos是一个源码公开的实时多任务操作系统,其主要工作流程如图1示。其任务切换的核心是利用出栈指令将各个任务的工作现场再现,并利用子程序返回指令改变PC指针完成任务的切换。移植的关键就是如何构造任务堆栈及任务切换时的出栈顺序。任务区堆栈初始化主要是模拟任务被中断后的堆栈内容。在这个流程中我们可以看到我们要编写的几个子程序的工作位置。 图 1 2 196KC的工作状态表示方法 196KC是INTEL的16位单片机,和程序运行密切相关的寄存器有指令计数器PC、堆栈指针sp、程序状态寄存器PSW,中断屏蔽寄存器INTMASK和INTMASK1,窗口寄存器WSR(以下将程序状态寄存器PSW,中断屏蔽寄存器INTMASK和INTMASK1,窗口寄存器WSR统称为程序状态字)。执行子程序调用call指令时自动将pc进栈,子程序返回调用RET指令时自动将pc出栈。由于196KC有16位的寻址能力,故这一动作有2个字节进(出)栈。pusha指令将程序状态字进栈,popa指令将程序状态字出栈,这一动作共有4个字节进(出)栈。另外pusha动作会将PSW中的中断允许位清零,故我们用pusha关闭中断,用popa将用来恢复中断允许。时钟节拍是一个特定的周期性中断,在每个时钟节拍到来时对任务延时做一次裁决。在此时钟节拍我们采用196KC中的软件定时器中断。 3 Tasking c编译器的工作细节 带参数的函数调用编译后主要操作是先将参数进栈,然后执行call指令。在函数入口处将堆栈中的参数倒入寄存器tmp0,tmp2,tmp4和tmp6进行操作(以下称临时寄存器),这主要是堆栈一般在RAM区,对RAM区操作不如对寄存器操作快。如果该函数有局部变量,局部变量也是分配在堆栈中。Tasking c编译器用一寄存器?frame01(以下称框架寄存器)对局部变量进行访问,这也是为了提高程序运行效率。函数返回时执行ret操作,并对SP指针进行调整,跳过函数的参数在堆栈中的位置。中断调用和函数调用类似,中断本身虽没有参数,但进中断后也要对临时寄存器进行保护。另外进中断后执行pusha操作。中断返回时临时寄存器出栈(注意出栈顺序),再执行popa和ret操作。图2所示为堆栈区结构。 图 2 4 移植的细节 在OSTaskStkInit()中任务堆栈区的构造。196KC的堆栈区由高向低增长,首先高处是任务的入口参数,接着是PC指针,程序状态字,如前述,任务切换时要对临时寄存器和框架寄存器进行保护。明确了任务堆栈的构造后,编写任务启动函数(指OSStaart函数)和任务切换函数(指OS_TAASK_SW和OSIntCtxSw函数)的关键就是,当得到了最高优先级的任务堆栈指针后,如何按正确的顺序出栈,直到PC指针。其中OS_TASK_SW()函数在切换任务之前还要编写对当前任务的现场进行保护程序,而OSIntCtxSw()不用,因为我们的中断函数用C写成,OSIntCtxSw()是在中断中调用的,Tasking C编译器在进中断时已自动对其保护。但同时还应注意,在中断服务程序中我们没有定义局部变量,故Tasking C编译器没有对框架寄存器进行保护,对这一寄存器的保护我们自己加上。 #pragma interrupt (OSTickISR=OS_TICK_ISR_VECTOR) void OSTickISR(void) { asm push ?frame01; OSIntNesting++; hso_command=0x19; AD_Timer_Count+=5000; hso_time = AD_Timer_Count; OSTimeTick(); OSIntExit(); asm pop ?frame01; } 在此还应提醒一下,在其它中断服务程序中如果没有定义局部变量,也应加上对框架寄存器的保护。如果有局部变量,编译器会自动对框架寄存器保护。 在编写OSIntCtxSw()函数时应当注意,由于OSIntCtxSw()是在OSIntExit()中调用的,在调用OSIntCtxSw()之前又有一个关中断的操作。如前述,我们采用pusha的方式关中断,也就是说如果切换另一高优先级的任务后会在当前任务中留下在OSIntCtxSw()和OSIntExit()调用的返回地址4个字节的垃圾和pusha关中断时进栈的4个字节垃圾,共8个字节,为保证下次切换到该任务的正确性,要将SP指针加8,然后再进行任务切换。为加深对此的理解,我们做一假设,如果196KC是24位(3个字节)寻址能力,在当前任务中会留下OSIntCtxSw()和OSIntExit()调用的返回地址6个字节的垃圾,如果关中断直接采用asm di方式,而不牵扯到堆栈操作,此时SP要调整6个字节而不是8个字节。 5 正确性检验 设计一点灯程序。其6个灯,每一个点灯操作用一个单独任务。任务流程如图3示。第一个灯每两个时钟节拍做一次异或操作。如果LED1每执行2次异或操作向任务2发一信号量2,每执行3次异或操作向任务3发一信号量3,每执行4次异或操作向任务4发一信号量4,每执行5次异或操作向任务5发一信号量5,每执行6次异或操作向任务6发一信号量6。任务2到任务6接到相应的信号量时对自已控制的灯进行一次异或操作。理论分析,LED2到LED6的波形周期为LED1的2到6 倍。用示波器对6 个灯的波形进行观察,与分析相符合,连续运行n 天没有发现down 机和复位,证明移植成功。 图 3 参考文献 1 Labrosse Jean J.MicroC/OS-ⅡThe Real-Time Kernel. 2 邵贝贝译. uC/OS-Ⅱ-源码公开的实时嵌入式操作系统. 北京: 中国电力出版社, 2001



关键词: 实时     操作系统     uCOS-     196KC     移植     下载    

菜鸟
2003-03-04 20:39:00     打赏
2楼
帖子开始处有附件文档下载

菜鸟
2003-03-07 03:07:00     打赏
3楼
都有关

共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]