摘要:主要讨论了将μC/OS-II实时操作系统在8019KC单片机上进行移植的原理和方法,给出了一个以Tasking C为编译器、以8019KC为处理器,对μC/OS-II实时操作系统进行移植的具体实例。
关键词:80196KC; uC/OS-II;Tasking C;移植
Intel的80196KC系列单片机在中国国内有很大一批用户。支持80196KC的C编译器生产厂商主要有Tasking和IAR。但国内使用Tasking公司C编译器的用户较多。由于μC/OS-Ⅱ系统为源码公开的实时操作系统,因此是当前嵌入式系统开发的主要方法。但是,在μC/OS-Ⅱ网站上没有现成的移植实例。因此,有必要进行一次移植以使操作系统成为μC/OS-Ⅱ,这种移植采用的处理器为80196KC,而其编译器为Tasking c 196。
1 μC/OS-Ⅱ的工作原理
μC/OS-Ⅱ是一个源码公开的实时多任务操作系统,其工作流程如图1所示。图中,任务切换的核心是利用出栈指令将各个任务的工作现场再现,并利用子程序返回指令改变PC指针以完成任务的切换。移植的关键是如何构造任务堆栈及任务切换时的出栈顺序。任务区堆栈初始化主要是模拟任务被中断后的堆栈内容。
2 80196KC的工作状态
80196KC是Intel公司的16位单片机,和程序运行密切相关的寄存器有指令计数器PC、堆栈指针sp、程序状态寄存器PSW、中断屏蔽寄存器INTMASK和INTMASK1以及窗口寄存器WSR(以下将程序状态寄存器PSW、中断屏蔽寄存器INTMASK和INTMASK1、窗口寄存器WSR统称为程序状态字)。它们可在执行子程序调用call指令时自动将pc进栈,并在子程序返回调用RET指令时自动将pc出栈。由于80196KC有16位的寻址能力,故这一动作有2个字节进(出)栈,其中push a指令将程序状态字进栈,pop a指令将程序状态字出栈。这一动作共有4个字节进(出)栈。另外push a动作会将PSW中的中断允许位清零,故通常用push a关闭中断,而用pop a恢复中断允许。由于80196KC的时钟节拍是特定的周期性中断,当每个时钟节拍到来时,系统将对任务延时做一次裁决。因此,在这个时钟节拍可采用80196KC中的软件定时器中断。
3 Tasking c编译器的工作细节
带参数的函数调用编译后的主要操作是先将参数进栈,然后执行call指令。在函数入口处将堆栈中的参数倒入寄存器tmp0、tmp2、
tmp4和tmp6以进行操作(以下称临时寄存器)的原因主要是,堆栈一般位于RAM区,而对RAM区操作不如对寄存器操作快。如果该函数有局部变量,局部变量也是分配在堆栈中。Tasking c编译器一般用一寄存器frame01(以下称框架寄存器)对局部变量进行访问,在函数返回时执行ret操作,并对SP指针进行调整,以跳过函数参数在堆栈中的位置。中断调用和函数调用类似,中断本身虽没有参数,但进中断后要对临时寄存器进行保护。因此,应在进中断后执行push a操作,并在中断返回时使临时寄存器出栈(注意出栈顺序),然后再次执行pop a和ret操作。图2所示为堆栈区的一般结构。
4 移植的细节
在OSTaskStkInit()中,任务堆栈区的构造特点是80196KC的堆栈区由高向低增长,最高处是任务的入口参数,接着是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 popframe01;
}
还应注意,在其它中断服务程序中,如果没有定义局部变量,也应加上对框架寄存器的保护。如果有局部变量,编译器会自动对框架寄存器进行保护。在编写OSIntCtxSw()函数时应当注意,由于OS-IntCtxSw()是在OSIntExit()中调用的,且在调用OS-IntCtxSw()之前又有一个关中断的操作。因此,笔者采用push a方式来关闭中断,也就是说,切换到另一高优先级的任务后,会在当前任务中留下在OSIntC-txSw()和OSIntExit()调用的返回地址4个字节的垃圾和pusha关中断时进栈的4个字节垃圾(共8个字节)。因此,为了保证下次切换到该任务的正确性,应将SP指针加8,然后再进行任务切换。为加深对此的理解,可以做一假设:如果80196KC是24位(3个字节)寻址能力,在当前任务中会留下OSIntCtxSw()和OSIntExit()调用的返回地址的6个字节的垃圾,如果关中断直接采用asm di方式,而不牵扯到堆栈操作,此时SP应调整6个字节而不是8个字节。
5 正确性检验
图3是一个点灯程序的主任务流程。其6个灯中的每一个点灯操作都是一个单独任务。第一个灯每两个时钟节拍做一次异或操作。如果LED1每执行2次异或操作向任务2发一信号量2每执行3次异或操作向任务3发一信号量3每执行4次异或操作向任务4发一信号量4,每执行5次异或操作向任务5发一信号量5,每执行6次异或操作向任务6发一信号量6。那么,任务2到任务6在接到相应的信号量时将对自已控制的灯进行一次异或操作。理论分析,LED2到LED6的波形周期分别为LED1的2到6 倍。笔者曾用示波器对6 个灯的波形进行观察,其结果与理论分析相符,同时,在连续运行数天后,没有发现死机和复位,证明移植成功。
引用地址:μC/OS-II在80196KC单片机上的移植
小广播
热门活动
换一批
更多
最新应用文章
更多精选电路图
更多热门文章
更多每日新闻
- Allegro MicroSystems 在 2024 年德国慕尼黑电子展上推出先进的磁性和电感式位置感测解决方案
- 左手车钥匙,右手活体检测雷达,UWB上车势在必行!
- 狂飙十年,国产CIS挤上牌桌
- 神盾短刀电池+雷神EM-i超级电混,吉利新能源甩出了两张“王炸”
- 浅谈功能安全之故障(fault),错误(error),失效(failure)
- 智能汽车2.0周期,这几大核心产业链迎来重大机会!
- 美日研发新型电池,宁德时代面临挑战?中国新能源电池产业如何应对?
- Rambus推出业界首款HBM 4控制器IP:背后有哪些技术细节?
- 村田推出高精度汽车用6轴惯性传感器
- 福特获得预充电报警专利 有助于节约成本和应对紧急情况
更多往期活动
11月16日历史上的今天
厂商技术中心