转载请注明原文地址:http://blog.csdn.net/oyhb_1992/article/details/72654582
Ucosii的移植到STM32其实非常简单,但有些时候就是会出现一些莫名其妙的错误!
Ucosii的移植网上都说是修改os_cpu.hos_cpu_c.cos_cpu_a.asm三个文件,其实这样说是不全的!还需要修改startup_stm32f10x_hd.s启动文件一小部分代码和自己实现SysTick_Handler(void)时钟滴答中断函数。
os_cpu.h os_cpu_c.cos_cpu_a.asm这三部分很简单,网上到处都是直接复制粘贴
os_cpu.h
/************************(C) COPYLEFT 2010 Leafgrass *************************
* File Name: os_cpu_c.c
* Author: Librae
* Date: 06/10/2010
* Description: μCOS-II在STM32上的移植代码C语言部分,
*包括任务堆栈初始化代码和钩子函数等
******************************************************************************/
#ifndef __OS_CPU_H__
#define __OS_CPU_H__
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#defineOS_CPU_EXT extern
#endif
/******************************************************************************
*定义与编译器无关的数据类型
******************************************************************************/
typedef unsignedchar BOOLEAN;
typedef unsignedchar INT8U;
/* Unsigned 8 bit quantity*/
typedef signedchar INT8S;
/*Signed8 bit quantity*/
typedef unsignedshort INT16U;
/*Unsigned 16 bit quantity*/
typedef signedshort INT16S;
/* Signed16 bit quantity*/
typedef unsignedintINT32U;
/* Unsigned 32 bit quantity*/
typedef signedintINT32S;
/*Signed32 bit quantity*/
typedef floatFP32;
/*Single precision floating point*/
typedef doubleFP64;
/* Double precisionfloating point*/
//STM32是32位位宽的,这里OS_STK和OS_CPU_SR都应该为32位数据类型
typedef unsignedintOS_STK;
/* Each stack entry is 32-bit wide*/
typedef unsignedintOS_CPU_SR;
/* Define size of CPU status register*/
/*
*******************************************************************************
*Cortex M3
*Critical SectionManagement
*******************************************************************************
*/
/*
*******************************************************************************
*ARM Miscellaneous
*******************************************************************************
*/
//定义栈的增长方向.
//CM3中,栈是由高地址向低地址增长的,所以OS_STK_GROWTH设置为1
#define OS_STK_GROWTH1/* Stack grows from HIGH to LOW memory on ARM*/
//任务切换宏,由汇编实现.
#define OS_TASK_SW()OSCtxSw()
/*
*******************************************************************************
*PROTOTYPES
*(see OS_CPU_A.ASM)
*******************************************************************************
*/
//OS_CRITICAL_METHOD= 1 :直接使用处理器的开关中断指令来实现宏
//OS_CRITICAL_METHOD= 2 :利用堆栈保存和恢复CPU的状态
//OS_CRITICAL_METHOD= 3 :利用编译器扩展功能获得程序状态字,保存在局部变量cpu_sr
#define OS_CRITICAL_METHOD3//进入临界段的方法
#ifOS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();
}
#define OS_EXIT_CRITICAL(){OS_CPU_SR_Restore(cpu_sr);
}
#endif
voidOSCtxSw(void);
voidOSIntCtxSw(void);
voidOSStartHighRdy(void);
voidOSPendSV(void);
#ifOS_CRITICAL_METHOD == 3u/* See OS_CPU_A.ASM*/
OS_CPU_SR OS_CPU_SR_Save(void);
voidOS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif
OS_CPU_EXT INT32UOSInterrputSum;
#endif
/************************(C) COPYLEFT 2010 Leafgrass ************************/
os_cpu.h
/*
*********************************************************************************************************
*uC/OS-II
*TheReal-Time Kernel
*
*
*(c) Copyright2006, Micrium, Weston, FL
*AllRights Reserved
*
*ARMCortex-M3 Port
*
* File: OS_CPU_C.C
* Version: V2.86
* By: Jean J. Labrosse
*
* For: ARMv7M Cortex-M3
* Mode: Thumb2
* Toolchain :RealView Development Suite
*RealView MicrocontrollerDevelopment Kit (MDK)
*ARM Developer Suite (ADS)
*Keil uVision
*********************************************************************************************************
*/
#define OS_CPU_GLOBALS
#include"includes.h"
/*
*********************************************************************************************************
*LOCALVARIABLES
*********************************************************************************************************
*/
#if OS_TMR_EN >0
static INT16U OSTmrCtr;
#endif
/*
*********************************************************************************************************
*OSINITIALIZATION HOOK
*(BEGINNING)
*
* Description:This function is called by OSInit() at the beginning of OSInit().
*
* Arguments : none
*
* Note(s): 1) Interrupts should be disabled duringthis call.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSInitHookBegin (void)
{
#if OS_TMR_EN >0
OSTmrCtr = 0;
#endif
}
#endif
/*
*********************************************************************************************************
*OSINITIALIZATION HOOK
*(END)
*
* Description:This function is called by OSInit() at the end of OSInit().
*
* Arguments : none
*
* Note(s): 1) Interrupts should be disabled duringthis call.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSInitHookEnd (void)
{
}
#endif
/*
*********************************************************************************************************
*TASKCREATION HOOK
*
* Description:This function is called when a task is created.
*
* Arguments : ptcbis a pointer to the task control block of the task being created.
*
* Note(s): 1) Interrupts are disabled during thiscall.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0
void OSTaskCreateHook (OS_TCB *ptcb)
{
#ifOS_APP_HOOKS_EN > 0
App_TaskCreateHook(ptcb);
#else
(void)ptcb;
/* Preventcompiler warning*/
#endif
}
#endif
/*
*********************************************************************************************************
*TASKDELETION HOOK
*
* Description:This function is called when a task is deleted.
*
* Arguments : ptcbis a pointer to the task control block of the task being deleted.
*
* Note(s): 1) Interrupts are disabled during thiscall.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0
void OSTaskDelHook (OS_TCB *ptcb)
{
#ifOS_APP_HOOKS_EN > 0
App_TaskDelHook(ptcb);
#else
(void)ptcb;
/* Preventcompiler warning*/
#endif
}
#endif
/*
*********************************************************************************************************
*IDLE TASK HOOK
*
* Description:This function is called by the idle task. This hook has been added to allow you to do
*such things as STOP the CPU toconserve power.
*
* Arguments : none
*
* Note(s): 1) Interrupts are enabled during thiscall.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251
void OSTaskIdleHook (void)
{
#ifOS_APP_HOOKS_EN > 0
App_TaskIdleHook();
#endif
}
#endif
/*
*********************************************************************************************************
*STATISTIC TASK HOOK
*
* Description:This function is called every second by uC/OS-II's statistics task. This allows your
*application to add functionalityto the statistics task.
*
* Arguments : none
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0
void OSTaskStatHook (void)
{
#ifOS_APP_HOOKS_EN > 0
App_TaskStatHook();
#endif
}
#endif
/*
*********************************************************************************************************
*INITIALIZE A TASK'S STACK
*
* Description:This function is called by either OSTaskCreate() or OSTaskCreateExt() to initializethe
*stack frame of the task beingcreated. This function is highlyprocessor specific.
*
* Arguments : taskis a pointer to the task code
*
*p_argis a pointer to a user supplied dataarea that will be passed to the task
*when the task firstexecutes.
*
*ptosis a pointer to the top ofstack. It is assumed that 'ptos' pointsto
*a 'free' entry on the taskstack. If OS_STK_GROWTH is set to 1 then
*'ptos' will containthe HIGHEST valid address of the stack. Similarly, if
*OS_STK_GROWTH isset to 0, the 'ptos' will contains the LOWEST valid address
*of the stack.
*
*optspecifies options that can be usedto alter the behavior of OSTaskStkInit().
*(see uCOS_II.H forOS_TASK_OPT_xxx).
*
* Returns: Always returns the location of the newtop-of-stack once the processor registers have
*been placed on the stack in theproper order.
*
* Note(s): 1) Interrupts are enabled when your taskstarts executing.
*2) All tasks run in Thread mode,using process stack.
*********************************************************************************************************
*/
OS_STK*OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16Uopt)
{
OS_STK *stk;
(void)opt;
/* 'opt' isnot 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*/
*(--stk) = (INT32U)0xFFFFFFFEL;
/* 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*/
/* Remaining registers saved on process stack*/
*(--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);
}
/*
*********************************************************************************************************
*TASK SWITCHHOOK
*
* Description:This function is called when a task switch is performed. This allows you to perform other
*operations during a contextswitch.
*
* Arguments : none
*
* Note(s): 1) Interrupts are disabled during thiscall.
*2) It is assumed that the globalpointer 'OSTCBHighRdy' points to the TCB of the task that
*will be 'switched in' (i.e.the highest priority task) and, 'OSTCBCur' points to the
*task being switched out (i.e. thepreempted task).
*********************************************************************************************************
*/
#if(OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0)
void OSTaskSwHook (void)
{
#ifOS_APP_HOOKS_EN > 0
App_TaskSwHook();
#endif
}
#endif
/*
*********************************************************************************************************
*OS_TCBInit() HOOK
*
* Description:This function is called by OS_TCBInit() after setting up most of the TCB.
*
* Arguments : ptcbis a pointer to the TCB of the task being created.
*
* Note(s): 1) Interrupts may or may not be ENABLEDduring this call.
*********************************************************************************************************
*/
#ifOS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSTCBInitHook (OS_TCB *ptcb)
{
#ifOS_APP_HOOKS_EN > 0
App_TCBInitHook(ptcb);
#else
(void)ptcb;
/* Prevent compilerwarning*/
#endif
}
#endif
/*
*********************************************************************************************************
*TICK HOOK
*
* Description:This function is called every tick.
*
* Arguments : none
*
* Note(s): 1) Interrupts may or may not be ENABLEDduring this call.
*********************************************************************************************************
*/
#if(OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0)
void OSTimeTickHook (void)
{
#ifOS_APP_HOOKS_EN > 0
App_TimeTickHook();
#endif
#if OS_TMR_EN >0
OSTmrCtr++;
if (OSTmrCtr >= (OS_TICKS_PER_SEC /OS_TMR_CFG_TICKS_PER_SEC)) {
OSTmrCtr = 0;
OSTmrSignal();
}
#endif
}
#endif
#ifOS_CPU_HOOKS_EN > 0u && OS_VERSION > 290u
voidOSTaskReturnHook(OS_TCB *ptcb)
{
(void)ptcb;
}
#endif
/*-----------------------(C) COPYRIGHT @ 2012 liycobl ----------------- end of file -----------------*/
os_cpu_a.asm
;
/***********************(C) COPYRIGHT 2010 Libraworks *************************
;
* File Name: os_cpu_a.asm
;
* Author: Librae
;
* Version: V1.0
;
* Date: 06/10/2010
;
* Description: μCOS-II asm portfor STM32
;
*******************************************************************************/
IMPORT OSRunning;
External references
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSIntNesting
IMPORT OSIntExit
IMPORT OSTaskSwHookEXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
EXPORT OS_CPU_SR_Save;
Functions declared in this file
EXPORT OS_CPU_SR_Restore
EXPORT PendSV_HandlerNVIC_INT_CTRLEQU0xE000ED04 ;
中断控制寄存器
NVIC_SYSPRI2EQU0xE000ED20 ;
系统优先级寄存器(2)
NVIC_PENDSV_PRIEQU0xFFFF0000 ;
PendSV中断和系统节拍中断
;
(都为最低,0xff).
NVIC_PENDSVSET EQU0x10000000 ;
触发软件中断的值.
PRESERVE8 AREA|.text|, CODE, READONLY
THUMB ;
********************************************************************************************************
;
CRITICALSECTION METHOD 3 FUNCTIONS
;
;
Description:Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
;
would store the state of theinterrupt disable flag in the local variable 'cpu_sr' and then
;
disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II'sfunctions that need to
;
disable interrupts. You would restore the interrupt disable stateby copying back 'cpu_sr'
;
into the CPU's status register.
;
;
Prototypes:OS_CPU_SR OS_CPU_SR_Save(void);
;
voidOS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
;
Note(s): 1) These functions are used in generallike this:
;
;
void Task (void *p_arg)
;
{
;
#if OS_CRITICAL_METHOD ==3/* Allocate storage for CPUstatus register */
;
OS_CPU_SR cpu_sr;
;
#endif
;
;
:
;
:
;
OS_ENTER_CRITICAL();
/* cpu_sr = OS_CPU_SaveSR();
*/
;
:
;
:
;
OS_EXIT_CRITICAL();
/* OS_CPU_RestoreSR(cpu_sr);
*/
;
:
;
:
;
}
;
********************************************************************************************************
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
;
*
;
* 功能描述:使用调度器运行第一个任务
;
*
;
* 参数: None
;
*
;
* 返 回 值: None
;
**************************************************************************************/
OSStartHighRdy
LDRR4, =NVIC_SYSPRI2;
set thePendSV exception priority
LDRR5, =NVIC_PENDSV_PRI
STRR5, [R4]
MOVR4, #0;
set thePSP to 0 for initial context switch call
MSRPSP, R4
LDRR4, =OSRunning;
OSRunning= TRUE
MOVR5, #1
STRBR5, [R4]
;
切换到最高优先级的任务
LDRR4, =NVIC_INT_CTRL;
rigger thePendSV exception (causes context switch)
LDRR5, =NVIC_PENDSVSET
STRR5, [R4]
CPSIEI;
enableinterrupts at processor level
OSStartHang
BOSStartHang;
shouldnever get here
;
/**************************************************************************************
;
* 函数名称: OSCtxSw
;
*
;
* 功能描述:任务级上下文切换
;
*
;
* 参数: None
;
*
;
* 返 回 值: None
;
***************************************************************************************/
OSCtxSw
PUSH{R4, R5}
LDRR4, =NVIC_INT_CTRL;
触发PendSV异常 (causes context switch)
LDRR5, =NVIC_PENDSVSET
STRR5, [R4]
POP{R4, R5}
BXLR
;
/**************************************************************************************
;
* 函数名称: OSIntCtxSw
;
*
;
* 功能描述:中断级任务切换
;
*
;
* 参数: None
;
*
;
* 返 回 值: None
;
***************************************************************************************/
OSIntCtxSw
PUSH{R4, R5}
LDRR4, =NVIC_INT_CTRL;
触发PendSV异常(causes context switch)
LDRR5, =NVIC_PENDSVSET
STRR5, [R4]
POP{R4, R5}
BXLR
NOP
;
/**************************************************************************************
;
* 函数名称: OSPendSV
;
*
;
* 功能描述: OSPendSV is used to cause acontext switch.
;
*
;
* 参数: None
;
*
;
* 返 回 值: None
;
***************************************************************************************/
PendSV_Handler
CPSIDI;
Prevent interruption during context switch
MRSR0, PSP;
PSP is process stackpointer如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈-白菜注
CBZR0, PendSV_Handler_Nosave;
Skip register save thefirst time
SUBSR0, R0, #0x20;
Saveremaining 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
;
At this point, entire context of process has been saved
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
MSRPSP, R0;
Load PSP with new process SP
ORRLR, LR, #0x04;
Ensureexception return uses process stack
CPSIEI
BXLR;
Exception return willrestore remaining context
end
关键是:
关键点1:
官方移植好的版本里自带STM32启动文件vectors.s,当然我们一般用STM32库自带的startup_stm32f10x_hd.s启动文件。这里就有要注意的地方。按照官方移植好的版本要求PendSV的中断函数名字是OS_CPU_OSPendSV,而startup_stm32f10x_hd.s里面已经定义好的名字是PendSV_Handler
PendSV_Handler PROC
EXPORT PendSV_Handler[WEAK]
B.
ENDP
所以我们要统一一下,我的办法是把Ucosii中所有出现的OS_CPU_OSPendSV改成PendSV_Handler。为什么不改startup_stm32f10x_hd.s,是因为这样移植的兼容性更好,下次一直到另一个STM32工程里时候,直接把Ucos ii的文件全部拷贝过去,不用修改另一个STM32工程里的startup_stm32f10x_hd.s。
关键点2:
编写SysTick_Handler(void)时钟滴答中断函数。
随便在某一个源文件里实现就可以,我在stm32f10x_it.c里实现了这个函数
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
//2017-5-21欧阳海宾注释掉。
voidSysTick_Handler(void)
{
OSIntEnter();
//进入中断
OSTimeTick();
//调用ucos的时钟服务程序
OSIntExit();
//触发任务切换软中断
}
关键点3:编写延时函数,正点原子或刘洋都有,直接粘贴出来就是
Pbdata.h
#ifndef _pbdata_H
#define _pbdata_H
#include"stm32f10x.h"
#include"includes.h"
#include"misc.h"
//ucosII任务堆栈设置
//设置任务优先级
#defineSTART_TASK_PRIO 8
#defineSTART_TASK2_PRIO 9
#defineSTART_TASK3_PRIO 10
//设置任务堆栈大小
#defineSTART_STK_SIZE 64 //空间大小=64*4(字节)
#defineSTART_STK_SIZE2 64 // 空间大小=64*4(字节)
#defineSTART_STK_SIZE3 64 // 空间大小=64*4(字节)
//创建任务堆栈空间
static OS_STKSTART_TASK_STK[START_STK_SIZE];
static OS_STKSTART_TASK_STK2[START_STK_SIZE2];
static OS_STKSTART_TASK_STK3[START_STK_SIZE3];
extern OS_EVENT*led1_MsgQueue;
extern void*MsgQueuetb[20];
//定义函数
void delay(uint32_t nCount);
void Delay_Init(void);
void delay_us(uint32_t nus);
void delay_ms(uint16_t nms);
void LED_GPIO_Config(void);
/* the macrodefinition to trigger the led on or off
* 1 - on
- 0 - off
*/
#define ON 1
#define OFF 0
//带参宏,可以像内联函数一样使用
#define LED1(a) if (a)\
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
\
else\
GPIO_SetBits(GPIOB,GPIO_Pin_8)#endif
Pbdata.c
#include"pbdata.h"
OS_EVENT*led1_MsgQueue;
void* MsgQueuetb[20];
static uint8_t fac_us=0;
//us延时倍乘数
static uint16_tfac_ms=0;
//ms延时倍乘数
//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void Delay_Init(void)
{
uint32_t reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000;
//为系统时钟的1/8 reload=SystemCoreClock/8000000;
//每秒钟的计数次数 单位为K
reload*=1000000/OS_TICKS_PER_SEC;
//根据OS_TICKS_PER_SEC设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
fac_ms=1000/OS_TICKS_PER_SEC;
//代表ucos可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;
//开启SYSTICK中断
SysTick->LOAD=reload;
//每1/OS_TICKS_PER_SEC秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
//开启SYSTICK
}
//延时nus
//nus为要延时的us数.
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD;
//LOAD的值
ticks=nus*fac_us;
//需要的节拍数
tcnt=0;
told=SysTick->VAL;
//刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow=ticks)break;
//时间超过/等于要延迟的时间,则退出.
}
};
}
//延时nms
//nms:要延时的ms数
void delay_ms(uint16_tnms)
{
if(OSRunning==TRUE)//如果os已经在跑了
{
if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期
{
OSTimeDly(nms/fac_ms);
//ucos延时
}
nms%=fac_ms;
//ucos已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((uint32_t)(nms*1000));
//普通方式延时,此时ucos无法启动调度.
}
void delay(uint32_t nCount)
{
for(;
nCount!=0;
nCount--);
}
/*
*函数名:LED_GPIO_Config
*描述 :配置LED用到的I/O口
*输入 :无
*输出 :无
*/
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启GPIOF的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*选择要控制的GPIOC引脚*/
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_5;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOC*/
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* 关闭所有led灯*/
GPIO_SetBits(GPIOB, GPIO_Pin_8);
//GPIO_SetBits(GPIOB, GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
到这里就移植完成,但是用的时候经常会有问题!这里就针对网上最流行的一种问题进行解决
经常会有人,运行的时候卡在空闲任务或单步调试进入硬件错误的中断函数里或者卡在延时函数。
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
if (CoreDebug->DHCSR & 1) { //check C_DEBUGEN == 1 -> DebuggerConnected
__breakpoint(0);
// halt program execution here
}
/* Go to infinite loop when Hard Faultexception occurs */
while (1)
{
}
}
其实都是一个原因,就是空闲任务不能少且不能放错位置,初始化统计任务不能放在OSInit();
和OSStart();
之间,必须用在另一个任务的初始化代码里来,否则会出现运行的时候卡在空闲任务或单步调试进入硬件错误的中断函数里,我就是在这里卡了一天才移植成功,网上百度居然没有一种方法说明白了问题的所在和解决办法。
下面贴出我的主函数
main.c
#include"includes.h" //里面是ucos ii的头文件
#define ON 1
#define OFF 0
#define LED2(a) if (a)\
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
\
else\
GPIO_SetBits(GPIOB,GPIO_Pin_8)
//设置任务堆栈大小
void start_task(void *pdata);
void start_task2(void *pdata);
void start_task3(void *pdata);
OS_EVENT *sem;
int main(void)
{
RCC_ClocksTypeDefRCC_Clocks;
sem=OSSemCreate(0);
Delay_Init();
//初始化延时函数
SystemInit();
LED_GPIO_Config();
RCC_GetClocksFreq(&RCC_Clocks);
OSInit();
//初始化UCOS操作系统
//OSStatInit();
//初始化统计任务放在此处会导致硬件错误,必须放在下面就Ok了 欧阳海宾2017-5-22
OSTaskCreate(start_task,//指向任务代码的指针
(void *)0,//任务开始执行时,传递给任务参数的指针
(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],//分配给任务堆栈的栈顶指针
START_TASK_PRIO);
//分配给任务的优先级
OSTaskCreate(start_task2,//指向任务代码的指针
(void *)0,//任务开始执行时,传递给任务参数的指针
(OS_STK*)&START_TASK_STK2[START_STK_SIZE2-1],//分配给任务堆栈的栈顶指针
START_TASK2_PRIO);
//分配给任务的优先级
OSTaskCreate(start_task3,//指向任务代码的指针
(void *)0,//任务开始执行时,传递给任务参数的指针
(OS_STK*)&START_TASK_STK3[START_STK_SIZE3-1],//分配给任务堆栈的栈顶指针
START_TASK3_PRIO);
//分配给任务的优先级OSStart();
//启动ucos操作系统
}
void start_task(void *pdata)
{
INT8U error;
OS_CPU_SR cpu_sr=0;
pdata=https://www.it610.com/article/pdata;
//OSStatInit();
//初始化统计任务,不能放在上面!while(1)
{
OSSemPend(sem,0,&error);
LED2(OFF);
delay_ms(500);
//OSSemPost(sem);
//delay_ms(500);
}
}
void start_task2(void *pdata)
{
INT8U error;
OS_CPU_SR cpu_sr=0;
pdata=pdata;
//OSStatInit();
//初始化统计任务
OSStatInit();
//???????
while(1)
{
LED2(ON);
delay_ms(500);
OSSemPost(sem);
//delay_ms(500);
//OSSemPend(sem,0,&error);
}
}
void start_task3(void *pdata)
{uint16_t i=0;
pdata = pdata;
while(1)
{
//OS_ENTER_CRITICAL();
OSIdleCtr++;
//OS_EXIT_CRITICAL();
}
}
这个代码是我在硬件STM32f103上实现了的,可以实现led闪烁!
【ucos|ucos ii移植到STM32 (HardFault_Handler)】
??
推荐阅读
- stm32|基于STM32和freeRTOS智能门锁设计方案
- 日常分享|共享充电宝方案原理,具体部件组成以及主控MUC参数
- #|ARM裸机开发(汇编LED灯实验(I.MX6UL芯片))
- STM32|STM32的四种IO输出模式
- STM32 远程升级(ISP / IAP)
- leetcode做题笔记|leetcode:
- 课程笔记|uCos中的邮箱和消息队列
- stm32|stm32f103can总线过滤器配置
- STM32CubeMX配置SDIO模式(非DMA方式)
- STM32|如何建一个STM32F030标准库工程模板