如何做自己网站平台,电商设计的前景,网站推广文章 优帮云,点开文字进入网站是怎么做的从v8.2.0版本开始#xff0c;FreeRTOS新增了任务通知这个功能#xff0c;可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西#xff0c;使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项#xff0c;要使用任务通知的话就需要将宏configUSE_T…从v8.2.0版本开始FreeRTOS新增了任务通知这个功能可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项要使用任务通知的话就需要将宏configUSE_TASK_NOTIFICATIONS定义为1 。FreeRTOS的每个任务都有一个32位的通知值任务控制块中的成员变量ulNotifiedValue就是这个通知值。任务通知是一个事件可以提高速度减少RAM的使用但是任务通知也是有限的FreeRTOS的任务通知只能有一个接收任务接收任务可以因为任务通知而进入阻塞态但是发送任务不会因为任务通知发送失败而阻塞。
0x01 发送任务通知
任务通知函数有6个
xTaskNotify
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );TaskHandle_t xTaskToNotify 任务句柄指定任务通知是发送给那个任务的uint32_t ulValue任务通知值eNotifyAction eAction任务通知更新的方法是一个枚举类型
typedef enum
{eNoAction 0, /* Notify the task without updating its notify value. */eSetBits, /* Set bits in the tasks notification value.更新指定的bit */eIncrement, /* Increment the tasks notification value.通知值加1 */eSetValueWithOverwrite, /* Set the tasks notification value to a specific value even if the previous value has not yet been read by the task. 覆写的方式更新通知值*/eSetValueWithoutOverwrite /* Set the tasks notification value if the previous value has been read by the task.不覆写通知值 */
} eNotifyAction;xTaskNotifyFromISR
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );BaseType_t *pxHigherPriorityTaskWoken退出此函数是否要进行任务切换
xTaskNotifyGive
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );TaskHandle_t xTaskToNotify指定通知是发送给那个任务的
vTaskNotifyGiveFromISR
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );xTaskNotifyAndQuery
xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t*pulPreviousNotificationValue);TaskHandle_t xTaskToNotify任务句柄指定任务通知是发送给那个任务的uint32_t ulValue任务通知值eNotifyAction eAction任务通知更新方法uint32_t* pulPreviousNotificationValue用来保存更新前的任务通知值
xTaskNotifyAndQueryFromISR
xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t*pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken);0x02 获取任务通知
获取任务通知的函数有两个
ulTaskNotifyTake()获取任务通知可以设置在退出此函数的时候将任务通知值清理或者减1.当任务通知用作二值信号量或者计数信号量的时候使用此函数来获取信号量。xTaskNotifyWait()等待任务通知比ulTaskNotifyTake更为强大全功能版任务通知获取函数
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )BaseType_t xClearCountOnExit为pdFALSE的话在退出函数的时候任务通知值减1类似计数型信号量当为pdTRUE的话在退出函数的时候任务通知清零类似二值信号量TickType_t xTicksToWait阻塞时间
返回值任务通知值减少值或者清零之前的值
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )uint32_t ulBitsToClearOnEntry当没有接收到任务通知的时候将任务通知与此参数的取反值进行按位与运算当此参数为0xffffffff或者ULONG_MAX的时候就会将任务通知值清零uint32_t ulBitsToClearOnExit如果接收到了任务通知在做完相应的处理退出函数之前将任务通知与此参数的取反值进行按位与运算当此参数为0xffffffff或者ULONG_MAX的时候就会将任务通知值清零uint32_t *pulNotificationValue此参数来保存任务通知值TickType_t xTicksToWait 阻塞时间
返回值 pdTRUE获取了任务通知 pdFALSE任务通知获取失败
实验 任务通知模拟二值信号量
获取任务通知值如果获取到的话则进行逻辑处理
//DataProcess_task函数
void DataProcess_task(void *pvParameters)
{u8 len0;u8 CommandValueCOMMANDERR;u32 NotifyValue;u8 *CommandStr;POINT_COLORBLUE;while(1){NotifyValueulTaskNotifyTake(pdTRUE,portMAX_DELAY); //获取任务通知if(NotifyValue1) //清零之前的任务通知值为1说明任务通知有效{lenUSART_RX_STA0x3fff; //得到此次接收到的数据长度CommandStrmymalloc(SRAMIN,len1); //申请内存sprintf((char*)CommandStr,%s,USART_RX_BUF);CommandStr[len]\0; //加上字符串结尾符号LowerToCap(CommandStr,len); //将字符串转换为大写 CommandValueCommandProcess(CommandStr); //命令解析if(CommandValue!COMMANDERR){LCD_Fill(10,90,210,110,WHITE); //清除显示区域LCD_ShowString(10,90,200,16,16,CommandStr); //在LCD上显示命令printf(命令为:%s\r\n,CommandStr);switch(CommandValue) //处理命令{case LED1ON: LED10;break;case LED1OFF:LED11;break;case BEEPON:BEEP0;break;case BEEPOFF:BEEP1;break;}}else{printf(无效的命令请重新输入!!\r\n);}USART_RX_STA0;memset(USART_RX_BUF,0,USART_REC_LEN); //串口接收缓冲区清零myfree(SRAMIN,CommandStr); //释放内存}else {vTaskDelay(10); //延时10ms也就是10个时钟节拍 }}
}接收到了数据发送任务通知vTaskNotifyGiveFromISR的第一个参数是DataProcess_task任务的任务句柄DataProcess_Handler
//串口1中断服务程序
void USART1_IRQHandler(void)
{ u32 timeout0;u32 maxDelay0x1FFFF;BaseType_t xHigherPriorityTaskWoken;HAL_UART_IRQHandler(UART1_Handler); //调用HAL库中断处理公用函数timeout0;while (HAL_UART_GetState(UART1_Handler) ! HAL_UART_STATE_READY)//等待就绪{timeout;超时处理if(timeoutmaxDelay) break; }timeout0;while(HAL_UART_Receive_IT(UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) ! HAL_OK)//一次处理完成之后重新开启中断并设置RxXferCount为1{timeout; //超时处理if(timeoutmaxDelay) break; }//发送任务通知if((USART_RX_STA0x8000)(DataProcess_Handler!NULL))//接收到数据并且接收任务通知的任务有效{vTaskNotifyGiveFromISR(DataProcess_Handler,xHigherPriorityTaskWoken);//发送任务通知portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换}
}