【FreeRtos教程八】STM32 CubeMx——Task Notifications(任务通知)

目录

1 任务通知

2 示例程序

2.1 例程功能

2.2 步骤

2.3 实验结果

2.4 函数讲解

2.5 程序源码


1 任务通知

1. 基本概念

我们之前讲过消息队列、信号量、互斥量、事件组,它们都可以实现任务间的通信和同步。本节我们讲解任务通知(Task Notifications),它是freeRTOS中实现的另一种通信和同步的方法,在一定程度上可以代替信号量、消息队列、事件标志组的功能;而且任务通知所需要的资源更少、执行速度更快。

freeRTOS的任务通知,和信号量、消息队列、事件标准组一样,也是一种可以阻塞任务的事件。 每个任务对应有一个任务通知,任务可以在等待自己对应的任务通知时被阻塞,向该任务通知发送通知可以唤醒该任务;

任务通知的值,就是任务控制块结构体中的变量ulNotifiedValue,32bit;这也说明了任务通知是和任务一一对应的; 更新任务通知的值ulNotifiedValue,可以有多种方式:覆盖旧通知值、(如果上次未处理则)不覆盖旧通知值、更新任务通知的某几个bit、增加任务通知值。

灵活运用更新任务通知值的方法,可以使任务通知实现信号量、消息队列、事件标志组等的功能。 例如:向某个任务发送一个信号量,可以通过将该任务的通知值加1实现;获取信号量,可以将该任务的通知值减1实现; 向某个任务的通知值中写入一个数据,相对于向该任务发送了一个长度为1的消息; 设置某个任务通知值的bit0~bit31,可以实现事件标志组。

2.任务通知的优势与限制

任务通知实现的信号量、消息队列、事件标志组,比之前讲过的实现方法占用内存更少、执行速度更快;但是使用时有一些限制:

  • 不能同时使用任务通知来广播给多个任务,也就是说同一时间对于某个任务,只能实现一个“信号量”或“消息队列”或“事件标志组”的作用;
  • 使用任务通知时,不支持发送信息的超时等待(即发送方不可超时等待,这一点和之前讲过的信号量、消息队列、事件标志组不同,它们是可以支持超时等待的)。

2 示例程序

2.1 例程功能

创建两个按键任务,按键按下即发送一个任务通知;创建一个打印任务,等待发送任务通知并判断那一位为1。

2.2 步骤

 配置两个按键IO口

 配置两个按键任务和一个打印任务

定义两个位

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define BIT_1 (1<<1)
#define BIT_2 (1<<2)
/* USER CODE END PD */

按键KEY0按下,给myTask01发送任务通知

/* USER CODE END Header_StartTask_KEY0 */
void StartTask_KEY0(void const * argument)
{
  /* USER CODE BEGIN StartTask_KEY0 */
  /* Infinite loop */
  for(;;)
  {
    if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0)
    {
        osDelay(10);
        if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0)
        {
            osThreadSuspendAll();
            printf("KEY0按下 \n");
            osThreadResumeAll();
            osSignalSet(myTask01Handle,BIT_1);
            //xTaskNotifyGive(myTask01Handle);  //FreeRtos源码函数
            while(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0)
            {
                osDelay(10);
            }
        }
    }
      osDelay(1);
  }
  /* USER CODE END StartTask_KEY0 */
}

按键KEY1按下,给myTask01发送任务通知

/* USER CODE END Header_StartTask_KEY1 */
void StartTask_KEY1(void const * argument)
{
  /* USER CODE BEGIN StartTask_KEY1 */
  /* Infinite loop */
  for(;;)
  {
    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
    {
        osDelay(10);
        if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
        {
            osThreadSuspendAll();
            printf("KEY1按下 \n");
            osThreadResumeAll();
            osSignalSet(myTask01Handle,BIT_2);
            while(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
            {
                osDelay(10);
            }
        }
    }
      osDelay(1);
  }
  /* USER CODE END StartTask_KEY1 */
}

接收任务通知,并判断哪一位被置1打印字符串

/* USER CODE END Header_StartTask01 */
void StartTask01(void const * argument)
{
  /* USER CODE BEGIN StartTask01 */
  /* Infinite loop */
    osEvent event;
  for(;;)
  {
      event=osSignalWait(BIT_1|BIT_2,osWaitForever);
      if(event.value.signals&BIT_1)
      {
          printf("BIT_1 发生 \n");
      }
      if(event.value.signals&BIT_2)
      {
          printf("BIT_2 发生 \n");
      }
      //ulTaskNotifyTake(pdFALSE,portMAX_DELAY); //FreeRtos源码函数
      //printf("事件发生");
      osDelay(1);
  }
  /* USER CODE END StartTask01 */
}

2.3 实验结果

  • 按键1被按下,打印“BIT_1 发生”
  • 按键2被按下,打印“BIT_2 发生”

2.4 函数讲解

1 int32_t osSignalSet (osThreadId thread_id, int32_t signal)

/**
* @brief  Set the specified Signal Flags of an active thread.
* @param  thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
* @param  signals       specifies the signal flags of the thread that should be set.
* @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
* @note   MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
*/
int32_t osSignalSet (osThreadId thread_id, int32_t signal)
  • 函数功能:发送任务通知
  • 传入参数:thread_id(任务句柄) signal(被置1的位)

2 osEvent osSignalWait (int32_t signals, uint32_t millisec)

/**
* @brief  Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
* @param  signals   wait until all specified signal flags set or 0 for any single signal flag.
* @param  millisec  timeout value or 0 in case of no time-out.
* @retval  event flag information or error code.
* @note   MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
*/
osEvent osSignalWait (int32_t signals, uint32_t millisec)
  • 函数功能:接收任务通知
  • 传入参数:signal(要等待的被置1的位)millisec(超时等待时间)

2.5 程序源码

github链接:HaoJosephWen/FreeRtos_personal (github.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值