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

img
img

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

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

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

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

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中,任务通知是默认使能的:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5864d266c006441ab3a338706bed8596.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_19,color_FFFFFF,t_70,g_se,x_16)


### 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`是保存的接收的通知的值,如下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6fff4bfe83ea48a9bdaba8035e50afeb.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16)  
 我们看一下`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 */
}


结果如下,按照预期的结果执行:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/72f488979132485d9045e7de1682dcf6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_16,color_FFFFFF,t_70,g_se,x_16)


### 4、中断中发送通知


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



#include “cmsis_os.h”

/* USER CODE BEGIN EV */
extern osThreadId THreadHandle;
/* USER CODE END EV */

/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
time3_count++;
if(time3_count >= 10){
osSignalSet(THreadHandle,test_signal1);
time3_count = 0;
}
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */

/* USER CODE END TIM3_IRQn 1 */
}


把THread任务再次修改一下:



void StartTHread(void const * argument)
{
/* USER CODE BEGIN StartTHread */

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

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

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

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

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

片转存中…(img-ZBkx6Nb8-1715874519125)]

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值