μC/OS-II系统中事件标志的使用

以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接:https://doc.micrium.com/display/ucos/

编译环境:Atollic TrueSTUDIO for STM32 9.3.0

硬件:基于STM32F103VET6单片机(使用HAL库)

一、介绍

  要启用μC/OS-II事件服务,必须在OS_CFG.H中设置配置常量。当OS_FLAG_EN设置为0时,事件标志服务被禁止;当OS_FLAG_EN设置为1时, 事件标志服务被启用。

  μC/OS-II事件标志由两个元素组成:一个(8bit、16bit或32bit)用于保存组中事件的当前状态;一个用于等待这些位的组合被设置(1)或清除(0)的任务列表。

  下图显示了一个流程图来说明任务和事件之间的关系。事件既能够由任务发出,也能够由中断发出;同样任务和中断都能接收事件。但创建和删除只能由任务完成。

 

二、创建一个事件标志组,OSFlagCreate()

  事件标志需要创建才能被使用,通过调用OSFlagCreate()函数创建,并指定存储在事件标志组中的初始值。函数原型为:

  1、OS_FLAG_GRP  *OSFlagCreate (OS_FLAGS flags, INT8U *err):

  • flags是包含要存储在事件标志组中的初始值;
  • err保存错误类型;
  • 返回与标志组相关联的指针。

三、置位或清除事件在一个事件标志组中,OSFlagPost()

  设置或清除事件标志组中的位,函数原型为:

  1、OS_FLAGS  OSFlagPost (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *err):

  • pgrp是指向所需事件标志组的指针;
  • flags如果'opt'是OS_FLAG_SET,则在'flags'中设置的每个位将在事件标志组中被置位;如果'opt'是OS_FLAG_CLR,则在'flags'中设置的每个位将被清除;
  • opt标志位的状态;
  • err保存错误类型。

四、在一个事件标志组中等待事件,OSFlagPend()

  等待事件标志组的事件,函数原型为:

  1、OS_FLAGS  OSFlagPend (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err):

  • pgrp是指向所需事件标志组的指针
  • flags指定您希望等待哪个位(即标志)。您需要的位通过在“flags”中设置相应的位来指定。例如,如果你的应用程序想要等待位0和1,那么“标志”将包含0x03。
  • wait_type你指定的所有位被置位还是其中一个为被置位(如果你想等待到事件标志,对应的位被清零,还需要添加OS_FLAG_CONSUME);
  • timeout等待时长(如果是0将一直等下去);
  • err 保存错误类型。

五、示例代码(非中断方式)

  1、开启事件标志服务的相关的配置

 

#define OS_FLAG_EN                1    /* Enable (1) or Disable (0) code generation for EVENT FLAGS    */
#define OS_FLAG_ACCEPT_EN         1    /*     Include code for OSFlagAccept()                          */
#define OS_FLAG_DEL_EN            1    /*     Include code for OSFlagDel()                             */
#define OS_FLAG_NAME_EN           1    /*     Enable names for event flag group                        */
#define OS_FLAG_QUERY_EN          1    /*     Include code for OSFlagQuery()                           */
#define OS_FLAG_WAIT_CLR_EN       1    /* Include code for Wait on Clear EVENT FLAGS                   */
#define OS_FLAGS_NBITS           16    /* Size in #bits of OS_FLAGS data type (8, 16 or 32)            */

 

 

 

  2、定义一个事件标志组指针:

/* 定义一个事件标志组 */
OS_FLAG_GRP *FlagStat;

  3、创建事件标志组:

/* 创建事件标志组 */
FlagStat = OSFlagCreate(0x0, &err);

  4、在两个任务中分别发送事件标志:

static void AppTask1(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
        {
            /* 设置bit0为1 */
            OSFlagPost(FlagStat, 0x01, OS_FLAG_SET, &err);
        }
        OSTimeDlyHMSM(0, 0, 0, 100);
    }
}

static void AppTask2(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)
        {
            /* 设置bit1 为1 */
            OSFlagPost(FlagStat, 0x02, OS_FLAG_SET, &err);
        }
        OSTimeDlyHMSM(0, 0, 0, 100);
    }
}

  5、在一个任务中等待两个事件标志:

static void AppTaskLed(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        /* 等待bit0和bit1 都被置位,因为添加OS_FLAG_CONSUME,当等到事件标志会被相应的位会被清零 */
        OSFlagPend(FlagStat, 0x03, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 0, &err);
        if(err == OS_ERR_NONE)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
        }
    }
}

六、示例代码(中断方式)

  1、开启事件标志服务的相关的配置:

#define OS_FLAG_EN                1    /* Enable (1) or Disable (0) code generation for EVENT FLAGS    */
#define OS_FLAG_ACCEPT_EN         1    /*     Include code for OSFlagAccept()                          */
#define OS_FLAG_DEL_EN            1    /*     Include code for OSFlagDel()                             */
#define OS_FLAG_NAME_EN           1    /*     Enable names for event flag group                        */
#define OS_FLAG_QUERY_EN          1    /*     Include code for OSFlagQuery()                           */
#define OS_FLAG_WAIT_CLR_EN       1    /* Include code for Wait on Clear EVENT FLAGS                   */
#define OS_FLAGS_NBITS           16    /* Size in #bits of OS_FLAGS data type (8, 16 or 32)            */

 

   2、定义一个事件标志组指针:

/* 定义一个事件标志组 */
OS_FLAG_GRP *FlagStat;

  3、创建事件标志组:

/* 创建事件标志组 */
FlagStat = OSFlagCreate(0x0, &err);

  4、中断函数中进行针对μC/OS系统的处理:

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
#if uCOS_EN == 1

#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
    OS_CPU_SR   cpu_sr = 0u;
#endif

    OS_ENTER_CRITICAL();
    OSIntEnter();
    OS_EXIT_CRITICAL();
#endif

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

#if uCOS_EN == 1
    OSIntExit();
#endif

}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
#if uCOS_EN == 1

#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */
    OS_CPU_SR   cpu_sr = 0u;
#endif

    OS_ENTER_CRITICAL();
    OSIntEnter();
    OS_EXIT_CRITICAL();
#endif

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);

#if uCOS_EN == 1
    OSIntExit();
#endif
}

  5、在中断的回调函数中发送事件标志,针对不同端口引脚被触发发送不同的事件标志:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    INT8U err;

    if(GPIO_Pin == GPIO_PIN_0)
    {
        OSFlagPost(FlagStat, 0x01, OS_FLAG_SET, &err);
    }

    if(GPIO_Pin == GPIO_PIN_13)
    {
        OSFlagPost(FlagStat, 0x02, OS_FLAG_SET, &err);
    }
}

  6、在一个任务去接收中断发出的事件标志:

static void AppTaskLed1(void *p_arg)
{
    INT8U err;

    (void)p_arg;

    while(1)
    {
        OSFlagPend(FlagStat, 0x03, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 0, &err);
        if(err == OS_ERR_NONE)
        {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
        }
    }
}

 

#endif

posted @ 2020-10-18 13:26  不要让自己太懒  阅读(1643)  评论(0编辑  收藏  举报