关于任务通知特点、优缺点:FreeRTOS任务通知
关于计数信号量的特点、本质:FreeRTOS计数信号量使用
ulTaskNotifyTake() 替代 xSemaphoreTake()
其中参数xClearOnExit需要设置为pdFALSE,读取任务通知值后任务通知值每次减1
xTaskNotifyGive() 替代 xSemaphoreGive()
vTaskNotifyFromISR 替代 xSemaphoreGiveFromISR()
API说明
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
//发送任务通知,返回值永远是pdTRUE参数xTaskToNotify是任务句柄,既要发向的任务
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
//同上,用于中断中
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
//获取任务通知,返回值是任务通知值,参数xClearCountOnExit为pdTRUE表示用作二值信号量,为pdFALSE表示用作计数信号量
测试程序
总体设计:2个任务,1个中断。
printcounttask:仅仅打印当前计数;
serialtask:获取计数信号量,并打印获取之后的计数信号量的值;
串口中断:接收到串口数据后,给一个信号量。
创建任务
#define PRINT_COUNT_TASK_PRIO 1 //任务优先级
#define PRINT_COUNT_TASK_STK_SIZE 80 //任务堆栈大小
TaskHandle_t PrintCountTaskHandler; //任务句柄
void PrintCountFunc(void *pvParameters); //任务函数
#define SERIAL_TASK_PRIO 4 //任务优先级
#define SERIAL_TASK_STK_SIZE 80 //任务堆栈大小
TaskHandle_t SerialTaskHandler; //任务句柄
void SerialTaskFunc(void *pvParameters); //任务函数
void OtherTest(void )
{
BaseType_t ret;
BoardInitMcu();
BoardInitPeriph();
ret=xTaskCreate((TaskFunction_t )PrintCountFunc,
(const char* )"printcount",
(uint16_t )PRINT_COUNT_TASK_STK_SIZE,
(void* )NULL,
(UBaseType_t )PRINT_COUNT_TASK_PRIO,
(TaskHandle_t* )&PrintCountFunc);
ret=xTaskCreate((TaskFunction_t )SerialTaskFunc,
(const char* )"serialtask",
(uint16_t )SERIAL_TASK_STK_SIZE,
(void* )NULL,
(UBaseType_t )SERIAL_TASK_PRIO,
(TaskHandle_t* )&SerialTaskHandler);
vTaskStartScheduler();
}
各个任务
void PrintCountFunc(void *pvParameters)
{
char string[21] = {0};
static uint8_t i=0;
for(;;)
{
i++;
sprintf(string, "%03d ", i);
printf(" %d\r\n",i);
dis_string(1,0,(uint8_t *)string,1);
vTaskDelay(500);
}
}
void SerialTaskFunc(void *pvParameters)
{
uint32_t tasknotifyvalue ;
for(;;)
{
tasknotifyvalue= ulTaskNotifyTake( pdFALSE, 100);
if(tasknotifyvalue)
{
printf("semaphore counting =%d\r\n",(tasknotifyvalue-1));
vTaskDelay(1000); //延时1000ms,也就是1000个时钟节拍
}
else
{
vTaskDelay(10);
}
}
}
串口中断
void USART1_IRQHandler( void )
{
BaseType_t pxHigherPriorityTaskWoken=pdFALSE;
//幅度有限,省略部分代码,仅列出主要代码
if(RESET != __HAL_UART_GET_FLAG(&UartHandle,UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&UartHandle);
/*任务通知用作二值信号量*/
vTaskNotifyGiveFromISR( SerialTaskHandler, &pxHigherPriorityTaskWoken );
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
}
}
运行结果