在MC68HC908GP32上移植μC/OS-II

嵌入式系统 时间:2016-09-12来源:网络

(2)代码临界区

μC/OS-II在进入系统临界代码区之前要关闭中断,等到退出临界区后再打开,从而保护核心数据不被多任务环境下的其他任务或中断破坏。在GP32中,开关中断可以通过汇编指令CLI和SEI来实现。所以μC/OS-II中的宏OS_ENTER_CRITICAL()定义为指令SEI,OS_EXIT_CRITICAL()定义为指令CLI。

(3)堆栈增长方向

GP32的堆栈是由高地址向低地址方向增长的,所以常量OS_STK_GPOWTH必须设置为1。

(4)OS_TASK_SW()函数的定义

在μC/OS-II中,OS_TASK_SW()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,堆栈中应该按进栈次序设置好各个寄存器的内容。OS_TASK_SW()函数模拟一次中断过程,在中断返回的时候进行任务切换。GP32中可采用软中断指令SWI实现任务切换。中断服务程序的入口点必须指向汇编函数OSCtxSw()。

OS_TASK_SW()的定义:

#define OS_TASK_SW() asm swi

3.OS_CPU08.ASM文件

μC/OS-II的移植需要改写OS_CPU08.ASM中的4个函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()。

(1)OSStartHighRdy()函数

该函数由SStart()函数调用,功能是运行优先级最高的就绪任务。在调用 OSStart()之前,必须先调用OSInit(),并且已经至少创建了一个任务。为了启动任务,OSStartHighRdy()首先找到当前就绪的优先级最高的任务(OSTCBHighRdy中保存有优先级最高任务的任务控制块-TCB的地址),并从任务的任务控制块(OS_TCB)中找到指向堆栈的指针,然后从堆栈中弹出全部寄存器的内容,运行RTE中断返回。由于任务创建时堆栈的结构就是按中断后的堆栈结构初始化的,执行RET指令后就切换到新任务(有关μC/OS-II的任务切换机制,请参考系列讲座的第2讲)。对于OSStartHighRdy的代码,我们采用在C中嵌入汇编的方法编写。需要说明的是,由于GP32中有512字节RAM,所以地址指针必须是16位的;而GP32中累加寄存器A为8位,所以用累加器A传递地址必须进行两次读入、输出操作。

Void OSStartHighRdy(void)

{asm

{

jsr OSTaskSwHook //调用用户定义接口函数

lda OSRunning //设置OSRunning变量,标志进入多任务模式

inca

sta OSRunning

ldx OSTCBHighRdy //取得最高优先级就绪任务TCB地址

stx OSTCBCur //保存到OSTCBCur中

pshx

ldx OSTCBHighRdy:1//保存地址的第二个字节

stx OSTCBCur:1

pulh

lda 0,X //载放就绪任务堆栈指针

psha

ldx 1,X //载入就绪任务堆栈指针第二个字节

pulh

txs

pulh //恢复索引寄存器内容

rti //中断返回,运行新任务

}}

(2)OSCtxSw()函数

OSCtxSw()是一个任务级的任务切换函数(在任务中调用,区别于在中断程序中调用的OSIntCtxSw())。在GP32上实现,可通过执行一条软中断指令SWI来实现任务切换。软中断向量指向OSCtxSw()。在 μC/OS-II中,如果任务调用了某个函数,而该函数的执行结果可能造成系统任务新调度(例如试图唤醒一个优先级更高的任务),则在函数的末尾会调用 OSSched();如果OSSched()将查找当前就绪的优先级最高的任务,若不是当前任务,则判断是否需要进行任务调度,并找到该任务控制块 OS_TCB的地址,将该地址拷贝到变量OSTCBHighRdy中,然后通过宏OS_TASK_SW()执行软中断进行任务切换。在此过程中,变量 OSTCBCur始终包含一个指向当前运行任务OS_TCB的指针。OSCtxSw()的汇编代码如下:

Void OSCtxSw(void)

{asm

{pshh //保存X寄存器

tsx

pshx

pshh

dx OSTCBCur //载入当前任务的TCB指针

pshx

ldx OSTCBCur:1 //载入TCB的第二个字节

pulh

pula

sta 0,x //保存当前堆栈指针

pula

sta 1,x

jsr OSTaskSwHook //调用用户定义的接口函数

lda OSPrioHighRdy //设置OSPrioCur=OSPrioHighRdy

sta OSPrioCur

pshx

ldx OSTCBHighRdy:1

stx OSTCBCur:1

pulh

lda 0,x //载入堆栈指针

psha

ldx,1,x

pulh

txs

pulh //恢复索引寄存器内容

rti //中断返回,切换任务

}}

(4)OSTickISR()函数

在μC/OS-II中,当调用OSStart()启动多任务环境后,时钟中断的使用是非常重要的。在时钟中断程序中负责处理所有与定时相关的工作,如任务的延时、等待操作等等。在时钟中断中将查询处于等待状态的任务,判断是否延时结束,否则将重新进行任务调度。

为GP32编写的函数OSTickISR()的代码如下:

void OSTickISR()void{

asm{

pshh

LDA T1SC

BCLR 7,T1SC //允许中断嵌套

}

OsintEnter(); /*标志进入中断*/

OSTimeTick(); /*调用时钟节拍函数*/

OSlntExit(); /*标志退出中断*/

Asm{

Pulh

Rti

}}

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

1 2 3

关键词:

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版