当前位置 博文首页 > freemote的博客:FreeRTOS使用任务通知作二值信号量

    freemote的博客:FreeRTOS使用任务通知作二值信号量

    作者:[db:作者] 时间:2021-07-18 16:15

    关于任务通知特点、优缺点: FreeRTOS任务通知

    关于二值信号量特点、本质:二值信号量使用

    ?ulTaskNotifyTake() ??????????? 替代 ? ? ?? xSemaphoreTake()

    xTaskNotifyGive()?????????????? 替代??????? xSemaphoreGive()

    vTaskNotifyGiveFromISR?? 替代??????? 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表示用作计数信号量

    测试程序

    总体设计:3个任务,1个中断

    lcdtask:计数,LCD显示并打印,计数到50的时候,发送任务通知给任务totaltask;

    totaltask:读取任务通知,并打印累积读取到的次数;

    serialtask:读取任务通知,并打印收到的数据;

    串口中断:空闲中断后,发送任务通知给任务serialtask。

    创建任务

    #define LCD_TASK_PRIO		              1	     //任务优先级
    #define LCD_TASK_STK_SIZE 		      80     //任务堆栈大小
    TaskHandle_t LCDTaskHandler;                         //任务句柄
    void LCDTaskFunc(void *pvParameters);                //任务函数、
    
    #define TOTAL_COUNT_TASK_PRIO		       2     //任务优先级
    #define TOTAL_COUNT_TASK_STK_SIZE 	      50     //任务堆栈大小
    TaskHandle_t TotalCountTaskHandler;                  //任务句柄
    void TotalCountTaskFunc(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 )LCDTaskFunc,     	
    		    (const char*    )"lcdtask",   	
    		    (uint16_t       )LCD_TASK_STK_SIZE, 
    		    (void*          )NULL,				
    		    (UBaseType_t    )LCD_TASK_PRIO,	
    		    (TaskHandle_t*  )&LCDTaskHandler); 
    	
        ret=xTaskCreate((TaskFunction_t )TotalCountTaskFunc,     	
    		    (const char*    )"totaltask",   	
    		    (uint16_t       )TOTAL_COUNT_TASK_STK_SIZE, 
    		    (void*          )NULL,				
    		    (UBaseType_t    )TOTAL_COUNT_TASK_PRIO,	
    		    (TaskHandle_t*  )&TotalCountTaskHandler);   
    
        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  LCDTaskFunc(void *pvParameters)
    {
        char  string[21] = {0};
        static uint8_t i=0;
    
        for(;;)
        {
    	i++;
    		
    	sprintf(string, "%03d ", i);
    	printf("count :%d\r\n",i);
    		
            dis_string(1,0,(uint8_t *)string,1);
    		
    	if(i==50)
    	{
    	    xTaskNotifyGive(TotalCountTaskHandler);
    	    i=0;
    	}
    						
            vTaskDelay(500);              //延时500ms,也就是500个时钟节拍	
        }
    }
    
    void TotalCountTaskFunc(void *pvParameters)
    {
        static uint32_t i=0;
        uint32_t tasknotifyvalue;
    	
        for(;;)
        {	
            tasknotifyvalue= ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
    		
    	if(tasknotifyvalue)
    	{
    	    i++;
    	    printf(" total :%d\r\n",i);
    	}
    	else
    	{
    	    vTaskDelay(10);
    	}
        }
    }   
    
    void SerialTaskFunc(void *pvParameters)
    {
        uint32_t tasknotifyvalue;
    
        for(;;)
        {
    	tasknotifyvalue= ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
    		
    	if(tasknotifyvalue)
    	{
    	    printf("serial:%s",SerialFrame.Buff);
    	    memset(SerialFrame.Buff,0,255);
    	    SerialFrame.Len=0;
    	}
    	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);
        }
    }

    运行结果

    ?

    cs