イベントフラグ・グループの通知タスクを使用してFreeRTOSタスクの通知

ディレクトリ

プロパティ

アプリケーションの制限

イベントフラグ・グループとしてタスク通知

タスク通知などの利点イベントフラグ・グループ

欠点イベントフラグ・グループとしてタスク通知

APIの一部

テスト手順


プロパティ

各タスクは、タスクの割り当て通知の32ビット値は、タスクの通知を受信タスクのブロックを解除するために、イベントの任務に直接送信されています。

タスクの通知は、次の4つの方法により通知タスク値を更新することができます。

受信した通知タスクの設定値(前の値を上書きしません)。

受信したジョブの通知設定値(前の値を上書きします)。

1を設定する以上の仕事の通知値を受け取ります。

受信した通知タスクの値を増やします。

それが代わりに使用されたときに通知タスクの柔軟性に起因は、セマフォを数える、単一のキューの使用、バイナリ信号の量を必要とするかもしれない、イベントフラグがセット。使用タスク通知ロックを解除するためにタスク45%以上よりも高速道、およびラムの少ないが必要です。 

アプリケーションの制限

  1. タスクがイベントを受け取る唯一のものである場合は、タスクの通知にのみ使用することができます。
  2. 通知タスクキューの代わりに使用することができます待機中のタスクの状態をブロックすることにより通知することができ、タスクを受け、タスクが送信されない場合でも、伝送状態をブロックしてはいけません。

イベントフラグ・グループとしてタスク通知

xTaskNotifyWait()             xEventGroupWaitBitsの代わりに使用されています()

xTaskNotify()xEventGroupSetBitsの代わりに使用されています()

xTaskNotifyFromISR()xEventGroupSetBitsFromISRの代わりに使用されています()

タスク通知などの利点イベントフラグ・グループ

完全ISRに実装xEventGroupSetBitsFromISR()、xTaskNotifyFromISR()、顕著な性能上の利点を有しているxTaskNotifyFromISRので()、及びxEventGroupSetBitsFromISRと比較して()RTOSタスクデーモン何らかの処理を遅延させなければなりません。

欠点イベントフラグ・グループとしてタスク通知

ビットは、判断の組み合わせがある場合、ブロッキング状態を残して、マッチした追加の裁判官を必要がある場合にタスクの通知は、裁判官の位置を組み合わせることはできません。

APIの一部

xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
//发送任务通知,参数xTaskToNotify是发向的任务句柄,ulValue是发送的任务通知值,eAction 是发送的形式
xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, 
uint32_t ulValue, 
eNotifyAction eAction, 
BaseType_t *pxHigherPriorityTaskWoken );//同上,用于中断函数中

xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, 
uint32_t ulBitsToClearOnExit, 
uint32_t *pulNotificationValue, 
TickType_t xTicksToWait );
//接收任务通知,参数ulBitsToClearOnEntry表示读取之前是否清除,设置为0xffffffff将会清除
//参数ulBitsToClearOnExit表示读取之后是否清楚,设置为0xffffffff将会清除
//参数pulNotificationValue用于获取任务通知值
//参数xTicksToWait表示阻塞时间 

タスク通知フォームはeNotifyActionを送りました

/* Actions that can be performed when vTaskNotify() is called. */
typedef enum
{
    eNoAction = 0,/* Notify the task without updating its notify value. */
    eSetBits,	                //设置位
    eIncrement,	                //增加任务通知值
    eSetValueWithOverwrite,     //覆盖的方式设置任务通知值
    eSetValueWithoutOverwrite	//不覆盖的方式设置任务通知值
} eNotifyAction;

テスト手順

全体的な設計:二つのタスク、割り込み

時間タスク50の送信通知をカウントし、カウントし:counttask

serialtask:获取任务通知,并判断是何种事件

串口中断:收到数据之后,发送任务通知

创建任务

#define COUNT_TASK_PRIO			    1	 //任务优先级
#define COUNT_TASK_STK_SIZE 		    80   //任务堆栈大小
TaskHandle_t CountTaskHandler;                   //任务句柄
void CountTaskFunc(void *pvParameters);          //任务函数

#define SERIAL_TASK_PRIO		    4	 //任务优先级
#define SERIAL_TASK_STK_SIZE 		    80   //任务堆栈大小
TaskHandle_t SerialTaskHandler;                  //任务句柄
void SerialTaskFunc(void *pvParameters);         //任务函数

#define BIT_0   1<<0
#define BIT_1   1<<1
#define BIT_2   1<<2

void OtherTest(void )
{
    BaseType_t ret;
	
    BoardInitMcu();
    BoardInitPeriph();
		
    ret=xTaskCreate( (TaskFunction_t )CountTaskFunc,     	
		     (const char*    )"counttask",   	
		     (uint16_t       )COUNT_TASK_STK_SIZE, 
		     (void*          )NULL,				
		     (UBaseType_t    )COUNT_TASK_PRIO,	
		     (TaskHandle_t*  )&CountTaskHandler); 
	
    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  CountTaskFunc(void *pvParameters)
{
    static uint8_t i;
	
    for(;;)
    {
	i++;
		
	printf("count =%d\r\n",i);

	if(i==50)
	{
	    i=0;

	    xTaskNotify( SerialTaskHandler, BIT_1, eSetBits );
	}
						
        vTaskDelay(500);                     //延时500ms,也就是500个时钟节拍	
    }
}

void SerialTaskFunc(void *pvParameters)
{
    BaseType_t ret;
    uint32_t pulNotificationValue;
	
    for(;;)
    {
	ret= xTaskNotifyWait(0,   //读取之前,设置相应的位,0:不设置,ffffffffff:设置所有的位                  
			0xffffffff,     //读取之后,清除相应的位
	     &pulNotificationValue, 	//读取到的值
	                        10);  //阻塞时间
	
        if(ret==pdPASS)
        {
	    if((pulNotificationValue&BIT_0)==BIT_0)
	    {
	        printf("serial \r\n");
	    }
	    else
	    {
	        if((pulNotificationValue&BIT_1)==BIT_1)
	        {
		    printf("count \r\n");
	        }
	        else
	        {
		    printf("default");
	        }
	    }
        }
        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);
 	
	/*任务通知用作事件标志组*/
	xTaskNotifyFromISR( SerialTaskHandler, 
                                       (1<<0), 
                                     eSetBits,     
                   &pxHigherPriorityTaskWoken);
	portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
    }
}

运行结果

与使用事件标志组是一样的。

 

发布了35 篇原创文章 · 获赞 25 · 访问量 1万+

おすすめ

転載: blog.csdn.net/freemote/article/details/104413285