位置:51电子网 » 技术资料 » 其它综合

uC/OS-II在C8051F上的移植

发布时间:2008/6/5 0:00:00 访问次数:575

uc/os-ii在c8051f上的移植

1 开发工具和运行环境

  实现μc/os-ii的移植,要求所用的c编译器支持混合编程。keil c51可为众多的8051派生器件编程。我们选用的是keil7.02集成开发环境,仿真板基于c8051f015芯片。

2 移植中所需修改的文件

  和cpu相关的文件主要有三个,分别是汇编文件os_cpu_a.asm、c语言文件 os_cpu_c.c和头文件os_cpu.h。

2.1 os_cpu.h文件

  os_cpu.h文件中定义了数据类型及与硬件相关的基本信息。其中改动部分如下:
typedef unsigned char os_stk; /* 堆栈的宽度为8位 */
os_cpu_ext int8u ie_shadow;
#define os_enter_critical() ie_shadow = ie; ie &= 0x7f /* 关中断 */
#define os_exit_critical() ie = ie_shadow
/* 恢复中断 */
#define os_stk_growth 0
#define os_task_sw() osctxsw()

  在c8051f中,堆栈都是按字节操作的,故数据类型os_stk声明为8位。方向从低地址向高地址方向递增,所以os_stk_growth设置为0。μc/os-ii在进入系统临界代码区之前要关中断,等到退出临界区后再打开,以保护核心数据不被多任务环境下的其它任务或中断破坏。开、关中断可通过设置sfr中的中断屏蔽位实现。在关中断时,先将ie的内容保存在全局变量ie_ shadow中,然后关中断;退出临界区时,还原ie_shadow的值。os_task_sw()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,堆栈中应该按入栈次序设置好各个寄存器。os_task_sw()函数模拟一次中断过程,在中断返回的时候进行任务切换。由于c8051f015没有软中断,故直接定义宏os_task_sw()为函数osctxsw()。

2.2 os_cpu_a.asm文件

  编译器将每个文件作为一个模块,编译模块以主名命名,称为编译模块名,用name 来声明。因此,应在文件头部声明name os_cpu_a。

  函数有程序部分和局部变量部分,它们分别放在独立的段中。在大模式下,段名声明的固定格式为 ?pr?函数名?模块名 segment code。因此需要将osstarthighrdy()、osctxsw()、osintctxsw()和ostickisr()用上面的格式一一声明。如?pr?osstarthighrdy?os_cpu_a segment code,本模块实现的函数需要用public声明,如public osstarthighrdy等。

  c51将所有定义说明的数据标识符转换为大写字符,对函数则根据有无寄存器参数传送和函数是否可重入进行换名,如:void osintenter(void) reentrant函数的名字osintenter换成_?osintenter。这些规则可从编译后的lst文件中看出。程序中声明引用的五个全局变量为ostcbcur、ostcbhighrdy、osrunning、ospriocur、ospriohighrdy,声明格式是extrn idata (ostcbcur)等。调用四个外部子程序ostaskswhook()、osintenter()、osintexit()、ostimetick(),固定格式为:extrn code (_?ostaskswhook)等。

  由于c8051f的堆栈指针只有8位,只能指向内部数据区的256个字节,因此,当前运行的任务的堆栈在idata区,堆栈大小为40h(64字节),堆栈起点由keil决定。通过标号可以获得keil分配的sp起点,代码如下:
?stack segment idata
rseg ?stack
osstack:
ds 40h
osstkstart idata osstack-1
为简化子程序特定义压栈出栈宏。压栈的次序为psw、acc、b、dpl、dph、r0~r7,出栈的次序与入栈相反。
pushall macro
irp reg, <psw,acc, b, dpl, dph, 0, 1, 2, 3, 4, 5, 6, 7>
push reg
endm
popall macro
irp reg, <7, 6, 5, 4, 3, 2, 1, 0, dph, dpl, b, acc, psw>
pop reg
endm
具体函数的修改部分见本刊网络补充版(http://www.dpj.com.cn)。

2.3 os_cpu_c.c文件

  移植μc/os-ii 需要在os_cpu_c.c中定义六个函数,而实际上需要定义的只有ostaskstkinit()一个函数。该函数用来初始化任务的堆栈。初始状态的堆栈只须初始化?c_xbp (仿真堆栈指针)、任务地址及堆栈的长度。由于只有inc dptr指令,故返回栈的最低地址,且最低地址处存放栈的长度,方便用汇编语言实现任务的切换。堆的大小可根据任务的实际情况自行确定,由参数ppdata所指的值确定。
void *ostaskstkinit (void (*task)(void *pd), void *ppdata,
void *ptos, int16u opt) reentrant
{
os_stk *stk;
int8u heapsize;
heapsize=*(int8u *)ppdata;
opt = opt;
stk = (os_stk *)ptos+heapsize+2;
*stk++ = 15;
*stk++ = (int16u)task & 0xff;
*stk++ = (int16u)task >> 8;
stk = (os_stk *)ptos+heapsize+2;
*--stk = (int16u) (ptos+heapsize-1) >> 8;
*--stk = (int16u) (ptos+heapsize-1) & 0xff;
return ((void *)stk);
}

3 可重入函数

  因为51系列堆栈空间的限制, keil编译器没有像大系统那样使用调用堆栈。一般c语言调用过程中

uc/os-ii在c8051f上的移植

1 开发工具和运行环境

  实现μc/os-ii的移植,要求所用的c编译器支持混合编程。keil c51可为众多的8051派生器件编程。我们选用的是keil7.02集成开发环境,仿真板基于c8051f015芯片。

2 移植中所需修改的文件

  和cpu相关的文件主要有三个,分别是汇编文件os_cpu_a.asm、c语言文件 os_cpu_c.c和头文件os_cpu.h。

2.1 os_cpu.h文件

  os_cpu.h文件中定义了数据类型及与硬件相关的基本信息。其中改动部分如下:
typedef unsigned char os_stk; /* 堆栈的宽度为8位 */
os_cpu_ext int8u ie_shadow;
#define os_enter_critical() ie_shadow = ie; ie &= 0x7f /* 关中断 */
#define os_exit_critical() ie = ie_shadow
/* 恢复中断 */
#define os_stk_growth 0
#define os_task_sw() osctxsw()

  在c8051f中,堆栈都是按字节操作的,故数据类型os_stk声明为8位。方向从低地址向高地址方向递增,所以os_stk_growth设置为0。μc/os-ii在进入系统临界代码区之前要关中断,等到退出临界区后再打开,以保护核心数据不被多任务环境下的其它任务或中断破坏。开、关中断可通过设置sfr中的中断屏蔽位实现。在关中断时,先将ie的内容保存在全局变量ie_ shadow中,然后关中断;退出临界区时,还原ie_shadow的值。os_task_sw()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,堆栈中应该按入栈次序设置好各个寄存器。os_task_sw()函数模拟一次中断过程,在中断返回的时候进行任务切换。由于c8051f015没有软中断,故直接定义宏os_task_sw()为函数osctxsw()。

2.2 os_cpu_a.asm文件

  编译器将每个文件作为一个模块,编译模块以主名命名,称为编译模块名,用name 来声明。因此,应在文件头部声明name os_cpu_a。

  函数有程序部分和局部变量部分,它们分别放在独立的段中。在大模式下,段名声明的固定格式为 ?pr?函数名?模块名 segment code。因此需要将osstarthighrdy()、osctxsw()、osintctxsw()和ostickisr()用上面的格式一一声明。如?pr?osstarthighrdy?os_cpu_a segment code,本模块实现的函数需要用public声明,如public osstarthighrdy等。

  c51将所有定义说明的数据标识符转换为大写字符,对函数则根据有无寄存器参数传送和函数是否可重入进行换名,如:void osintenter(void) reentrant函数的名字osintenter换成_?osintenter。这些规则可从编译后的lst文件中看出。程序中声明引用的五个全局变量为ostcbcur、ostcbhighrdy、osrunning、ospriocur、ospriohighrdy,声明格式是extrn idata (ostcbcur)等。调用四个外部子程序ostaskswhook()、osintenter()、osintexit()、ostimetick(),固定格式为:extrn code (_?ostaskswhook)等。

  由于c8051f的堆栈指针只有8位,只能指向内部数据区的256个字节,因此,当前运行的任务的堆栈在idata区,堆栈大小为40h(64字节),堆栈起点由keil决定。通过标号可以获得keil分配的sp起点,代码如下:
?stack segment idata
rseg ?stack
osstack:
ds 40h
osstkstart idata osstack-1
为简化子程序特定义压栈出栈宏。压栈的次序为psw、acc、b、dpl、dph、r0~r7,出栈的次序与入栈相反。
pushall macro
irp reg, <psw,acc, b, dpl, dph, 0, 1, 2, 3, 4, 5, 6, 7>
push reg
endm
popall macro
irp reg, <7, 6, 5, 4, 3, 2, 1, 0, dph, dpl, b, acc, psw>
pop reg
endm
具体函数的修改部分见本刊网络补充版(http://www.dpj.com.cn)。

2.3 os_cpu_c.c文件

  移植μc/os-ii 需要在os_cpu_c.c中定义六个函数,而实际上需要定义的只有ostaskstkinit()一个函数。该函数用来初始化任务的堆栈。初始状态的堆栈只须初始化?c_xbp (仿真堆栈指针)、任务地址及堆栈的长度。由于只有inc dptr指令,故返回栈的最低地址,且最低地址处存放栈的长度,方便用汇编语言实现任务的切换。堆的大小可根据任务的实际情况自行确定,由参数ppdata所指的值确定。
void *ostaskstkinit (void (*task)(void *pd), void *ppdata,
void *ptos, int16u opt) reentrant
{
os_stk *stk;
int8u heapsize;
heapsize=*(int8u *)ppdata;
opt = opt;
stk = (os_stk *)ptos+heapsize+2;
*stk++ = 15;
*stk++ = (int16u)task & 0xff;
*stk++ = (int16u)task >> 8;
stk = (os_stk *)ptos+heapsize+2;
*--stk = (int16u) (ptos+heapsize-1) >> 8;
*--stk = (int16u) (ptos+heapsize-1) & 0xff;
return ((void *)stk);
}

3 可重入函数

  因为51系列堆栈空间的限制, keil编译器没有像大系统那样使用调用堆栈。一般c语言调用过程中

相关IC型号

热门点击

 

推荐技术资料

罗盘误差及补偿
    造成罗盘误差的主要因素有传感器误差、其他磁材料干扰等。... [详细]
版权所有:51dzw.COM
深圳服务热线:13692101218  13751165337
粤ICP备09112631号-6(miitbeian.gov.cn)
公网安备44030402000607
深圳市碧威特网络技术有限公司
付款方式


 复制成功!