STM32F4X UCOSIII任务信号量
- 任务信号量与内核信号量对比
- 内核信号量
- 任务信号量
- UCOSIII任务信号量API
- 任务信号量发送函数
- 任务信号量接收函数
- UCOSIII任务信号量例程
之前的章节中讲解过信号量这个机制,UCOSIII除了有内核信号量之外,还有任务信号量。在UCOSIII中,每个任务内部都会有一个32位的内嵌信号量。在大多数情况下,任务信号量可以代替内核信号量。
任务信号量与内核信号量对比
内容 | 内核信号量 | 任务信号量 |
---|---|---|
是否需要创建 | 是 | 否 |
是否需要指定任务 | 否 | 需要指定任务 |
是否可以广播 | 是 | 否 |
内核信号量
内核信号量在使用前需要用户创建信号量,内核信号量不需要指定接收信号量的任务,并且可以以广播的方式给所有等待信号量的任务获取信号量。
任务信号量
任务信号量不需要用户创建,任务信号量在创建任务的时候就已经内嵌到任务控制块里面。任务信号量使用的时候需要指定接收任务信号量的任务,而且一次只能指定一个任务,不能广播。
UCOSIII任务信号量API
任务信号量发送函数
/** p_tcb:指向需要发送信号量的任务,NULL则代表自己* opt:用户选项* p_err:错误代码
返回值:返回任务信号量值,如果在中断中调用,则为0
*/
OS_SEM_CTR OSTaskSemPost (OS_TCB *p_tcb,OS_OPT opt,OS_ERR *p_err)
opt可以选择OS_OPT_POST_NONE和OS_OPT_POST_NO_SCHED
- OS_OPT_POST_NONE:发送完任务信号量后不做任何操作
- OS_OPT_POST_NO_SCHED:发送完任务信号量后不调度
任务信号量接收函数
/** timeout:超时时间* opt:用户选项* p_ts:时间戳* p_err:错误代码
返回值:返回任务信号量值,如果在中断中调用,则为0
*/
OS_SEM_CTR OSTaskSemPend (OS_TICK timeout,OS_OPT opt,CPU_TS *p_ts,OS_ERR *p_err)
opt可以选择OS_OPT_PEND_BLOCKING和OS_OPT_PEND_NON_BLOCKING
- OS_OPT_PEND_BLOCKING:阻塞等待任务信号量,除非有任务信号量,否则任务不会恢复
- OS_OPT_PEND_NON_BLOCKING:不阻塞等待任务信号量,如果任务等待时间超过设定的超时时间,任务会恢复并返回一个错误代码
UCOSIII任务信号量例程
下列例程中,任务1会每隔1秒向任务2发送任务信号量,任务2则阻塞等待信号量。
/*
*********************************************************************************************************
* 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 > 0uOSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif#ifdef CPU_CFG_INT_DIS_MEAS_ENCPU_IntDisMeasMaxCurReset();
#endif#if (APP_CFG_SERIAL_EN == DEF_ENABLED)App_SerialInit(); /* Initialize Serial communication for application ... */
#endifOSTaskCreate((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);elseprintf("%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);elseprintf("%s Create Error\r\n",APPTASK2NAME);OSTaskDel ( & AppTaskStartTCB, & err ); }static void AppTask1 (void *p_arg)
{OS_ERR err;while(DEF_TRUE){OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次OSTaskSemPost(&AppTask2TCB,OS_OPT_POST_NONE,&err); // 向TASK2发送任务信号量if(err == OS_ERR_NONE)printf("Task1 Sem Post Success\r\n");elseprintf("Task1 Sem Post Error\r\n");}}
static void AppTask2 (void *p_arg)
{OS_ERR err;while(DEF_TRUE){OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err); // 阻塞等待任务信号量if(err == OS_ERR_NONE)printf("Task2 Get Sem Success \r\n");elseprintf("Task1 Get Sem Error\r\n");}}