基于Cortex-M0的UCOS移植
来源:互联网 发布:php函数strip tags 编辑:程序博客网 时间:2024/05/16 07:20
上个星期突然想做一下ucos在cortex-m0平台上的移植,所以就看cortex-m0的内核架构和指令集,接着就开始着手移植了。先说明一下,我的开发板是新唐(Nuvoton)的NuTiny-EVB M051,芯片是M0516LAN。
可以分两步走。第一步,移植ucos的底层代码。第二步,建立新任务。
第一步:移植ucos就是修改这么几个文件:os_cpu_c.c , os_cpu.h , os_cpu_a.asm
其中,os_cpu.h主要是定义数据类型的定义,和有关处理器的一些设置,如栈的生长方向,进入临界代码段的方式,数据存储的大小端设置等等。
1. os_cpu.h:
1.1 定义好数据类型。这个简单,所以不用怎么说。
1.2 定义进行临界代码段的方式,我定义为方式3。即进入时保存PSR,然后关中断,出来是恢复PSR的值。
对应的函数为:OS_CPU_SR OS_CPU_SR_Save(void), void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)
1.3 定义栈的生长方向。我定义为从高向下生长的方向。
1.4 函数的声明。这里有5个函数需要声明。分别是:
void OSCtxSw(void)
void OSIntCtxSw(void)
void OSStartHighRdy(void)
OS_CPU_SR OS_CPU_SR_Save(void)
void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)
由于OSIntCtxSw和OSCtxSw代码可以一致,所以只定义OSCtxSw。
1.5 具体代码如下:
#ifndef OS_CPU_H#define OS_CPU_H#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT#else#define OS_CPU_EXT extern#endif#ifndef OS_CPU_EXCEPT_STK_SIZE#define OS_CPU_EXCEPT_STK_SIZE 1 /* Default exception stack size is 128 OS_STK entries */#endiftypedef unsigned char BOOLEAN;typedef unsigned char INT8U; /* Unsigned 8 bit quantity */typedef signed char INT8S; /* Signed 8 bit quantity */typedef unsigned short INT16U; /* Unsigned 16 bit quantity */typedef signed short INT16S; /* Signed 16 bit quantity */typedef unsigned int INT32U; /* Unsigned 32 bit quantity */typedef signed int INT32S; /* Signed 32 bit quantity */typedef float FP32; /* Single precision floating point */typedef double FP64; /* Double precision floating point */typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */#define OS_CRITICAL_METHOD 3#if OS_CRITICAL_METHOD == 3#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}#endif#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */#define OS_TASK_SW() OSCtxSw()#if OS_CRITICAL_METHOD == 3 OS_CPU_SR OS_CPU_SR_Save (void);void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr);#endifvoid OSCtxSw (void); void OSStartHighRdy (void);
#define OSIntCtxSw() OSCtxSw();#endif
2. os_cpu_c.c
2.1 定义函数OSTaskStkInit(),对于其它的函数可以不用理,因为如果你不需要用到钩子函数的话,是不用实现的。
OSTaskStkInit()主要初始化各个任务的栈。
2.2 由于cortex-m0的架构决定,当产生异常(包括中断)时,进栈的顺序如下:(这是Full descending的模式)
XXX<---SP before exception
xPSR
PC
LR
R12
R3
R2
R1
R0 <--SP after before exception
2.3 代码如下:
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt){ OS_STK *stk; (void)opt; // 'opt' is not used, prevent warning stk = ptos; // Load stack pointer /* Registers stacked as if auto-saved on exception */ *(--stk) = (INT32U)0x01000000L; // xPSR *(--stk) = (INT32U)task; // Entry Point (PC) *(--stk) = (INT32U)0xefefefefL; // LR *(--stk) = (INT32U)0x12121212L; // R12 *(--stk) = (INT32U)0x03030303L; // R3 *(--stk) = (INT32U)0x02020202L; // R2 *(--stk) = (INT32U)0x01010101L; // R1 *(--stk) = (INT32U)p_arg; // R0 : argument /* Remaining registers saved on process stack */ *(--stk) = (INT32U)0x07070707L; //R7 *(--stk) = (INT32U)0x06060606L; // R6 *(--stk) = (INT32U)0x05050505L; // R5 *(--stk) = (INT32U)0x04040404L; // R4 *(--stk) = (INT32U)0x11111111L; // R11 *(--stk) = (INT32U)0x10101010L; // R10 *(--stk) = (INT32U)0x09090909L; // R9 *(--stk) = (INT32U)0x08080808L; // R8 return (stk);}
3. os_cpu_a.asm
这个文件是对头文件 os_cpu.h所定义的函数进行实现。都是汇编代码,不过不是很难懂。
;2011-05-23 xiaoben
EXTERN OSRunning
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
EXPORTOS_CPU_SR_Save
EXPORTOS_CPU_SR_Restore
EXPORTOSStartHighRdy
EXPORTOSCtxSw
EXPORTOSIntCtxSw
AREA os_cpu_asm, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
OS_CPU_SR_Save
MRSR0, PRIMASK
CPSIDI
BXLR
OS_CPU_SR_Restore
MSRPRIMASK, R0
BXLR
OSStartHighRdy
LDR R0, __OSTaskSwHook ; Call OSTaskSwHook()
BLX R0
LDR R0, __OSRunning ; OSRunning=1
MOVS R1, #0x01
STRB R1, [R0]
LDR R0, __OSTCBHighRdy ; SP = OSTCBHighRdy->OSTCBStkPtr
LDR R1, [R0]
LDR R2, [R1]
MSR MSP, R2
; Restore registers from new task stack
POP {R0-R7} ; Restore R4-R7, R8-R11
MOV R11, R3
MOV R10, R2
MOV R9, R1
MOV R8, R0
ADD SP, #0x10 ; Restore PSR, PC, LR, R12
POP {R0-R3}
MOV R12, R0
MOV LR,R1
PUSH {R2} ; Push PC into stack
MSR PSR, R3
SUB SP, #0x1C ; Restore R0-R3
POP {R0-R3}
ADD SP, #0x0C
CPSIE I ; Enable interrupts. NOTE: must not omit!
POP {PC} ; Jump to the task and execute, not return.
OSCtxSw
CPSIDI
; Save registers into current task stack
SUBSP, #0x20 ; Save R4-R7
PUSH{R4-R7}
ADDSP, #0x30 ; Save PSR, PC, LR, R12, R0-R3
MRS R7, PSR
MOV R6, LR ; NOTE!
MOV R5, LR
MOV R4, R12
PUSH{R0-R7}
SUBSP, #0x10 ; Save R8-R11
MOV R3, R11
MOV R2, R10
MOV R1, R9
MOV R0, R8
PUSH{R0-R3}
; Save SP in current stask stack
MRSR0, MSP ; OSTCBCur->OSTCBStkPtr = SP
LDRR1, __OSTCBCur
LDRR2, [R1]
STRR0, [R2]
LDRR0, __OSTaskSwHook ; Call OSTaskSwHook()
BLXR0
LDRR0, __OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDRR1, __OSPrioHighRdy
LDRBR2, [R1]
STRBR2, [R0]
LDR R0, __OSTCBCur ; OSTCBCur = OSTCBHighRdy
LDRR1, __OSTCBHighRdy
LDRR2, [R1]
STRR2, [R0]
LDR R0, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr
MSRMSP, R0
; Restore registers from new task (with high priority) stack
POP{R0-R7} ; Restore R4-R7, R8-R11
MOV R11, R3
MOV R10, R2
MOV R9, R1
MOV R8, R0
ADD SP, #0X10 ; Restore PSR, PC, LR, R12
POP{R0-R3}
MSR PSR, R3
PUSH{R2}
MOV LR, R1
MOV R12, R0
SUB SP, #0X1C ; Restore R0-R3
POP{R0-R3}
ADDSP, #0X0C
CPSIEI ; Enable interrupts! NOTE: must not omit!
POP{PC} ; Jump to task and execute, not return
NOP
__OSRunning
DCD OSRunning
__OSTaskSwHook
DCD OSTaskSwHook
__OSIntExit
DCD OSIntExit
__OSIntNesting
DCD OSIntNesting
__OSPrioCur
DCD OSPrioCur
__OSPrioHighRdy
DCD OSPrioHighRdy
__OSTCBCur
DCD OSTCBCur
__OSTCBHighRdy
DCD OSTCBHighRdy
END
第二步: 到了这里,整个ucos内核就算移植好了。接下来就要建立任务了。对于任务的建立,与头文件 os_cfg.h有关。我们要在os_cfg.h设置一下有关任务的东西。
1. os_cfg.h里面有很多开关量,对于任务里用不到的东西,比如说信号量、定时器之类的,我们可以把它关掉,以减少系统的内存占有率。对于最低优先级OS_LOWEST_PRIO和最大任务数OS_MAX_TASKS要注意一下。还有OS_TICKS_PER_SEC,关于系统的节拍,也要设置一下,一般100到200之间就可以了。
2. 对于任务时钟的节拍,采用cortex-m0的SYSTick来作为节拍源,所以还要加上SysTick的异常处理函数!!!!我在main函数里面添加。
3. main函数里面任务的建立。我们先建立一个闪烁的LED任务。代码如下:
#include <stdio.h>
#include "M051Series.h"
#include "Driver/DrvGPIO.h"
#include "Driver/DrvSYS.h"
#include "ucos_ii.h"
/* LED 任务相关 */
#define LED_STK_SIZE64
#define TASK_LED_PRIO 10 //不要大于OS_LOWEST_PRIO
OS_STK TaskLEDStk[LED_STK_SIZE]; //任务栈
void task_led(void *pdata);
/* 与开发板相关的函数定义 */
void init_target(void);
void init_sys_clock(void);
void init_led(void);
void led_on(void);
void led_off(void);
/* SysTick Exception ISR */
void SysTick_Handler(void)
{
OSIntEnter();
OSTimeTick();
OSIntExit();
}
/* main */
int main()
{
__disable_irq();
init_target();
OSInit();
OSTaskCreate( task_led, (void*)0, TaskLEDStk[LED_STK_SIZE-1], TASK_LED_PRIO );
OSStart();
return 0;
}
void task_led(void *pdata)
{
(void)pdata;
while(1)
{
led_on();
OSTimeDlyHMSM(0, 0, 1, 0);
led_off();
OSTimeDlyHMSMj(0, 0, 1, 0);
}
}
void init_target(void)
{
init_sys_clock();
init_led();
/* Note: Important */
SysTick_Config(DrvSYS_GetHCLKFreq()/OS_TICKS_PER_SEC-1); //Init system tick
}
void init_sys_colock(void)
{
UNLOCKREG();// Unlock the protected registersDrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);// Enable the 12MHz oscillator oscillationwhile (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);// Waiting for 12M Xtal stable
DrvSYS_SelectHCLKSource(0);LOCKREG();// Lock the protected registersDrvSYS_SetClockDivider(E_SYS_HCLK_DIV, 0); // HCLK clock frequency = HCLK clock source / (HCLK_N + 1)
}
void init_led(void)
{
DrvGPIO_Open(E_PORT3, E_PIN6, E_IO_OUTPUT);DrvGPIO_SetBit(E_PORT3, E_PIN6);//led 接P3.6引脚
}
void led_on(void)
{
DrvGPIO_ClrBit(E_PORT3, E_PIN6);
}
void led_off(void)
{
DrvGPIO_ClrBit(E_PORT3, E_PIN6);
}
到此,整个UCOS在cortex-m0就移植成功并且可以运行任务啦。。。从晚上跑到天亮,都非常稳定。
第二天,我又结合之前做过的TXT阅读器,在UCOS上也做了一个TXT电子书阅读器,也挺流畅,也很稳定。感觉很不错!
- 基于Cortex-M0的UCOS移植
- 基于Cortex M0+的STM32L0系列简介
- UCOS 在cortex-m3上的移植
- 基于Cortex M0+的STM32L053xx学习资料介绍
- 在带FPU的Cortex-M4F上移植ucos-III
- cortex M0
- ARM Cortex-M3,Cortex-M0,Cortex-A8的主要区别
- ARM Cortex-M3,Cortex-M0,Cortex-A8的主要区别
- 基于S3C44B0(ARM7TDI)的uCOS-II移植
- uCos-II操作系统在基于Cortex-M3处理器上简要移植步骤
- 基于ARM Cortex-M0+内核的bootloader程序升级原理及代码解析
- 移植uCOS-II到Cortex-M3平台
- 移植uCOS-II到Cortex-M3平台
- cortex M0与msp430的比较
- Cortex-M0(+)内核的处理器架构简介
- QM UML状态机建模实例之移植 cortex-m0
- 【Cortex-M0】3 ARM Cortex-M0
- 基于Kinetis的KL系列之Cortex-M0的WAV音频播放器——系统设计(1)
- JavaScript特性集合
- 让drawText绘出中文
- 两个指针相减
- swf
- java中堆和栈的比较以及理解
- 基于Cortex-M0的UCOS移植
- 位图法;海量数据处理之位图技巧;位图技巧;海量数据;编程珠玑第二章问题A;40亿整数;腾讯面试题
- Centos5.5上LNMP(spawn-fcgi)平台搭建
- test
- 触发器学习
- DC
- Centos5.5上vsftpd安装使用
- Ajax基于iframe文件上传
- huffman编码和译码实现