STM32F4X UCOSIII任务

什么是任务

在日常生活中,我们要完成一个问题时,一般都会把一个大问题分解成若干个小问题,当每个小问题依次被解决时,大问题也随之被解决。同样地对于MCU来说也是如此,通常在没有RTOS的情况下,一般我们都会把所有的业务逻辑都放到main函数里面进行解决,但是随着业务逻辑的不断增多,就会发现把所有的业务逻辑都放到main函数里面就会显得特别臃肿,而且实时性也不好。RTOS可以把一个很复杂的业务逻辑分成一个个的任务,每个任务都可以根据自己的事件片进行调度,从而使程序更加简洁,提高实时性。

UCOS任务

任务控制块(OS_TCB)

在UCOSIII中,每个任务都会有自己的任务控制块,所谓的任务控制块就类似于人的身份证,是这个任务的唯一标识,后续对任务的操作都会基于任务控制块进行操作。

struct os_tcb {
    CPU_STK             *StkPtr;                            /* Pointer to current top of stack                        */

    void                *ExtPtr;                            /* Pointer to user definable data for TCB extension       */

#if ((OS_CFG_DBG_EN > 0u) || (OS_CFG_STAT_TASK_STK_CHK_EN > 0u))
    CPU_STK             *StkLimitPtr;                       /* Pointer used to set stack 'watermark' limit            */
#endif

    OS_TCB              *NextPtr;                           /* Pointer to next     TCB in the TCB list                */
    OS_TCB              *PrevPtr;                           /* Pointer to previous TCB in the TCB list                */

    OS_TCB              *TickNextPtr;
    OS_TCB              *TickPrevPtr;

    OS_TICK_LIST        *TickListPtr;                       /* Pointer to tick list if task is in a tick list         */

#if OS_CFG_DBG_EN > 0u
    CPU_CHAR            *NamePtr;                           /* Pointer to task name                                   */
#endif

#if ((OS_CFG_DBG_EN > 0u) || (OS_CFG_STAT_TASK_STK_CHK_EN > 0u))
    CPU_STK             *StkBasePtr;                        /* Pointer to base address of stack                       */
#endif

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    OS_TLS               TLS_Tbl[OS_CFG_TLS_TBL_SIZE];
#endif

#if OS_CFG_DBG_EN > 0u
    OS_TASK_PTR          TaskEntryAddr;                     /* Pointer to task entry point address                    */
    void                *TaskEntryArg;                      /* Argument passed to task when it was created            */
#endif

    OS_PEND_DATA        *PendDataTblPtr;                    /* Pointer to list containing objects pended on           */
    OS_STATE             PendOn;                            /* Indicates what task is pending on                      */
    OS_STATUS            PendStatus;                        /* Pend status                                            */

    OS_STATE             TaskState;                         /* See OS_TASK_STATE_xxx                                  */
    OS_PRIO              Prio;                              /* Task priority (0 == highest)                           */
#if ((OS_CFG_DBG_EN > 0u) || (OS_CFG_STAT_TASK_STK_CHK_EN > 0u))
    CPU_STK_SIZE         StkSize;                           /* Size of task stack (in number of stack elements)       */
#endif
    OS_OPT               Opt;                               /* Task options as passed by OSTaskCreate()               */

    OS_OBJ_QTY           PendDataTblEntries;                /* Size of array of objects to pend on                    */

    CPU_TS               TS;                                /* Timestamp                                              */
#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
    CPU_INT08U           SemID;                             /* Unique ID for third-party debuggers and tracers.       */
#endif
    OS_SEM_CTR           SemCtr;                            /* Task specific semaphore counter                        */

                                                            /* DELAY / TIMEOUT                                        */
    OS_TICK              TickRemain;                        /* Number of ticks remaining (updated at by OS_TickTask() */
    OS_TICK              TickCtrPrev;                       /* Used by OSTimeDly??() in PERIODIC mode                 */

#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    OS_TICK              TimeQuanta;
    OS_TICK              TimeQuantaCtr;
#endif

#if OS_MSG_EN > 0u
    void                *MsgPtr;                            /* Message received                                       */
    OS_MSG_SIZE          MsgSize;
#endif

#if OS_CFG_TASK_Q_EN > 0u
    OS_MSG_Q             MsgQ;                              /* Message queue associated with task                     */
#if OS_CFG_TASK_PROFILE_EN > 0u
    CPU_TS               MsgQPendTime;                      /* Time it took for signal to be received                 */
    CPU_TS               MsgQPendTimeMax;                   /* Max amount of time it took for signal to be received   */
#endif
#endif

#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OS_REG               RegTbl[OS_CFG_TASK_REG_TBL_SIZE];  /* Task specific registers                                */
#endif

#if OS_CFG_FLAG_EN > 0u
    OS_FLAGS             FlagsPend;                         /* Event flag(s) to wait on                               */
    OS_FLAGS             FlagsRdy;                          /* Event flags that made task ready to run                */
    OS_OPT               FlagsOpt;                          /* Options (See OS_OPT_FLAG_xxx)                          */
#endif

#if OS_CFG_TASK_SUSPEND_EN > 0u
    OS_NESTING_CTR       SuspendCtr;                        /* Nesting counter for OSTaskSuspend()                    */
#endif

#if OS_CFG_TASK_PROFILE_EN > 0u
    OS_CPU_USAGE         CPUUsage;                          /* CPU Usage of task (0.00-100.00%)                       */
    OS_CPU_USAGE         CPUUsageMax;                       /* CPU Usage of task (0.00-100.00%) - Peak                */
    OS_CTX_SW_CTR        CtxSwCtr;                          /* Number of time the task was switched in                */
    CPU_TS               CyclesDelta;                       /* value of OS_TS_GET() - .CyclesStart                    */
    CPU_TS               CyclesStart;                       /* Snapshot of cycle counter at start of task resumption  */
    OS_CYCLES            CyclesTotal;                       /* Total number of # of cycles the task has been running  */
    OS_CYCLES            CyclesTotalPrev;                   /* Snapshot of previous # of cycles                       */

    CPU_TS               SemPendTime;                       /* Time it took for signal to be received                 */
    CPU_TS               SemPendTimeMax;                    /* Max amount of time it took for signal to be received   */
#endif

#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
    CPU_STK_SIZE         StkUsed;                           /* Number of stack elements used from the stack           */
    CPU_STK_SIZE         StkFree;                           /* Number of stack elements free on   the stack           */
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_TS               IntDisTimeMax;                     /* Maximum interrupt disable time                         */
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
    CPU_TS               SchedLockTimeMax;                  /* Maximum scheduler lock time                            */
#endif

#if OS_CFG_DBG_EN > 0u
    OS_TCB              *DbgPrevPtr;
    OS_TCB              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
    CPU_INT08U           TaskID;                            /* Unique ID for third-party debuggers and tracers.       */
#endif
};

可以看到任务控制块结构体里面有很多成员变量,这些变量都是记录了每个任务的状态,当然这些变量我们只需要做个简单的理解即可,因为在任务的运行中我们都不需要直接去访问这些变量,UCOSIII会通过API进行访问。

UCOSIII任务的状态

任务状态图

任务就像日常生活中的人一样,也有自己的运行状态,任务大概可以分成以下几种状态。
在这里插入图片描述

  • (1):创建任务–>就绪态:任务被创建后会被放到任务的就绪列表中,此时还没有被调度。
  • (2):就绪态–>运行态:发生任务切换时,任务就绪列表中优先级最高的任务会被调度,此时就进入运行态。
  • (3):运行态–>就绪态:如果此时有一个更高优先级的任务被创建或者恢复后,发生任务调度,此时更高优先级的任务会被调度,原先运行的任务会重新回到任务就绪列表,变成就绪态。
  • (4):运行态–>阻塞态:任务在等待某些资源(信号量、互斥锁、消息等),此时任务会进行阻塞状态。
  • (5):阻塞态–>就绪态:如果任务被恢复后(获取到资源),会重新把任务放到就绪列表中,等待调度。
  • (6)(7)(8):阻塞态、就绪态、运行态–>删除态:调用OSTaskDel函数将任务删除,被删除的任务不能再次使用,也不会继续参与任务的调度
  • (9):删除态–>就绪态:调用OSTaskCreate函数创建任务,任务重新进入就绪态。

UCOSIII任务状态

从上图可以大概知道RTOS中的任务状态,下面就来具体了解一下UCOSIII的任务状态。

  • (就绪)OS_TASK_STATE_RDY:任务被创建后被放到就绪列表,等待调度
  • (延时)OS_TASK_STATE_DLY:调用OSTimeDly,任务会进入延时调度状态。
  • (阻塞)OS_TASK_STATE_PEND:当任务等待信号量,互斥锁,消息等资源时,会进入阻塞状态
  • (阻塞超时)OS_TASK_STATE_PEND_TIMEOUT:任务在等待信号量,互斥锁,消息等资源时,可以设置超时阻塞时间,超过时间任务会退出阻塞态,进行就绪态
  • (挂起)OS_TASK_STATE_SUSPENDED:任务调用OSTaskSuspend挂起自己或者其他任务,被挂起的任务将不参与调度,直到调用OSTaskResume恢复任务。
  • (延时+挂起)OS_TASK_STATE_DLY_SUSPENDED:任务延时一段时间,当延时还没结束就被挂起时,效果叠加。只有当延时结束并且挂起被恢复时,任务才会进行调度。
  • (阻塞+挂起)OS_TASK_STATE_PEND_SUSPENDED:任务阻塞等待资源进入阻塞态时,被其他任务挂起时,效果叠加。只有当获取到资源退出阻塞态并且挂起被恢复时,任务才会进行调度。
  • (超时等待 + 挂起)OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:任务在指定时间内等待事件或信号的产生,但是任务已经被其他任务挂起。
  • (删除)OS_TASK_STATE_DEL:调用OSTaskDel删除任务,被删除任务不能继续使用

任务优先级

UCOSIII的任务在创建的时候可以设置任务的优先级,任务调度器通常会选择优先级调度优先级高的任务先运行。在UCOSIII中,最大支持的优先级是0-255,数值越低,代表优先级越高。UCOSIII可以通过配置文件设置优先级的数量。

任务调度

抢占式调度

UCOSIII是一个可抢占,支持优先级的内核,在创建任务的时候给每个任务都分配了一个优先级,可抢占的意思是如果在系统出现一个高优先级任务,那么这个高优先级的任务会立刻进行调度。当系统发生一些可以触发任务调度的事件时,UCOSIII会选择任务就绪列表中优先级最高的任务进行调度。同样地当中断结束后也会进行任务调度,此时UCOSIII也是会选择任务就绪列表中优先级最高的任务进行调度。下图简单描述了高优先级调度的过程。
在这里插入图片描述

  • 低优先级任务正在运行,此时发生了一次中断
  • 系统进入中断
  • 开始运行中断服务函数
  • 中断服务函数运行完成,跳出中断
  • UCOSIII接管系统
  • 由于有高优先级任务,UCOSIII选择运行高优先级任务,低优先级任务不运行
  • 开始运行高优先级任务
  • 高优先级任务运行完成
  • UCOSIII接管系统
  • 选择低优先级任务运行
  • 开始运行低优先级任务

时间片轮转调度

当多个任务有相同的优先级时,uC/OS-III 允许每个任务运行规定的时间片。当任务没有用完分配给它的时间片时,它可以自愿地放弃CPU。
在这里插入图片描述
假设有2个优先级相同的就绪态线程A与B,A 线程的时间片设置为10,B线程的时间片设置为 5,那么当系统中不存在比A优先级高的就绪态线程时,系统会在 A、B线程间来回切换执行,并且每次对A线程执行10个节拍的时长,对B线程执行5个节拍的时长。

任务调度点

当系统发生以下事件时,会触发任务的调度

  1. 任务被标记或发送消息给另一个任务
  2. 任务调用 OSTimeDly()或 OSTimeDlyHMSM()
  3. 任务所等待的事件发生或超时
  4. 任务取消挂起
  5. 新任务被创建
  6. 任务被删除
  7. 内核对象被删除
  8. 任务改变自身的优先级或其它任务的优先级
  9. 当任务通过调用 OSTaskSuspend()停止自身
  10. 任务调用 OSTaskResume()恢复其它停止了的任务
  11. 退出中断服务程序
  12. 通过调用 OSSchedUnlock()调度器被解锁
  13. 调用 OSSchedRoundRobinYield()任务放弃了分配给它的时间片
  14. 用户调用 OSSched()

任务栈

UCOSIII中每个任务都有自己的栈空间,任务栈的作用是用来进行任务调度时保存当前任务的状态,以便后续恢复任务。UCOSIII中的任务栈初始化函数是OSTaskStkInit

CPU_STK  *OSTaskStkInit (OS_TASK_PTR    p_task,
                         void          *p_arg,
                         CPU_STK       *p_stk_base,
                         CPU_STK       *p_stk_limit,
                         CPU_STK_SIZE   stk_size,
                         OS_OPT         opt)
{
    CPU_STK    *p_stk;


    (void)opt;                                                  /* Prevent compiler warning                               */

    p_stk = &p_stk_base[stk_size];                              /* Load stack pointer                                     */
                                                                /* Align the stack to 8-bytes.                            */
    p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
                                                                /* Registers stacked as if auto-saved on exception        */
    *--p_stk = (CPU_STK)0x01000000u;                            /* xPSR                                                   */
    *--p_stk = (CPU_STK)p_task;                                 /* 任务处理函数                                            */
    *--p_stk = (CPU_STK)OS_TaskReturn;                          /* 任务返回函数,通常任务都是一个死循环,没有返回                                            */
    *--p_stk = (CPU_STK)0x12121212u;                            /* R12                                                    */
    *--p_stk = (CPU_STK)0x03030303u;                            /* R3                                                     */
    *--p_stk = (CPU_STK)0x02020202u;                            /* R2                                                     */
    *--p_stk = (CPU_STK)p_stk_limit;                            /* R1    任务的栈大小                                                 */
    *--p_stk = (CPU_STK)p_arg;                                  /* R0 : 任务参数                                          */
                                                                /* Remaining registers saved on process stack             */
    *--p_stk = (CPU_STK)0x11111111u;                            /* R11                                                    */
    *--p_stk = (CPU_STK)0x10101010u;                            /* R10                                                    */
    *--p_stk = (CPU_STK)0x09090909u;                            /* R9                                                     */
    *--p_stk = (CPU_STK)0x08080808u;                            /* R8                                                     */
    *--p_stk = (CPU_STK)0x07070707u;                            /* R7                                                     */
    *--p_stk = (CPU_STK)0x06060606u;                            /* R6                                                     */
    *--p_stk = (CPU_STK)0x05050505u;                            /* R5                                                     */
    *--p_stk = (CPU_STK)0x04040404u;                            /* R4                                                     */
    return (p_stk);
}

由于ARM的栈是满减栈,所以任务栈的生成方向如下所示
在这里插入图片描述
上面的任务栈初始化代码可以分成两部分,一部分是初始化R0-R3、R12、R14和PC,分别保存了任务的参数,任务的入口函数、任务的返回函数。R0-R3、R12、R14、PSR和PC会在发生异常时,自动压入栈里面,并且返回时自动弹栈,不用人为保存。第二部分是初始化R4-R11,因为任务刚创建,还没开始运行,所以初始化的值都是固定值。

UCOSIII任务常用函数

任务创建函数OSTaskCreate

/*
 * p_tcb:任务控制块
 * p_name:任务名
 * p_task:任务入口函数
 * p_arg:任务参数
 * prio:任务优先级
 * p_stk_base:任务栈地址
 * stk_limit:栈深度的限制位置
 * stk_size;任务栈大小
 * q_size:设置可以发送到任务的最大消息数
 * time_quanta:在任务之间循环时的时间片的时间量(以滴答为单位)。指定0则使		用默认值
 * p_ext:向用户提供的内存位置的指针,用作 TCB 扩展
 * opt:用户可选的任务特定选项
 * p_err:返回的错误码
*/
void  OSTaskCreate (OS_TCB        *p_tcb,
                    CPU_CHAR      *p_name,
                    OS_TASK_PTR    p_task,
                    void          *p_arg,
                    OS_PRIO        prio,
                    CPU_STK       *p_stk_base,
                    CPU_STK_SIZE   stk_limit,
                    CPU_STK_SIZE   stk_size,
                    OS_MSG_QTY     q_size,
                    OS_TICK        time_quanta,
                    void          *p_ext,
                    OS_OPT         opt,
                    OS_ERR        *p_err)
{

任务删除函数OSTaskDel

/*
 * p_tcb:任务控制块
 * p_err:返回的错误码
*/
void  OSTaskDel (OS_TCB  *p_tcb,
                 OS_ERR  *p_err)

任务挂起函数OSTaskSuspend

/*
 * p_tcb:任务控制块
 * p_err:返回的错误码
*/
void   OSTaskSuspend (OS_TCB  *p_tcb,
                      OS_ERR  *p_err)

任务恢复函数OSTaskResume

/*
 * p_tcb:任务控制块
 * p_err:返回的错误码
*/
void  OSTaskResume (OS_TCB  *p_tcb,
                    OS_ERR  *p_err)

任务延时函数

/*
 * dly:延时的时间片
 * opt:用户可选的特定选项
 * p_err:返回的错误码
*/
void  OSTimeDly (OS_TICK   dly,
                 OS_OPT    opt,
                 OS_ERR   *p_err)
/*
 * hours:小时
 * minutes:分
 * seconds:秒
 * milli:毫秒
 * opt:用户可选的特定选项
 * p_err:返回的错误码
*/
void  OSTimeDlyHMSM (CPU_INT16U   hours,
                     CPU_INT16U   minutes,
                     CPU_INT16U   seconds,
                     CPU_INT32U   milli,
                     OS_OPT       opt,
                     OS_ERR      *p_err)

UCOSIII任务创建例程

/*
*********************************************************************************************************
*                                              EXAMPLE CODE
*
*                             (c) Copyright 2013; Micrium, Inc.; Weston, FL
*
*                   All rights reserved.  Protected by international copyright laws.
*                   Knowledge of the source code may not be used to write a similar
*                   product.  This file may only be used in accordance with a license
*                   and should not be redistributed in any way.
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*
*                                            EXAMPLE CODE
*
*                                       IAR Development Kits
*                                              on the
*
*                                    STM32F429II-SK KICKSTART KIT
*
* Filename      : app.c
* Version       : V1.00
* Programmer(s) : YS
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/

#include  <includes.h>

/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

                                                                /* ----------------- APPLICATION GLOBALS -------------- */
static  OS_TCB   AppTaskStartTCB;
static  CPU_STK  AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE];

#define APPTASK1NAME    "App Task1"
#define APP_TASK1_PRIO          3   
#define APP_TASK1_STK_SIZE 1024
static OS_TCB AppTask1TCB;
static void  AppTask1  (void *p_arg);
static CPU_STK AppTask1Stk[APP_TASK1_STK_SIZE];

#define APPTASK2NAME    "App Task2"
#define APP_TASK2_PRIO          4   
#define APP_TASK2_STK_SIZE 1024
static OS_TCB AppTask2TCB;
static void  AppTask2  (void *p_arg);
static CPU_STK AppTask2Stk[APP_TASK2_STK_SIZE];
/*
*********************************************************************************************************
*                                         FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static  void  AppTaskStart          (void     *p_arg);


/*
*********************************************************************************************************
*                                                main()
*
* Description : This is the standard entry point for C code.  It is assumed that your code will call
*               main() once you have performed all necessary initialization.
*
* Arguments   : none
*
* Returns     : none
*********************************************************************************************************
*/

int main(void)
{

    OS_ERR  err;


    OSInit(&err);                                               /* Init uC/OS-III.                                      */
   
    OSTaskCreate((OS_TCB       *)&AppTaskStartTCB,              /* Create the start task                                */
                 (CPU_CHAR     *)"App Task Start",
                 (OS_TASK_PTR   )AppTaskStart,
                 (void         *)0u,
                 (OS_PRIO       )APP_CFG_TASK_START_PRIO,
                 (CPU_STK      *)&AppTaskStartStk[0u],
                 (CPU_STK_SIZE  )AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE / 10u],
                 (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE,
                 (OS_MSG_QTY    )0u,
                 (OS_TICK       )0u,
                 (void         *)0u,
                 (OS_OPT        )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR       *)&err);

    OSStart(&err);                                              /* Start multitasking (i.e. give control to uC/OS-III). */


}


/*
*********************************************************************************************************
*                                          STARTUP TASK
*
* Description : This is an example of a startup task.  As mentioned in the book's text, you MUST
*               initialize the ticker only once multitasking has started.
*
* Arguments   : p_arg   is the argument passed to 'AppTaskStart()' by 'OSTaskCreate()'.
*
* Returns     : none
*
* Notes       : 1) The first line of code is used to prevent a compiler warning because 'p_arg' is not
*                  used.  The compiler should not generate any code for this statement.
*********************************************************************************************************
*/

static  void  AppTaskStart (void *p_arg)
{
    CPU_INT32U  cpu_clk_freq;
    CPU_INT32U  cnts;
    OS_ERR      err;


   (void)p_arg;

    BSP_Init();                      
    CPU_Init();                                                 /* Initialize the uC/CPU services                       */

    cpu_clk_freq = BSP_CPU_ClkFreq();                           /* Determine SysTick reference freq.                    */
    cnts         = cpu_clk_freq                                 /* Determine nbr SysTick increments                     */
                 / (CPU_INT32U)OSCfg_TickRate_Hz;

    OS_CPU_SysTickInit(cnts);                                   /* Init uC/OS periodic time src (SysTick).              */

    Mem_Init();                                                 /* Initialize memory managment module                   */
    Math_Init();                                                /* Initialize mathematical module                       */


#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_IntDisMeasMaxCurReset();
#endif


#if (APP_CFG_SERIAL_EN == DEF_ENABLED)
    App_SerialInit();                                           /* Initialize Serial communication for application ...  */
#endif
	

	OSTaskCreate((OS_TCB     *)&AppTask1TCB,  // 线程TCB              
			 (CPU_CHAR   *)APPTASK1NAME, // 线程名字
			 (OS_TASK_PTR ) AppTask1, // 线程入口函数
			 (void       *) "TASK1", // 线程参数
			 (OS_PRIO     ) APP_TASK1_PRIO, // 线程优先级
			 (CPU_STK    *)&AppTask1Stk[0], // 线程栈起始地址
			 (CPU_STK_SIZE) APP_TASK1_STK_SIZE / 10, // 栈深度的限制位置
			 (CPU_STK_SIZE) APP_TASK1_STK_SIZE, // 栈大小
			 (OS_MSG_QTY  ) 5u, // 最大的消息个数
			 (OS_TICK     ) 0u, // 时间片
			 (void       *) 0, // 向用户提供的内存位置的指针
			 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), // 线程特定选项
			 (OS_ERR     *)&err); // 错误标志
	if(OS_ERR_NONE == err)
		printf("%s Create Success\r\n",APPTASK1NAME);
	else
		printf("%s Create Error\r\n",APPTASK1NAME);
	
			 
	OSTaskCreate((OS_TCB     *)&AppTask2TCB,  // 线程TCB              
			 (CPU_CHAR   *)APPTASK2NAME, // 线程名字
			 (OS_TASK_PTR ) AppTask2, // 线程入口函数
			 (void       *) "TASK2", // 线程参数
			 (OS_PRIO     ) APP_TASK2_PRIO, // 线程优先级
			 (CPU_STK    *)&AppTask2Stk[0], // 线程栈起始地址
			 (CPU_STK_SIZE) APP_TASK2_STK_SIZE / 10, // 栈深度的限制位置
			 (CPU_STK_SIZE) APP_TASK2_STK_SIZE, // 栈大小
			 (OS_MSG_QTY  ) 5u, // 最大的消息个数
			 (OS_TICK     ) 0u, // 时间片
			 (void       *) 0, // 向用户提供的内存位置的指针
			 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), // 线程特定选项
			 (OS_ERR     *)&err); // 错误标志
	if(OS_ERR_NONE == err)
		printf("%s Create Success\r\n",APPTASK2NAME);
	else
		printf("%s Create Error\r\n",APPTASK2NAME);
			 
	OSTaskDel ( & AppTaskStartTCB, & err );		 

}

static void  AppTask1  (void *p_arg)
{
    OS_ERR      err;
	while(DEF_TRUE)
	{
		printf("Task1 Runing  Task1 Arg %s\r\n",p_arg);
		OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次
	}
	
}
static void  AppTask2  (void *p_arg)
{
    OS_ERR      err;
	while(DEF_TRUE)
	{
		printf("Task1 Runing  Task2 Arg %s\r\n",p_arg);
		OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次
	}
	
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于uC/OS-IISTM32F4上的移植,以下是一个简单的教程: 步骤1:了解uC/OS-II 首先,您需要对uC/OS-II实时操作系统有一定的了解。阅读uC/OS-II的文档和参考手册,熟悉其核心概念和API。 步骤2:为STM32F4配置开发环境 确保您已经配置好了适合STM32F4的开发环境,包括编译器、调试器和开发板。您可以选择使用Keil MDK或者其他适合您的工具。 步骤3:创建uC/OS-II项目 在您的开发环境中创建一个新的uC/OS-II项目。这包括创建一个新的工程,并将uC/OS-II的源代码添加到项目中。 步骤4:配置STM32F4硬件 根据您的具体硬件配置,配置STM32F4的外设和引脚。确保将中断向量表正确地映射到uC/OS-II的中断处理程序。 步骤5:配置uC/OS-II内核 根据您的应用需求,配置uC/OS-II内核。这包括选择任务调度策略、配置任务优先级、堆栈大小等。 步骤6:编写应用程序 在uC/OS-II的基础上,编写您的应用程序。这包括创建任务、同步和通信机制,以及处理中断等。 步骤7:构建和调试 使用您的开发环境构建项目,并将生成的可执行文件下载到STM32F4开发板上进行调试。 请注意,以上仅提供了一个简单的概述,具体的步骤可能因您的具体情况而有所不同。在进行移植之前,建议您仔细阅读uC/OS-II的文档,并参考STM32F4的相关资料和示例代码。希望这个简要的教程能对您有所帮助!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值