汕头站扩建工程,河北助手app下载,如何获得网站后台密码,公司网站设计图片任务通知简介
任务通知#xff1a;用来通知任务的#xff0c;任务控制块中的结构体成员变量ulNotifiedValue#xff08;32位#xff09;就是这个通知值。 #if( configUSE_TASK_NOTIFICATIONS 1 )volatile uint32_t ulNotifiedValue;volatile uint8_t ucNotifyState;#endi…任务通知简介
任务通知用来通知任务的任务控制块中的结构体成员变量ulNotifiedValue32位就是这个通知值。 #if( configUSE_TASK_NOTIFICATIONS 1 )volatile uint32_t ulNotifiedValue;volatile uint8_t ucNotifyState;#endif任务控制块TCB里有两个成员变量一个uint32_t的表示通知值一个uint8_t的用来表示通知状态。
使用队列、信号量、事件标志组时都需要另外创建一个结构体通过中间的结构体进行间接通信。使用任务通知时任务结构体TCB中就包含了内部对象可以直接接收别人发过来的通知。
任务通知值的更新方式
不覆盖接收任务的通知值覆盖接收任务的通知值更新接收任务通知值的一个或多个bit增加接收任务的通知值
只要合理灵活的利用任务通知的特点可以在一些场合中替代队列、信号量和事件标志组。
任务通知的优势
效率更高使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多。使用内存更小使用任务通知时无需额外创建结构体
任务通知的劣势
无法发送数据给ISRISR没有任务结构体所以无法给ISR发送数据。但是ISR可以使用任务通知发数据给任务。无法广播给多个任务任务通知只能是被指定的一个任务接收并处理。无法缓存多个数据任务结构体中只有一个任务通知值只能保存一个数据。发送受阻不支持阻塞发送发无法进入阻塞状态等待。
任务通知状态
#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )任务未等待通知任务通知默认的初始化状态等待通知接收方已经准备好了调用了接收任务通知函数等待发送方发给个通知等待接收发送方已经发送出去调用了发送任务通知函数等待接收方接收
任务通知相关API函数介绍
发送通知
函数描述xTaskNotify发送通知带有通知值xTaskNotifyAndQuery发送通知带有通知值并且保留接收任务的原有通知值xTaskNotifyGive发送通知不带通知值xTaskNotifyFromISRxTaskNotifyAndQueryFromISRvTaskNotifyGiveFromISR
接收通知
函数描述ulTaskNotifyTake获取任务通知可以设置在退出该函数的时候将任务通知值清零或者减一。xTaskNotifyWait获取任务通知可获取通知值和清除通知值的指定位
当任务通知用作于信号量时使用ulTaskNotifyTake函数获取信号量。当任务用作于事件标志组或队列时使用xTaskNotifyWait函数来获取。
模拟二值信号量和计数信号量
void StartMyTask1(void *argument)
{printf(StartMyTask1\r\n);uint32_t notify_value 0;for(;;){//这里实际是取通知值只要通知值大于0的时候就不会阻塞可以执行到下面//第一个参数设置为true表示执行完该函数后会将通知值设置为0//这意味着如果再没有接收通知那么会一直阻塞在这里。//函数返回值表示通知值再设置为0之前的值一般情况下为1notify_value ulTaskNotifyTake(pdTRUE,portMAX_DELAY);if(0 ! notify_value)printf(task1 notify_value%d\r\n,notify_value);vTaskDelay(pdMS_TO_TICKS(500));//500ms}
}void NotifyMyTask1FromISR()
{printf(NotifyMyTask1FromISR\r\n);BaseType_t xHigherPriorityTaskWoken pdFALSE;//这里是在中断服务函数中调用的vTaskNotifyGiveFromISR(myTask1Handle,xHigherPriorityTaskWoken);portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
NotifyMyTask1FromISR
task1 notify_value2
NotifyMyTask1FromISR
NotifyMyTask1FromISR
task1 notify_value2
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
NotifyMyTask1FromISR
NotifyMyTask1FromISR
task1 notify_value3
NotifyMyTask1FromISR
NotifyMyTask1FromISR
NotifyMyTask1FromISR
task1 notify_value3可以看到正常情况下执行一次NotifyMyTask1FromISR就会执行一次ulTaskNotifyTake。但是如果NotifyMyTask1FromISR函数执行的频率很快ulTaskNotifyTake函数执行不过来所以通知值不是1执行通知函数的时候实际上是将通知值加一ulTaskNotifyTake函数执行一次后还是会阻塞因为执行一次后将通知值设置为0了。如果将ulTaskNotifyTake函数的第一个参数设置为pdFALSE表示执行完后将通知值减一这样其实就是模拟计数信号量了。
void StartMyTask1(void *argument)
{printf(StartMyTask1\r\n);uint32_t notify_value 0;for(;;){//这里实际是取通知值只要通知值大于0的时候就不会阻塞可以执行到下面//第一个参数设置为false表示执行完该函数后会将通知值减1//函数返回值表示通知值在减1之前的值notify_value ulTaskNotifyTake(pdFALSE,portMAX_DELAY);if(0 ! notify_value)printf(task1 notify_value%d\r\n,notify_value);vTaskDelay(pdMS_TO_TICKS(500));//500ms}
}NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
NotifyMyTask1FromISR
NotifyMyTask1FromISR
task1 notify_value3
task1 notify_value2
task1 notify_value1模拟消息邮箱
void NotifyMyTask1FromISR(uint32_t notify_value)
{printf(NotifyMyTask1FromISR\r\n);BaseType_t xHigherPriorityTaskWoken pdFALSE;//这里是在中断服务函数中调用的//将参数值当作通知值发送给任务xTaskNotifyFromISR(myTask1Handle,notify_value,eSetValueWithOverwrite,xHigherPriorityTaskWoken);portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}void StartMyTask1(void *argument)
{printf(StartMyTask1\r\n);uint32_t notify_value 0;for(;;){//第一个参数表示接收前不清零通知值的bit//第二个参数表示接收后清零通知值的所有bitxTaskNotifyWait(0x00,0xFFFFFFFF,notify_value,portMAX_DELAY);printf(task1 notify_value%d\r\n,notify_value);vTaskDelay(pdMS_TO_TICKS(500));//500ms}
}NotifyMyTask1FromISR
task1 notify_value1
NotifyMyTask1FromISR
task1 notify_value2
NotifyMyTask1FromISR
task1 notify_value3
NotifyMyTask1FromISR
task1 notify_value4可以将参数作为通知值传递给任务。
模拟时间标志组
void NotifyMyTask1FromISR(uint32_t notify_value)
{//notify_value表示第几位设置为1其实可以一次设置多位这里不演示//notify_value 2则表示第二位置1那么通知值 (12)printf(NotifyMyTask1FromISR\r\n);BaseType_t xHigherPriorityTaskWoken pdFALSE;//模拟事件标志组其实就是利用通知值的每一位作为事件的Flag//发送和接收的时候都只是修改和判断对应bitxTaskNotifyFromISR(myTask1Handle,1notify_value,eSetBits,xHigherPriorityTaskWoken);portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}void StartMyTask1(void *argument)
{printf(StartMyTask1\r\n);uint32_t notify_value 0;for(;;){//第一个参数表示接收前不清零通知值的bit//第二个参数表示接收后清零通知值的所有bitxTaskNotifyWait(0x00,0xFFFFFFFF,notify_value,portMAX_DELAY);printf(task1 notify_value%d\r\n,notify_value);if((notify_value (10)) ! 0){printf(bit0 event... \r\n);}else if((notify_value (11)) ! 0){printf(bit1 event... \r\n);}else if((notify_value (12)) ! 0){printf(bit2 event... \r\n);}vTaskDelay(pdMS_TO_TICKS(500));//500ms}
}NotifyMyTask1FromISR
task1 notify_value4
bit2 event...
NotifyMyTask1FromISR
task1 notify_value2
bit1 event...
NotifyMyTask1FromISR
task1 notify_value1
bit0 event...
NotifyMyTask1FromISR
task1 notify_value4
bit2 event... 其实关于xTaskNotifyWait函数的第二个参数准确来说不是执行完xTaskNotifyWait函数后清零比特位而是在下次给通知值赋值的时候吧