FreeRTOS记录(五、FreeRTOS任务通知)_ossignalwait函数

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

| ulTaskNotifyTake | uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) | pdTRUE时在函数退出时将通知值清零,这种方法适用于实现二值信号量; pdFALSE时在函数退出时将通知值减 1,这种方法适用于实现计数信号量。 接收 |
| xTaskNotifyWait | BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) | 用于实现全功能版的等待任务通知,根据用户指定的参数的不同,可以灵活的用于实现轻量级的消息队列队列、二值信号量、计数信号量和事件组功能,并带有超时等待 接收 |

2、CMSIS封装后任务通知函数

在CubeMX中使用任务通知,就使用了两个函数osSignalSet发送和osSignalWait接收。

2.1 osSignalSet

根据是否在中断中使用,osSignalSet调用了xTaskGenericNotify或者xTaskGenericNotifyFromISR

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Signal Management \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*\*
\* @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)
{
#if( configUSE\_TASK\_NOTIFICATIONS == 1 ) 
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  uint32_t ulPreviousNotificationValue = 0;
  
  if (inHandlerMode())
  {
    if(xTaskGenericNotifyFromISR( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken ) != pdPASS )
      return 0x80000000;
    
    portYIELD\_FROM\_ISR( xHigherPriorityTaskWoken );
  }  
  else if(xTaskGenericNotify( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS )
    return 0x80000000;
  
  return ulPreviousNotificationValue;
#else
  (void) thread_id;
  (void) signal;

  return 0x80000000; /\* Task Notification not supported \*/ 	
#endif
}

2.2 osSignalWait

任务通知只能在任务中使用,不允许在中断中使用,osSignalWait调用xTaskNotifyWait实现:

/\*\*
\* @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)
{
  osEvent ret;

#if( configUSE\_TASK\_NOTIFICATIONS == 1 )
	
  TickType_t ticks;

  ret.value.signals = 0;  
  ticks = 0;
  if (millisec == osWaitForever) {
    ticks = portMAX_DELAY;
  }
  else if (millisec != 0) {
    ticks = millisec / portTICK_PERIOD_MS;
    if (ticks == 0) {
      ticks = 1;
    }
  }  
  
  if (inHandlerMode())
  {
    ret.status = osErrorISR;  /\*Not allowed in ISR\*/
  }
  else
  {
    if(xTaskNotifyWait( 0,(uint32_t) signals, (uint32_t \*)&ret.value.signals, ticks) != pdTRUE)
    {
      if(ticks == 0)  ret.status = osOK;
      else  ret.status = osEventTimeout;
    }
    else if(ret.value.signals < 0)
    {
      ret.status =  osErrorValue;     
    }
    else  ret.status =  osEventSignal;
  }
#else
  (void) signals;
  (void) millisec;
	
  ret.status =  osErrorOS;	/\* Task Notification not supported \*/
#endif
  
  return ret;
}

二、任务通知使用

在CubeMX中,任务通知是默认使能的:
在这里插入图片描述

1、定义通知量

在程序中定义几个通知量,我们知道任务通知是32位的,所以可以任意定义,我们测试使用了2个通知:

/\* USER CODE BEGIN EFP \*/
#define test\_signal1 1
#define test\_signal2 0xFFFFFFFE

2、任务中发送通知

在按键任务中,发送一个任务通知给温湿度读取任务,使用osSignalSet

if(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
      osDelay(10);
      if(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
        taskENTER\_CRITICAL();
        printf("K3 pushed!!,send a tasksignal to thread...\r\n");
        taskEXIT\_CRITICAL();
        osSignalSet(THreadHandle,test_signal2);
        while(HAL\_GPIO\_ReadPin(K3_GPIO_Port,K3_Pin) == 0){
          osDelay(10);
        }
      }
    }

3、接收通知

通过上文我们可以知道osSignalWait返回的类型是osEvent,所以需要定义过一个osEvent类型的变量,然后结构体变量中有一个成员v是保存的接收的通知的值,如下:
在这里插入图片描述
我们看一下osEvent结构体 :

/// Event structure contains detailed information about an event.
/// \note MUST REMAIN UNCHANGED: \b os\_event shall be consistent in every CMSIS-RTOS.
/// However the struct may be extended at the end.
typedef struct  {
  osStatus                 status;     ///< status code: event or error information
  union  {
    uint32_t                    v;     ///< message as 32-bit value
    void                       \*p;     ///< message or mail as void pointer
    int32_t               signals;     ///< signal flags
  } value;                             ///< event value
  union  {
    osMailQId             mail_id;     ///< mail id obtained by \ref osMailCreate
    osMessageQId       message_id;     ///< message id obtained by \ref osMessageCreate
  } def;                               ///< event definition
} osEvent;

所以最终 温湿度读取任务函数改为:

/\* USER CODE END Header\_StartTHread \*/
void StartTHread(void const \* argument)
{
  /\* USER CODE BEGIN StartTHread \*/
  float T=0,H=0;
  osEvent th_readevent;
  /\*128会溢出字的内存空间不够SHT21 协议读取\*/
  /\* Infinite loop \*/
  for(;;)
  {
    th_readevent = osSignalWait(test_signal2,osWaitForever);
    if(th_readevent.value.v == test_signal2){
      SHT2X\_THMeasure();
      T=(getTemperature()/100.0);
      H=(getHumidity()/100.0); 
      taskENTER\_CRITICAL();
      printf("0x%x",th_readevent.value.v);
      printf("\r\n%4.2f C\r\n%4.2f%%\r\n",T,H);
      taskEXIT\_CRITICAL();
    }
    osDelay(1);
  }
  /\* USER CODE END StartTHread \*/
}

结果如下,按照预期的结果执行:
在这里插入图片描述

4、中断中发送通知

我们在上次开启的定时器中断中,增加任务通知发送任务:

#include "cmsis\_os.h"
...


![img](https://img-blog.csdnimg.cn/img_convert/c1471a95d125c439a6c2a4b3b9e18f41.png)
![img](https://img-blog.csdnimg.cn/img_convert/2caf65ace382ec3b8c264dea4cf3f8cd.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值