8.1任务通知的原理和功能 8.2任务通知相关函数 8.3示例一:使用任务通知传递数据 8.4示例二:将任务通知用作计数信号量
队列、信号量、事件组等IPC技术都需要创建一个中间对象,进程之间通过这些中间对象进行通讯或同步。创建对象就需要分配内存,占用一定内存
任务通知(TaskNotification):无需创建中间对象,进程之间直接通讯的方法 参数configUSE_TASK_NOTIFICATIONS需要设置为1才可以使用任务通知,默认值为1,可以在CubeMX中设置。 当参数configUSE_TASK_NOTIFICATIONS设置为1时,任务的任务控制块中会增加一个uint32_t类型的通知值直(NotificationValue)变量,并且任务接收通知有2种状况挂起(Pending)状态、非挂起(Not-Pending)状态
任务通知工作特点如下: 一个任务或ISR向另外一个指定的任务发送通知,将发送通知的进程称为发送者,将接收通知的进程称为接收者 发送者可以是任务或ISR,接收者只能是任务,不能是ISR 发送者发送通知时可以带有一个通知值,或者是使接收者的通知值发生改变的计算方法,例如使通知值加1。发送者只管发送通知,是否接收和处理通知由接收者去决定接收者有未处理的通知时处于挂起状态。接收者可以进入阻塞方式等待通知,接收到通知后再做处理。
任务通知有如下的一些优点: 性能更高。使用任务通知方法在进程间传递数据时,比使用队列或信号量等方法的速度快得多。 内存开销小。使用任务通知时内存开销小,因为只需在任务控制块中增加几个变量。 使用任务通知可以代替二值信号量、计数信号量、事件组可以代替只有一个存储单元的队列。任务通知使用比较灵活,而且工作效率高。
任务通知也有一些局限性,包括: 不能向ISR发送通知,只能是任务或ISR函数向任务发送通知任务通知指定了接收者,多个发送者可以向同一个接收者发送不同的通知,但是发送者不能将一个通知发送给不同的接 收者,也就是不能进行消息广播 任务通知一次只能发送或接收一个uint32_t类型的数据,不能像消息队列那样发送多个缓冲数据,因为任务控制块中只有一个uint32t类型的通知值作为数据缓存
8.21任务通知相关函数 8.2.1 7相关函数概述 8.2.2函数详解
8.2.1相关函数概述 可以在任务或IS里发送通知,但是只有任务能接收通知
函数在Task.h中
发送通知
xTaskNotify()向一个任务发送通知的函数,带有通知值,还有值的传递方式设置。适用于利用通知值直接传递数据。 xTaskNotifyFromlSR() xTaskNotifyFromISR()的ISR版本 xTaskNotifyAndQuery() 与xTaskNotify()的功能相似,但是可以返回接收者之发送前的通知值 xTaskNotifyAndQueryFromlSR() xTaskNotifyAndQuery()的ISR版本 xTaskNotifyGive()向一个任务发送通知,不带通知值,只是使接收者的通知值加1。适用于当做二值信号量或计数信号量时使用 vTaskNotifyGiveFromlSR() xTaskNotifyGive()的ISR版本
接收通知
xTaskNotifyWait() 等待并获取任务通知值的通用函数,可以设置进入和退出等待时的任务通知值的值,例如进入将通知值清零,或退出时将通知值清零 ulTaskNotifyTake()等待并获取任务通知值,可在退出时等待时将通知值减1或清零。适适用于作为二值信号量或计数信号量的场合
其他
xTaskNotifyStateClear()清除任务的等待状态,任务的通知值不变
发送和接收通知的函数可以分组两组: 通用版本的函数xTaskNotify()和xTaskNotifyWait(),可以发送任意的通知值,适合于在进程间通过通知值直接传递数据。 
适用于二值信号量和计数信号量的函数xTaskNotifyGive()和ulTaskNotifyTake(),发送时使接收者的通知值加1,接收时使通知值减1或清零, 
示例Demo8_1NotifyADC
任务通知用于传递数据 ADC采集到adc_value,然后通过通知发送adc_value 任务中,接收通知,然后输出(一直等待通知值,不用delay)
任务通知用于计数
Demo8_2NotifyCounting
8.4.1示例功能 使用函数xTaskNotifyGive()发送通知,使接收者的通知值加1, 使用函数ulTaskNotifyTake()读取通知,使通知值减1或清零 
任务通知模拟计数信号量与实际的计数信号量的细微差别: 实际的计数信号量的初始值不为零,一般用于表示可用资源的个数,例如餐厅中空余的餐桌个数 (左图) 任务通知模拟的计数信号量的初值为0,一般用于表示待处理的事件的个数,例如模拟进入餐厅的排队人数 (右图)
本节设计一个示例Demo8_2NotifyCounting,使用任务通知模拟计数信号量,表示如图所示的餐厅前排队的人数变化。 
在FreeRTOS中创建一个任务Task_Checkln,其通知值表示当前在排队的人数。 在任务Task_Checkln中连续检测KeyRight键,当KeyRight键按下时执行函数ulTaskNotifyTake()使通知值减1,表示允许1人进店,使排队人数减1。 设置RTC周期唤醒周期为2秒,在周期唤醒中断里执行函数vTaskNotifyGiveFromlSR()向任务Task_Checkln发送通知,使其通知值加1,表示又来1人加入排队的队伍。
