微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-Ⅱ在MC9S12A64上的移植及应用

μC/OS-Ⅱ在MC9S12A64上的移植及应用

时间:05-17 来源:互联网 点击:

器相关的数据类型,堆栈的宽度和增长方式以及开关中断的宏定义。由于我在移植时使用的是C交叉编译器,可以使OS_CPU_A.ASM和OS_CPUC.C两个文件合成为一个 OS_CPUC.C文件。

2.2 OS_CPU_C.C中主要函数的创建

2.2.1 时钟节拍中断服务子程序

void OSTickISR(void)

{

/* asm{

ldaa ppage //将每个任务的存储页面寄存器推入堆栈

psha

}*/

OSIntEnter(); //通知μC/OS-II进入时钟节拍中断服务子程序

OS_SAVE_SP();

CRGFLG =0xEF; //清中断标志

OSTimeTick(); //给每个用户任务控制块OS_TCB中的时间延时项OSTCBDly减1

OSIntExit(); //通知μC/OS-II时钟节拍服务子程序结束。

/*asm{

pula

staa ppage //恢复页面寄存器

nop

rti //中断返回

}*/

}

当时钟节拍中断发生时,CPU12会自动把CPU寄存器推入堆栈,但并不包括存储页面寄存器PPAGE,如果单片机系统的寻址范围超过64KB,需要通过给PPAGE赋值来区分不同的16KB地址,则需要把PPAGE也推入堆栈。OSTimtick()当某任务的任务控制块中的时间延时项 OSTCBDly减到了零,这个任务就进入了就绪态。OSIntExit()会调用中断级的任务切换函数OSIntCtxSw()做任务切换,而不再执行后面的指令。如果没有更高优先级的任务进入就绪态,则CPU会返回中断前状态。

2.2.2 任务级任务切换

OSCtxSW()实际上就是软中断服务子程序,软中断服务子程序向量地址必须指向OSCtxSW(),在连接文件中设置。如果当前任务调用μC/OS-Ⅱ提供的系统服务,并使得更高优先级任务处于就绪状态,μC/OS-Ⅱ就会借助上面提到的向量地址找到OSCtxSw()。

void OSCtxSw(void)

{

asm{

ldaa ppage //将任务的存储页面寄存器推入堆栈

psha

ldx OSTCBCur // 保存被挂起任务的堆栈指针到任务控制块

sts 0,x

}

OSTaskSwHook(); // 如果有时间要求苛刻的任务,可以通过用户接口函数调用

OSTCBCur = OSTCBHighRdy; // 将优先级最高的就绪态任务的任务控制块指针复制给当前运行的任务控制块中

OSPrioCur = OSPrioHighRdy;

asm{

ldx OSTCBCur // 找出新任务的堆栈指针

lds 0,x // 装入CPU的SP寄存器中

pula

staa ppage //恢复页面寄存器

nop

rti

}

}

2.3 信号量的建立与使用

(1)首先到μC/OS-II配置文件OS_CFG.C中将OS_SEM_EN设置为1这样μC/OS-II才能支持信号量。接着要调用OSSemCreate()函数建立该信号量,如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1。

(2)等待信号量OSSemPend()函数,它首先检查指针pevent所指的任务控制块是否是由OSSemCreate()。如果信号量当前是可用的,将信号量的计数值减1,然后函数将“无错”错误代码返回给它的调用函数。如果信号量的计数值为0,则调用OSSemPend()函数的任务要进入睡眠状态,等待另一个任务发出该信号量。OSSemPend()允许用户定义一个最长等待时间作为它的参数,这样可以避免该任务无休止地等待下去。如果该参数值为0,则该任务将一直等待下去。

(3)发送信号量OSSemPost()函数。它也首先检查参数指针pevent指向的任务控制块是否是OSSemCreate()函数建立的,接着检查是否有任务在等待该信号量。如果有任务正在等待该信号量,就把其中的最高优先级任务从等待任务列表中删除并使它进入就绪状态。如果这时没有任务在等待该信号量,该信号量的计数值就简单地加1。

Sem=OSSemCreate(1); //创建一个信号量

OSSemPend(Sem,0,err);// 等待信号量

不可重入型函数…

OSSemPost(Sem); //释放信号量

3 基于μC/OS-II操作系统的项目创建

源程序移植完,用户就可以试着制作自己的项目。编写任务代码与以前在前后台系统中基本相同,不同的是要把每个任务独立编写成一个文件,最后由主程序统一调度。我们可以先分别用三个文件编写三个小任务,每个任务都要设置成死循环。为了方便调度,任务的起始地址应被强制定位在固定地址上,我就规定它们起始地址分别为0x8000,0x9000和0xA000,如果任务都比较复杂,可以将每个任务的程序都定位在0x8000-0xBFFF地址空间,但分配的页面不同。其余的程序都要下到0x4000开始的地址中,这些工作都是在程序下载时解决的。所以我下载的Targets选择的是Flash Application它可以把程序下到0x4000开始的地址中,交叉编译软件Code Warrior给出的连接文件_MC9S12A64_FLAT.prm是程序最终链接与定位用的,他给出了程序的装载地址,用户可以根据使用单片机的内存分配情况和应用要求来修改这个文件。在定位时我先定义了三个地址块,

PAGE_3C8000 = READ_ONLY 0x3C8000 TO 0x3C8FFF;

PAGE_3C9000 = READ_ONLY 0x3C9000 TO 0x3C9FFF;

PA

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top