【STM32F4UCOSII移植】核心芯片使用STM32F407
1、源码
官网下载源码如下:
文章图片
文章图片
用到的主要在UCOS-II中的文件:
文章图片
在工程中创建三个文件夹分别为ports、source、Config
(1)ports下IAR中的所有文件
文章图片
(2)source中的所有文件
文章图片
(3)Config中文件在官方里程中,只需要一个文件
文章图片
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();
}
}
注:文中参考或自写部分均加以说明,其他代码均为官方源码,