大部分的μC/OS-II代码是使用ANSI C语言书写的,因此μC/OS-II的可移植性较好。尽管如此,仍然需要使用C和汇编语言写一些处理器相关的代码。μC/OS-II的移植需要满足以下要求:
(1)处理器的C编译器可以产生可重入代码;
(2)可以使用C调用进入和退出Critical Code(临界区代码);
(3)处理器必须支持硬件中断,并且需要一个定时中断源;
(4)处理器需要能够容纳一定数据的硬件堆栈;
(5)处理器需要有能够在CPU寄存器与内存和堆栈交换数据的指令。
移值μC/OS-II的主要工作就是处理器和编译器相关代码以及BSP的编写。
2 μC/OS-II DSP编写
BSP(板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作。
为μC/OS-II编写一个简单的BSP。它首先设置CPU内部寄存器和系统堆栈,并初始化堆栈指针,建立程序的运行和调用环境;然后可以方便地使用C语言设置MCF5272片选地址(CS0~CS7)、GPIO以及SDRAM控制器,初始化串口(UART0)作为默认打印口,并向操作系统提供一些硬件相关例程和函数如dprintf(),以方便调试;在CPU、板级和程序自身初始化完成后,就可以把CPU的控制权交给操作系统了。
MCF5272处理器将系统上电作为2号异常,因此需要在异常矢量表中相应位置填写第一条命令的物理地址,这可以在编译时自动完成。该矢量表必须存放在CS0对应的FLASH中供CPU上电时自动读取。如:
_vectors: //矢量表起始地址
.long 0x0,_start,_fault,_fault,… //初始化1K字节矢量表
……
_start: nop //第一条指令
move.w #0x2700,%sr //屏蔽所有中断
move.1 #_vectors,%d0
move.c %d0,%VBR //#vectors->VBR
move.1 #0x10000001,%d0
move.c %d0,%MBAR //SIM单元基地址0x10000000
move.1 #0x20000001,%a0 //SRAM起始地址0x20000000
move.c %a0,%RAMBAR0 //初始化内部SRAM
move.1 #0x20001001,%a7 //设置堆栈指针
……
jsr cpu_init //调用cpu_init初始化SIM单元
jsr ucos_start //启动μC/OS-II
……
其中,cpu_init函数用于初始化CPU内部SIM单元、SDRAM控制器、UART串口。值得注意的是SDRAM初始化,不同生产商的SDRAM的初始化时序有一定差异。
BSP在完成片级和板级初始化后,还负责初始化程序自身,如将.data段的内容从只读的ROM复制到SDRAM中,建立运行时环境。以下是建立程序数据段的代码:
memcpy(%26;amp;_sdata,%26;amp;_etext,(%26;amp;_edata-%26;amp;_sdata)); //拷贝.data段
memset(%26;amp;_sbss,0,(%26;amp;_ebss - %26;amp;_sbss)); //将.bss段清零
还需要为μC/OS-II编写4个简单的汇编函数。在每个硬件时钟到来后,μC/OS-II会在中断服务例程中调用OSIntCtxSw()进行任务调度;另外,当某个任务因等待资源而被挂起时,没有必要等到自己的时间片全都用完,可以自己主动放弃CPU,这可以通过调用一个任务级的任务调度函数OSCtxSw()来实现。其中相对复杂的是OSIntCtxSw()。由于OSTickISR()调用了OSIntExit(),OSIntExit()又再次调用了OSIntCtxSw(),如果进行任务切换,那么两次调用都不会返回,而不同的C编译器、不同的编译选项处理C调用时对堆栈的使用也不尽相同。因此OSIntCtxSw()是编译器相关的。GCC在使用2~4级优化时,在主调函数中会是一个jsr跳转指令,而被调函数以linkw %fp,#[!--empirenews.page--]实时操作系统μC/OS-II在MCF5272上的移植
大部分的μC/OS-II代码是使用ANSI C语言书写的,因此μC/OS-II的可移植性较好。尽管如此,仍然需要使用C和汇编语言写一些处理器相关的代码。μC/OS-II的移植需要满足以下要求:
(1)处理器的C编译器可以产生可重入代码;
(2)可以使用C调用进入和退出Critical Code(临界区代码);
(3)处理器必须支持硬件中断,并且需要一个定时中断源;
(4)处理器需要能够容纳一定数据的硬件堆栈;
(5)处理器需要有能够在CPU寄存器与内存和堆栈交换数据的指令。
移值μC/OS-II的主要工作就是处理器和编译器相关代码以及BSP的编写。
2 μC/OS-II DSP编写
BSP(板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作。
为μC/OS-II编写一个简单的BSP。它首先设置CPU内部寄存器和系统堆栈,并初始化堆栈指针,建立程序的运行和调用环境;然后可以方便地使用C语言设置MCF5272片选地址(CS0~CS7)、GPIO以及SDRAM控制器,初始化串口(UART0)作为默认打印口,并向操作系统提供一些硬件相关例程和函数如dprintf(),以方便调试;在CPU、板级和程序自身初始化完成后,就可以把CPU的控制权交给操作系统了。
MCF5272处理器将系统上电作为2号异常,因此需要在异常矢量表中相应位置填写第一条命令的物理地址,这可以在编译时自动完成。该矢量表必须存放在CS0对应的FLASH中供CPU上电时自动读取。如:
_vectors: //矢量表起始地址
.long 0x0,_start,_fault,_fault,… //初始化1K字节矢量表
……
_start: nop //第一条指令
move.w #0x2700,%sr //屏蔽所有中断
move.1 #_vectors,%d0
move.c %d0,%VBR //#vectors->VBR
move.1 #0x10000001,%d0
move.c %d0,%MBAR //SIM单元基地址0x10000000
move.1 #0x20000001,%a0 //SRAM起始地址0x20000000
move.c %a0,%RAMBAR0 //初始化内部SRAM
move.1 #0x20001001,%a7 //设置堆栈指针
……
jsr cpu_init //调用cpu_init初始化SIM单元
jsr ucos_start //启动μC/OS-II
……
其中,cpu_init函数用于初始化CPU内部SIM单元、SDRAM控制器、UART串口。值得注意的是SDRAM初始化,不同生产商的SDRAM的初始化时序有一定差异。
BSP在完成片级和板级初始化后,还负责初始化程序自身,如将.data段的内容从只读的ROM复制到SDRAM中,建立运行时环境。以下是建立程序数据段的代码:
memcpy(%26;amp;_sdata,%26;amp;_etext,(%26;amp;_edata-%26;amp;_sdata)); //拷贝.data段
memset(%26;amp;_sbss,0,(%26;amp;_ebss - %26;amp;_sbss)); //将.bss段清零
还需要为μC/OS-II编写4个简单的汇编函数。在每个硬件时钟到来后,μC/OS-II会在中断服务例程中调用OSIntCtxSw()进行任务调度;另外,当某个任务因等待资源而被挂起时,没有必要等到自己的时间片全都用完,可以自己主动放弃CPU,这可以通过调用一个任务级的任务调度函数OSCtxSw()来实现。其中相对复杂的是OSIntCtxSw()。由于OSTickISR()调用了OSIntExit(),OSIntExit()又再次调用了OSIntCtxSw(),如果进行任务切换,那么两次调用都不会返回,而不同的C编译器、不同的编译选项处理C调用时对堆栈的使用也不尽相同。因此OSIntCtxSw()是编译器相关的。GCC在使用2~4级优化时,在主调函数中会是一个jsr跳转指令,而被调函数以linkw %fp,#[!--empirenews.page--]如果这篇内容对您有帮助,欢迎点赞支持!