您的位置:首页 > 其它

【嵌入式】uCOS-II在STM32上的移植

2016-12-06 23:43 399 查看
本文主要提供uCOS在STM32上的移植的一些步骤和个人见解,只涉及具体实操加一点解释,不讲原理,如有不当之处敬请指出。

文中使用的STM32型号为STM32F103C8T6,使用的uCOS版本为V2.91

零、

关于使用MDK创建STM32工程的步骤,在本人的另一篇文章,有兴趣的可以参考一下。

http://blog.csdn.net/d521000121/article/details/53107579

一、

先从网上下载下来uCOS-II的源码(官网可能在国内下不了,随便百度一搜多的是了),反正STM32是满足移植条件的了,我们直接就进行移植吧。

为了便于使用,我把源码分成三个目录,建好了工程后如下图:



这里解释一下,

UCOSII-PORT将是我们要自己写的一些文件,它和我们使用的芯片有关。

UCOSII-CONFIG是uCOS-II的一些相关设置文件,我们分别把两个头文件放在里面。

UCOSII-CORE是uCOS-II内核功能实现的代码,这一部分我们是不用理会的。

剩下的目录意思可以参考前面我提到的另一篇博文。

二、

工程建好了之后,我们就可以开始写一些与硬件相关的部分,使uCOS能泡在我们的STM32上。

这里分三个文件,就是在UCOSII-PORT里面的三个文件

1.OS_CPU.H

1).定义与编译器相关的数据类型,因为为了保证移植性,源码中是没有直接使用C语言的数据另行的,所以我们需要定义一下。

2).定义允许和禁止终端的宏,uCOS-II在访问临界区代码时,需要先关闭终端,后再打开中断,实现这两个功能的宏,也需要我们写。

就是定义OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()这两个宏。

3).定义栈的增长方向,其实对于ARM的处理器都是支持的,但是C语言编译器GCC只支持从上往下生长,所以要这样定义

#define  OS_STK_GROWTH        1 

4).定义OS_TASK_SW()宏

这个宏是任务从低优先级切换到高优先级时候用的,可以使用软中断将中断向量指向OSCtxSW()函数,或者直接调用OSCtxSW()函数就好了。

/************************ (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
#define OS_CPU_EXT  extern
#endif

/******************************************************************************
*                    定义与编译器无关的数据类型
******************************************************************************/

typedef 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*/

//STM32是32位位宽的,这里OS_STK和OS_CPU_SR都应该为32位数据类型
typedef unsigned int   OS_STK;			/* Each stack entry is 32-bit wide*/
typedef unsigned int   OS_CPU_SR;		/* Define size of CPU status register*/
/*
*******************************************************************************
*                             Cortex M3
*                     Criti
11400
cal Section Management
*******************************************************************************
*/

/*
*******************************************************************************
*                               PROTOTYPES
*                           (see OS_CPU_A.ASM)
*******************************************************************************
*/
//OS_CRITICAL_METHOD = 1 :直接使用处理器的开关中断指令来实现宏
//OS_CRITICAL_METHOD = 2 :利用堆栈保存和恢复CPU的状态
//OS_CRITICAL_METHOD = 3 :利用编译器扩展功能获得程序状态字,保存在局部变量cpu_sr

#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

#if OS_CRITICAL_METHOD == 3u                      /* See OS_CPU_A.ASM                                  */
OS_CPU_SR  OS_CPU_SR_Save(void);
void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif

/*
*******************************************************************************
*                          ARM Miscellaneous
*******************************************************************************
*/

//定义栈的增长方向.
//CM3中,栈是由高地址向低地址增长的,所以OS_STK_GROWTH设置为1
#define  OS_STK_GROWTH        1      /* Stack grows from HIGH to LOW memory on ARM    */

//任务切换宏,由汇编实现.
#define  OS_TASK_SW()         OSCtxSw()

void       OSCtxSw(void);
void       OSIntCtxSw(void);
void       OSStartHighRdy(void);

void       OSPendSV(void);

OS_CPU_EXT INT32U OSInterrputSum;

#endif

/************************ (C) COPYLEFT 2010 Leafgrass ************************/


2.OS_CPU_A.ASM

1).编写在OS_CPU.H中提到的一些需要用汇编语言实现的函数代码。

2).编写OSSTartHighRdy()函数,这时一个运行优先级最高的就绪任务。

它会在OSStart()启动后就执行,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针SP,然后进行CPU的现场恢复。这时系统会将控制权交给用户创建的任务。要写这个函数主要是因为SP操作会因CPU而异。

3).编写OSCtxSw()函数,这是任务优先级切换函数,其工作也是换的最高优先级任务的堆栈指针,然后进行切换。

4).编写OSInitCtSw()函数,这时中断级的任务切换函数,这个跟OSCtxSw()类似,但是它不需要保存被中断任务。

;/*********************** (C) COPYRIGHT 2010 Libraworks *************************
;* File Name	: os_cpu_a.asm
;* Author		: Librae
;* Version		: V1.0
;* Date			: 06/10/2010
;* Description	: μCOS-II asm port	for STM32
;*******************************************************************************/

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     0xE000ED20  ; 系统优先级寄存器(2)
NVIC_PENDSV_PRI 	EQU     0xFFFF0000  ; PendSV中断和系统节拍中断
; (都为最低,0xff).
NVIC_PENDSVSET  	EQU     0x10000000  ; 触发软件中断的值.

PRESERVE8

AREA    |.text|, CODE, READONLY
THUMB

;********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU's status register.
;
; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status 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
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
;*
;* 功能描述: 使用调度器运行第一个任务
;*
;* 参    数: None
;*
;* 返 回 值: None
;**************************************************************************************/

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
;*
;* 功能描述: 任务级上下文切换
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

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
;*
;* 功能描述: 中断级任务切换
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

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
;*
;* 功能描述: OSPendSV is used to cause a context switch.
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

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

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

; At this point, entire context of process has been saved
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
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

end


3.OS_CPU_C.C

这是移植C语言编写的6个与操作系统相关的函数。

这里唯一必须移植的是任务堆栈初始化函数OSTaskStkInit()。这个函数会在任务被创建的时候调用,负责初始化任务的堆栈结构并返回新堆栈指针stk,初始化工作结束后,返回新的堆栈栈顶指针。

其余的均为Hook函数,又叫钩子函数,主要用来控制uCOS-II功能,必须被声明但并不一定要含有代码。

/*
*********************************************************************************************************
*                                               uC/OS-II
*                                         The Real-Time Kernel
*
*
*                                (c) Copyright 2006, Micrium, Weston, FL
*                                          All Rights Reserved
*
*                                           ARM Cortex-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 Microcontroller Development Kit (MDK)
*             ARM Developer Suite (ADS)
*             Keil uVision
*********************************************************************************************************
*/

#define  OS_CPU_GLOBALS

#include "includes.h"
/*
*********************************************************************************************************
*                                          LOCAL VARIABLES
*********************************************************************************************************
*/

#if OS_TMR_EN > 0
static  INT16U  OSTmrCtr;
#endif

/*
*********************************************************************************************************
*                                       OS INITIALIZATION HOOK
*                                            (BEGINNING)
*
* Description: This function is called by OSInit() at the beginning of OSInit().
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void  OSInitHookBegin (void)
{
#if OS_TMR_EN > 0
OSTmrCtr = 0;
#endif
}
#endif

/*
*********************************************************************************************************
*                                       OS INITIALIZATION HOOK
*                                               (END)
*
* Description: This function is called by OSInit() at the end of OSInit().
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void  OSInitHookEnd (void)
{
}
#endif

/*
*********************************************************************************************************
*                                          TASK CREATION HOOK
*
* Description: This function is called when a task is created.
*
* Arguments  : ptcb   is a pointer to the task control block of the task being created.
*
* Note(s)    : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void  OSTaskCreateHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TaskCreateHook(ptcb);
#else
(void)ptcb;                                  /* Prevent compiler warning                           */
#endif
}
#endif

/*
*********************************************************************************************************
*                                           TASK DELETION HOOK
*
* Description: This function is called when a task is deleted.
*
* Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
*
* Note(s)    : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void  OSTaskDelHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TaskDelHook(ptcb);
#else
(void)ptcb;                                  /* Prevent compiler 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 to conserve power.
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts are enabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251
void  OSTaskIdleHook (void)
{
#if OS_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 functionality to the statistics task.
*
* Arguments  : none
*********************************************************************************************************
*/

#if OS_CPU_HOOKS_EN > 0
void  OSTaskStatHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TaskStatHook();
#endif
}
#endif

/*
*********************************************************************************************************
*                                        INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
*              stack frame of the task being created.  This function is highly processor specific.
*
* Arguments  : task          is a pointer to the task code
*
*              p_arg         is a pointer to a user supplied data area that will be passed to the task
*                            when the task first executes.
*
*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
*                            of the stack.
*
*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
*                            (see uCOS_II.H for OS_TASK_OPT_xxx).
*
* Returns    : Always returns the location of the new top-of-stack once the processor registers have
*              been placed on the stack in the proper order.
*
* Note(s)    : 1) Interrupts are enabled when your task starts 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, 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                                        */
*(--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 SWITCH HOOK
*
* Description: This function is called when a task switch is performed.  This allows you to perform other
*              operations during a context switch.
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts are disabled during this call.
*              2) It is assumed that the global pointer '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. the preempted task).
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0)
void  OSTaskSwHook (void)
{
#if OS_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  : ptcb    is a pointer to the TCB of the task being created.
*
* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void  OSTCBInitHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TCBInitHook(ptcb);
#else
(void)ptcb;                                  /* Prevent compiler warning                           */
#endif
}
#endif

/*
*********************************************************************************************************
*                                               TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0)
void  OSTimeTickHook (void)
{
#if OS_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

#if OS_CPU_HOOKS_EN > 0u && OS_VERSION > 290u

void OSTaskReturnHook(OS_TCB *ptcb)
{
(void)ptcb;
}

#endif

/*----------------------- (C) COPYRIGHT @ 2012 liycobl -----------------  end of file -----------------*/


4.要写的基本就写完了,然后我们就可以开始写我们想写的部分了

还记得我们在前面进入临界段的方法函数里面,有用到一个cpu_sr,所以我们在使用开关中断的方法之前,必须先定义一个局部变量cpu_sr,并设为0。

main函数里面,分为几步:

1).硬件初始化,比如gpio口,AD,DA什么的。

2).OSInit()

3).创建任务

创建任务前,需要先申请任务堆栈空间以及任务的优先级

4).OSStart()

这里我就写了一个LED灯点亮然后熄灭的小程序,大家可以参考参考。

/*********************************Includes*********************************/

#include "stm32f10x.h"
#include "includes.h"

/**************************************************************************/

/********************************task config*******************************/

//start task
#define START_TASK_PRIO 10
#define START_STK_SIZE 64
OS_STK START_TASK_STK[START_STK_SIZE];
void start_task (void *pdata);

//led task
#define LED_TASK_PRIO 11
#define LED_STK_SIZE 64
OS_STK LED_TASK_STK[LED_STK_SIZE];
void led_task (void *pdata);
void led_init (void);

/**************************************************************************/

int main(void)
{
delay_init();
NVIC_Configuration();
led_init();
OSInit();
OSTaskCreate(start_task, NULL, (OS_STK *) &START_TASK_STK[START_STK_SIZE-1], START_TASK_PRIO);
OSStart();
return 0;
}

void led_init ()
{
GPIO_InitTypeDef  GPIO_InitStructure;
delay_init();

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);							//使能PB端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;													//LED0-->PB.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 						 			//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 							//IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);					 									//根据设定参数初始化GPIOB.8
GPIO_SetBits(GPIOB,GPIO_Pin_8);						 												//PB.8 输出高
}

void led_task (void *pdata)
{
while (1)
{
GPIO_SetBits(GPIOB,GPIO_Pin_8);						 											//PB.8 输出高
OSTimeDly(200);
GPIO_ResetBits(GPIOB,GPIO_Pin_8);					 											//PB.8 输出低
OSTimeDly(200);
}
}

void start_task (void *pdata)
{
OS_CPU_SR cpu_sr = 0;																							//用于开关中断进入临界段
pdata = pdata;
OS_ENTER_CRITICAL();
OSTaskCreate(led_task, NULL, (OS_STK *) &LED_TASK_STK[LED_STK_SIZE-1], LED_TASK_PRIO);
OS_EXIT_CRITICAL();
OSTaskSuspend(START_TASK_PRIO);

}


最后应该还有挺多没讲清楚的地方,本人也只是在自己摸索阶段,有问题的地方谢谢大家指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: