您的位置 首页 电路

uC/OSII在C8051F020单片机上的移植

1uC/OS-II的版本和C8051F020单片机的集成开发环境micro;C/OS-II内核使用了V2.52版本。虽然SiliconLab公司免费提供C8051F系列单片机的…

1 uC/OS-II的版别和C8051F020单片机的集成开发环境
µC/OS-II内核运用了V2.52版别。尽管Silicon Lab公司免费供给C8051F系列单片机的集成开发环境,我们运用习气,笔者仍是挑选了µVision2 V2.38A版别,C编译器版别是C51.exe V7.06,汇编器的版别是A51.exe V7.07。适配器运用Silicon Lab公司的EC2,需求阐明的是,要在Keil uVision2 IDE中调试C8051F系列单片机,有必要装置动态链接库。
2 uC/OS-II在C8051F020单片机上的移植
移植作业便是更改OS_CPU.H、OS_CPU_C.C、OS_CPU_A.ASM这几个文件。在阐明这几个文件之前,先阐明两点注意事项。(1)可重入函数。单片机内部仓库空间有限,C51供给一种紧缩栈的办法,当递归调用这个函数时,会导致变量被掩盖,所以在实时运用中,要用关键字reentrant将函数声明成可重入函数,把每次函数调用时的局部变量独自保存起来。但函数中不可以运用BOOL变量,我们在LARGE编译形式下,KEIL默许将一切变量定位到外部RAM的最高处,而MCS-51系列的MCU中只需内部20H-2FH的地址可以位寻址。(2)C51的关键字和uC/OS-II界说变量的对立。“pdata”、“data”在uC/OS-II中用做一些函数的形参,但它一起又是C51的关键字,在编译时导致语法过错,经过把“pdata”改成“ppdata”,“data”改成“ddata”处理了此问题。
2.1 OS_CPU.H文件
这个文件首要是与处理器相关的宏界说和数据类型声明。如前面说到的,不能运用bit型变量,把BOOLEAN型界说成unsigned char型。别的8位MCU数据宽度和仓库宽度都是8位,别离将OS_STK和OS_CPU_SR界说成unsigned char型。uC/OS-II供给了3种处理临界代码的办法,这儿运用第一种,即经过对寄存器EA开关中止。MCS-51系列MCU的仓库是从下向上递加的,界说OS_STK_GROWTH = 0。
2.2 OS_CPU_C.C文件
这个文件首要是完结OSTaskStkInit()。在uC/OS-II中,使命是一个无限循环,使命之间也不会相互调用,可是uC/OS-II总是碑文优先级最高的使命,假定当时有一个更高优先级的使命进入安排妥当状况,为了确保本来低优先级使命的完整性,uC/OS-II为每个使命建立了使命仓库,就相当于函数调用时保存回来地址和参数相同,用来保存当时使命的状况,确保使命切换能和函数调用相同正确。只不过函数调用时函数仓库的操作进程是编译器主动完结的,而使命切换时需求模仿一个和编译器相似的使命仓库的操作进程。实际上,uC/OS-II的移植作业首要便是处理这个问题,OSTaskStkInit()完结使命栈初始化,后边介绍的OS_CPU_A.ASM文件完结3种不同条件下的使命切换操作。
图1列出了运用使命仓库和MCS-51单片机的体系仓库结构,左面是MCS-51单片机的体系仓库,右边是运用使命的仓库。MCS-51单片机体系仓库是满递加栈,界说MCS51Sp为体系仓库指针,界说MCS51SpTop为体系仓库在内部RAM块的开端地址。初始化时把仓库指针指向0x60H地址,即MCS51Sp = MCS51SpTop = 0x60H。需求保存的寄存器共有13个,运用使命入栈操作详细进程如下:(1)、把一切的寄存器压入体系仓库;(2)、核算体系仓库的深度(SP- MCS51SpTop),而且保存到使命仓库的栈顶;(3)把体系仓库一切的内容保存到使命仓库,这儿既包含在(1)中入栈的13个寄存器也包含程序运转时需求保存的参数(斜线填充部分)。运用使命出栈操作详细进程如下:(1)、从使命仓库的栈顶得到要进行出栈的深度;把使命仓库一切内容康复到体系仓库;(2)、把13个寄存器出栈(还剩余程序指针PC);(3)、碑文RETI指令,把体系仓库中的地址康复到程序指针PC。
过错!链接无效。 图1使命仓库和体系仓库
OSTaskStkInit()的函数原型为 OS_STK *OSTaskStkInit(void (*task)(void *pd),void *pdata, OS_STK *ptos, INT16U opt);其间task指向运用使命的开端地址,pdata是运用使命传递的参数指针,ptos是使命仓库的栈顶指针,需求阐明的是,MCS-51单片机的仓库是递加的,所以这个指针应该指向使命仓库的低地址,在OSTaskCreat()中调用这个函数时opt没有意义,将opt设置为0。OSTaskStkInit()中,首要保存新建使命栈的开端地址(2个字节),也便是在图1右半部分的虚线部分,我们使命还没有被调度,MCU的状况字并不具有实际意义。
2.3 OS_CPU_A.ASM文件
这个文件包含4个汇编语言函数。OSStartHighRdy();OSCtxSw();OSIntCtxSw();OSTickISR()。Keil编译器不支撑插入行汇编代码,需求写这4个汇编函数,假如编译器支撑插入行汇编代码,就可以将一切与处理器相关的代码放到OS_CPU_C.C文件中(ARM和DSP的移植便是这样完结的)。
2.3.1 OSStartHighRdy()
OSStart()函数调用OSStartHighRdy(),使安排妥当态使命中优先级最高的使命开端碑文,OSStartHighRdy()移植代码如下:
RSEG ?PR?OSStartHighRdy?OS_CPU_A ; RSEG 挑选现已在SEGMENT界说的段
OSStartHighRdy:
USING 0 ; 挑选作业寄存器组
LCALL _?OSTaskSwHook
MOV R0, #LOW(OSRunning)
MOV @R0,#01 ; OSRunning = TRUE
OSStartHighRdyRpt:
MOV R0,#LOW (OSTCBCur) ; 取TCB指针OSTCBCur。在单片机C语言中,
INC R0 ; 指针占用3个字节,低字节是指针存储类
MOV DPH,@R0 ; 型编码,第二、第三字节别离寄存指针高
INC R0 ; 位、低位地址偏移量。
MOV DPL,@R0
INC DPTR ; 装载OSTCBStkPtr地址到DPTR
MOVX A, @DPTR
MOV R1,A
INC DPTR
MOVX A, @DPTR
MOV R0,A
MOV DPH, R1
MOV DPL, R0
MOVX A, @DPTR ; 出栈第一个字节,即体系仓库深度
MOV R4,A
MOV R0,#OSStkStart
COPY_STK_TO_SYS: ; 把使命仓库的数据康复到体系仓库
INC DPTR
INC R0
MOVX A, @DPTR
MOV @R0, A
DJNZ R4, COPY_STK_TO_SYS
MOV SP, R0 ; 调整体系仓库指针
POPAll
RETI
2.3.2 OSCtxSw()
这个函数完结使命切换。包含3个进程:(1)把体系仓库保存到当时使命仓库;(2)找出优先级最高的使命;(3)把高优先级使命的仓库康复到体系仓库。在写这部分代码时,只需写前两部分,第3部分的内容和OSStartHighRdy()简直彻底相同,跳转到OSStartHighRdyRpt开端的部分就可以了。
2.3.3 OSIntCtxSw()
OSIntExit()经过调用OSIntCtxSw(),在ISR中碑文使命切换功用。我们OSIntCtxSw()是在ISR中被调用的,这时处理器寄存器现已被保存到使命仓库。所以只需一条LJMP 指令跳转到OSCtxSw()函数的进程(2)的进口地址就可以了。
2.3.4 OSTickISR()
时钟节拍中止服务子程序OSTickISR()完结的操作和OSCtxSw()相似,只不过OSTickISR()是由硬件守时器溢出中止触发的,守时器运用了C8051F020单片机的T0,时钟节拍设置为每秒20次,外部的22.1184MHZ晶体经过2分频作为T0基准,只需在退出这个函数之前加上如下2条指令即可。
MOV TH0, #0x2C
MOV TL0, #0x12
3 测验移植代码
创立的2个测验使命及源码如下:
OSTaskCreate(TestTransplantA, (void *)0, & TestTransplantAStk[0],2);
OSTaskCreate(TestTransplantB, (void *)0, & TestTransplantBStk[0],3);
void TestTransplantA(void *ddata) reentrant
{ ddata=ddata;
for(;;)
{ Uart0Send(0xAA);
OSTimeDly(60*OS_TICKS_PER_SEC);
}
}
void TestTransplantB(void *ddata) reentrant
{ ddata=ddata;
for(;;)
{ Uart0Send(0xBB);
OSTimeDly(30*OS_TICKS_PER_SEC);
}
}
多使命调度开端后,经过超级终端接纳的UART0的数据为:AA BB BB AA BB BB AA BB BB AA BB BB AA BB BB AA BB BB AA ……。
高优先级的使命TestTransplantA()能首要被调度运转,阐明OSTaskStkInit()和OSStartHighRdy()函数是正确的。使命TestTransplantA()和使命TestTransplantB()由时钟节拍驱动而周期地被调度,阐明OSCtxSw()、OSIntCtxSw()、OSTickISR()也是正确的。经过以上两点可以以为移植结果是正确的。
4 结束语
在µC/OS-II平台下开发程序,首要要把握内核。经过上述移植进程,可以对使命仓库、使命调度有深刻理解。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/dianlu/263608.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部