STM32F4UCOSII移植

【STM32F4UCOSII移植】核心芯片使用STM32F407
1、源码
官网下载源码如下:
STM32F4UCOSII移植
文章图片
STM32F4UCOSII移植
文章图片

用到的主要在UCOS-II中的文件:
STM32F4UCOSII移植
文章图片

在工程中创建三个文件夹分别为ports、source、Config
(1)ports下IAR中的所有文件
STM32F4UCOSII移植
文章图片

(2)source中的所有文件
STM32F4UCOSII移植
文章图片

(3)Config中文件在官方里程中,只需要一个文件
STM32F4UCOSII移植
文章图片

2、文件修改
(1)修改os_cpu_a.asm
汇编语音,不了解,参考自正点原子

IMPORTOSRunning; External references IMPORTOSPrioCur IMPORTOSPrioHighRdy IMPORTOSTCBCur IMPORTOSTCBHighRdy IMPORTOSIntNesting IMPORTOSIntExit IMPORTOSTaskSwHook EXPORTOSStartHighRdy EXPORTOSCtxSw EXPORTOSIntCtxSw EXPORTOS_CPU_SR_Save; Functions declared in this file EXPORTOS_CPU_SR_Restore EXPORTPendSV_Handler NVIC_INT_CTRLEQU0xE000ED04; 中断控制寄存器 NVIC_SYSPRI2EQU0xE000ED22; 系统优先级寄存器(2) NVIC_PENDSV_PRIEQU0xFFFF; PendSV中断和系统节拍中断 ; (都为最低,0xff). NVIC_PENDSVSETEQU0x10000000; 触发软件中断的值.PRESERVE8 AREA|.text|, CODE, READONLY THUMB OS_CPU_SR_Save MRSR0, PRIMASK; 读取PRIMASK到R0,R0为返回值 CPSIDI; PRIMASK=1,关中断(NMI和硬件FAULT可以响应) BXLR; 返回 OS_CPU_SR_Restore MSRPRIMASK, R0; 读取R0到PRIMASK中,R0为参数 BXLR; 返回 ; * 功能描述: 使用调度器运行第一个任务 OSStartHighRdy LDRR4, =NVIC_SYSPRI2; set the PendSV exception priority LDRR5, =NVIC_PENDSV_PRI STRR5, [R4] MOVR4, #0; set the PSP to 0 for initial context switch call MSRPSP, R4 LDRR4, =OSRunning; OSRunning = TRUE MOVR5, #1 STRBR5, [R4] ; 切换到最高优先级的任务 LDRR4, =NVIC_INT_CTRL; rigger the PendSV exception (causes context switch) LDRR5, =NVIC_PENDSVSET STRR5, [R4] CPSIEI; enable interrupts at processor level OSStartHang BOSStartHang; should never get here ; * 功能描述: 任务级上下文切换 OSCtxSw PUSH{R4, R5} LDRR4, =NVIC_INT_CTRL; 触发PendSV异常 (causes context switch) LDRR5, =NVIC_PENDSVSET STRR5, [R4] POP{R4, R5} BXLR ; * 功能描述: 中断级任务切换 OSIntCtxSw PUSH{R4, R5} LDRR4, =NVIC_INT_CTRL; 触发PendSV异常 (causes context switch) LDRR5, =NVIC_PENDSVSET STRR5, [R4] POP{R4, R5} BXLR NOP ; * 功能描述: OSPendSV is used to cause a context switch. PendSV_Handler CPSIDI; Prevent interruption during context switch MRSR0, PSP; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈 CBZR0, PendSV_Handler_Nosave; Skip register save the first time TSTR14, #0x10 ITEQ VSTMDBEQ R0!, {S16-S31} SUBSR0, R0, #0x20; Save remaining regs r4-11 on process stack STMR0, {R4-R11} LDRR1, =OSTCBCur; OSTCBCur->OSTCBStkPtr = SP; LDRR1, [R1] STRR0, [R1]; R0 is SP of process being switched out PendSV_Handler_Nosave PUSH{R14}; Save LR exc_return value LDRR0, =OSTaskSwHook; OSTaskSwHook(); BLXR0 POP{R14} LDRR0, =OSPrioCur; OSPrioCur = OSPrioHighRdy; LDRR1, =OSPrioHighRdy LDRBR2, [R1] STRBR2, [R0] LDRR0, =OSTCBCur; OSTCBCur= OSTCBHighRdy; LDRR1, =OSTCBHighRdy LDRR2, [R1] STRR2, [R0] LDRR0, [R2]; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; LDMR0, {R4-R11}; Restore r4-11 from new process stack ADDSR0, R0, #0x20 ; Is the task using the FPU context? If so, push high vfp registers. TSTR14, #0x10 ITEQ VLDMIAEQ R0!, {S16-S31} MSRPSP, R0; Load PSP with new process SP ORRLR, LR, #0x04; Ensure exception return uses process stack CPSIEI BXLR; Exception return will restore remaining context NOP end

(2)修改os_cfg.h
#define OS_APP_HOOKS_EN 设置为0
(3)修改os_cpu_c.c
0)这个文件中的函数基本都空函数,其中OSTaskStkInit()函数是最重要的,其他函数如果报错屏蔽掉即可
1)修改OSTaskStkInit()函数,这个函数是堆栈函数,参考自正点原子,中间没有执行部分不知道为什么不可以屏蔽掉(死机)
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) { OS_STK *stk; (void)opt; stk= ptos; #if (__FPU_PRESENT==1)&&(__FPU_USED==1) *(--stk) = (INT32U)0x00000000L; //No Name Register *(--stk) = (INT32U)0x00001000L; //FPSCR *(--stk) = (INT32U)0x00000015L; //s15 *(--stk) = (INT32U)0x00000014L; //s14 *(--stk) = (INT32U)0x00000013L; //s13 *(--stk) = (INT32U)0x00000012L; //s12 *(--stk) = (INT32U)0x00000011L; //s11 *(--stk) = (INT32U)0x00000010L; //s10 *(--stk) = (INT32U)0x00000009L; //s9 *(--stk) = (INT32U)0x00000008L; //s8 *(--stk) = (INT32U)0x00000007L; //s7 *(--stk) = (INT32U)0x00000006L; //s6 *(--stk) = (INT32U)0x00000005L; //s5 *(--stk) = (INT32U)0x00000004L; //s4 *(--stk) = (INT32U)0x00000003L; //s3 *(--stk) = (INT32U)0x00000002L; //s2 *(--stk) = (INT32U)0x00000001L; //s1 *(--stk) = (INT32U)0x00000000L; //s0 #endif *(stk)= (INT32U)0x01000000L; /* xPSR*/ *(--stk)= (INT32U)task; /* Entry Point*/ *(--stk)= (INT32U)OS_TaskReturn; /* R14 (LR) (init value will cause fault if ever used)*/ *(--stk)= (INT32U)0x12121212L; /* R12*/ *(--stk)= (INT32U)0x03030303L; /* R3*/ *(--stk)= (INT32U)0x02020202L; /* R2*/ *(--stk)= (INT32U)0x01010101L; /* R1*/ *(--stk)= (INT32U)p_arg; /* R0 : argument*/#if (__FPU_PRESENT==1)&&(__FPU_USED==1) *(--stk) = (INT32U)0x00000031L; //s31 *(--stk) = (INT32U)0x00000030L; //s30 *(--stk) = (INT32U)0x00000029L; //s29 *(--stk) = (INT32U)0x00000028L; //s28 *(--stk) = (INT32U)0x00000027L; //s27 *(--stk) = (INT32U)0x00000026L; //s26 *(--stk) = (INT32U)0x00000025L; //s25 *(--stk) = (INT32U)0x00000024L; //s24 *(--stk) = (INT32U)0x00000023L; //s23 *(--stk) = (INT32U)0x00000022L; //s22 *(--stk) = (INT32U)0x00000021L; //s21 *(--stk) = (INT32U)0x00000020L; //s20 *(--stk) = (INT32U)0x00000019L; //s19 *(--stk) = (INT32U)0x00000018L; //s18 *(--stk) = (INT32U)0x00000017L; //s17 *(--stk) = (INT32U)0x00000016L; //s16 #endif *(--stk)= (INT32U)0x11111111L; /* R11*/ *(--stk)= (INT32U)0x10101010L; /* R10*/ *(--stk)= (INT32U)0x09090909L; /* R9*/ *(--stk)= (INT32U)0x08080808L; /* R8*/ *(--stk)= (INT32U)0x07070707L; /* R7*/ *(--stk)= (INT32U)0x06060606L; /* R6*/ *(--stk)= (INT32U)0x05050505L; /* R5*/ *(--stk)= (INT32U)0x04040404L; /* R4*/return (stk); }

2)将OS_CPU_SysTickInit()和OS_CPU_SysTickHandler()这两个函数屏蔽掉,改为自写的滴答定时器初始化以及中断处理函数
void SysTick_init(void) { SysTick_Config(SystemCoreClock/1000); //一毫秒执行一次中断 }void SysTick_Handler(void) { OSIntEnter(); //进入中断 OSTimeTick(); //调用ucos的时钟服务程序 OSIntExit(); //触发任务切换软中断 }

(4)os_dbg.c中#define OS_COMPILER_OPT //__root
(6)ucos_ii.h中添加#include “stm32f4xx.h”,这个比较重要,没有也会导致程序死机
3、主函数
#include "stm32f4xx.h" #include "ucos_ii.h" //设置任务优先级 #define START_TASK_PRIO10 //开始任务的优先级设置为最低 //设置任务堆栈大小 #define START_STK_SIZE64 //任务堆栈 OS_STK START_TASK_STK[START_STK_SIZE]; //任务函数 void start_task(void *pdata); int main(void) { OSInit(); OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO ); //创建起始任务 OSStart(); } //开始任务 void start_task(void *pdata) { SysLED_Init(); SysTick_init(); USART_Config(); printf("初始化完成\r\n"); while(1) { OSTimeDly(500); SysLed(); OSTimeDly(500); SysLed(); } }

注:文中参考或自写部分均加以说明,其他代码均为官方源码,

    推荐阅读