微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于MC68HC908GP32的μC/OS-II移植

基于MC68HC908GP32的μC/OS-II移植

时间:01-04 来源:互联网 点击:

和μC/OS-II中的其他中断服务程序一样,OSTickISR()首先在被中断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。μC/OS-II要求在中断服务程序开头调用OSIntEnter(),其作用是将记录中断嵌套层数的全局变量OSIntNesting加1。如果不调用OSIntEnter(),直接将OSIntNesting加1也是允许的。随后,OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务。在OSTickISR()的最后调用OSIntExit(),如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,OSIntExit()将进行任务调度。如果当有中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态,OSIntExit()将返回调用者OSTickISR(),最后OSTickISR()返回被中断的任务。

4.OS_CPU08.C文件

μC/OS-II的移植需要用户在OS_CPU08.C中定义6个函数:

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskStatHook()

OSTimeTickHook()

OSTaskStkInit()函数由任务创建函数OSTaskCreate()或OSTaskCreateExt()调用,用来初始化任务的堆栈。初始状态的堆栈模拟发生一次中断后的堆栈结构,按照中断后的进栈次序预留各个寄存器存储空间;而中断返回地址指向任务代码的起始地址。当调用OSTaskCreate()或OSTaskCreateExt()创建一个新任务时,需要传递的参数是:任务代码的起始地址、参数指针(pdata)、任务堆栈顶端的地址、任务的优先级。堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()OSTaskCreateExt()将指针保存在任务的OS_TCB中。

Void*OSTaskStklint(void(*task)(void*pd),void*pdata,void*ptos,INT16U opt)

{

INT16U *stk;

stk=(INT16U*)ptos; /*保存堆栈指针*/

*--stk=(INT16U)(task); /保存程序计数器内容*/

*--stk=(INT16U)(0x00); /初始化X和A寄存器内容*/

--stk=(INT16U)(0x00); /*初始化CCR和H寄存器*/

return((void*)stk);

}

其余的几个函数:OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook和OSTimeTickHook()均由用户自定义。

四、制作用户自己的项目

在为内核编写了上述与硬件相关的代码以后,用户就可以为自己的项目编写实际的代码了。在本例中,用户任务共有两个。任务1在初始化时钟中断以后,就进入了一人死循环。在这个循环里,任务1一方面以1s(秒)为周期改变并行I/O口PORTA第0个引脚的输出电压,另一方面每隔4s便向任务2发送1个信号。而任务2则始终等待任务1发来的信号,一旦收到信号,便改变并行I/O口PORTA第1个引脚的输出电压。具体的代码如下:

/*****************************************

* EXE2.C

*******************************************/

#includehidef.h>

#include includes.h

Byte PORTA @0x0000; /*并口A地址$0000*/

Byte DDRA @0x0004; /*并口A方向寄存器地址$0004*/

Byte T1SC @0x0020; /*定时器控制寄存器地址$0020*/

Byte T1MODH@0x0023; /*定时器模式寄存器地址$0023*/

OS_EVENT *Semaphore;

#define TASK_STK_SIZE 64 /*任务堆栈大小64字节*/

INT8U Task1Stk[TASK_STK_SIZE]; /*定义任务1堆栈*/

INT8U Task2Stk[TASK_STK_SIZE]; /*定义任务2堆栈*/

Void Hardwareinit(void);

Void Task1(void*pdata)

{int count=0;

/*int count=0;

/*初始化定时器*/

asm{

LDA #0x50

STA T1SC

LDHX #0x0333 //设定定时器间隔100ms

STHX T1MODH

CLI

}

for(;;){

PORTA=0xFE;

OSTimeDly(5); /*延时0.5s*/

PORTA|=0x01;

/*延时0.5s*/

DSTimeDly(5);

Count++;

If(count= =4){

OSSemPost(Semaphore);

Count=0;

}

}}

void Task2(void *pdata)

{

Byte err;

For(;;){

OSSemPend(Semaphore,0,err);

PORTA=0xFD:

OSSemPend(Semaphore,0,err);

PORTA|=0x02;

}

}

void main(void){

Hardwarelnit(); /*完成硬件的初始化工作*/

Oslint(); /*初始化多任务环境*/

Semaphore=OSSemCreate(0);

OSTaskCreate(Task1,(void*)0,(void*)Task1Stk

[TASK_STK_SIZE],10);

OSTaskCreate(Task2,void*)0,(void*)Task2Stk

[TASK_STK_SIZE],9);

OSStart();

}

在主程序main()中,用户必须先调用OSInit(),然后创建各个任务和信号量等,最后调用OSStart(),以启动内核运行,开始正常的任务调度。

本例中尽量减小了对RAM的需求:假如中断嵌套层数不超过三层,所需事件只有一个,即只需要

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

网站地图

Top