STM32F4UCOSII移植

时间:2024-04-10 21:06:40

核心芯片使用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
汇编语音,不了解,参考自正点原子

		IMPORT  OSRunning               ; External references
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy
        IMPORT  OSTCBCur
        IMPORT  OSTCBHighRdy
        IMPORT  OSIntNesting
        IMPORT  OSIntExit
        IMPORT  OSTaskSwHook   
        EXPORT  OSStartHighRdy               
        EXPORT  OSCtxSw
        EXPORT  OSIntCtxSw
		EXPORT  OS_CPU_SR_Save                                      ; Functions declared in this file
    	EXPORT  OS_CPU_SR_Restore       
        EXPORT  PendSV_Handler
NVIC_INT_CTRL   	EQU     0xE000ED04  ; 中断控制寄存器
NVIC_SYSPRI2    	EQU     0xE000ED22  ; 系统优先级寄存器(2)
NVIC_PENDSV_PRI 	EQU         0xFFFF  ; PendSV中断和系统节拍中断
                                        ; (都为最低,0xff).
NVIC_PENDSVSET  	EQU     0x10000000  ; 触发软件中断的值.

		PRESERVE8 	
		AREA    |.text|, CODE, READONLY
        THUMB 
OS_CPU_SR_Save
    MRS     R0, PRIMASK  	;读取PRIMASK到R0,R0为返回值 
    CPSID   I				;PRIMASK=1,关中断(NMI和硬件FAULT可以响应)
    BX      LR			    ;返回
OS_CPU_SR_Restore
    MSR     PRIMASK, R0	   	;读取R0到PRIMASK中,R0为参数
    BX      LR				;返回
;* 功能描述: 使用调度器运行第一个任务
OSStartHighRdy
        LDR     R4, =NVIC_SYSPRI2      ; set the PendSV exception priority
        LDR     R5, =NVIC_PENDSV_PRI
        STR     R5, [R4]
        MOV     R4, #0                 ; set the PSP to 0 for initial context switch call
        MSR     PSP, R4
        LDR     R4, =OSRunning         ; OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]
                                       ;切换到最高优先级的任务
        LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
        CPSIE   I                      ;enable interrupts at processor level
OSStartHang
        B       OSStartHang            ;should never get here
  ;* 功能描述: 任务级上下文切换     
OSCtxSw
		PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL  	;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
		POP     {R4, R5}
        BX      LR
;* 功能描述: 中断级任务切换
OSIntCtxSw
		PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL      ;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
		POP     {R4, R5}
        BX      LR
        NOP
;* 功能描述: OSPendSV is used to cause a context switch.
PendSV_Handler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP              ; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈
    CBZ     R0, PendSV_Handler_Nosave		                    ; Skip register save the first time
	TST 	R14, #0x10
	IT 		EQ
	VSTMDBEQ R0!, {S16-S31} 
    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}
    LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out
PendSV_Handler_Nosave
    PUSH    {R14}                                               ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
    BLX     R0
    POP     {R14} 
    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
	;Is the task using the FPU context? If so, push high vfp registers.
	TST 	R14, #0x10
	IT 		EQ
	VLDMIAEQ R0!, {S16-S31} 
	MSR     PSP, R0                                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                                  ; 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_PRIO      			10 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE  				64
//任务堆栈	
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();
	}
} 

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