Tutoriel d'introduction à FreeRTOS (concept de groupe d'événements et utilisation des fonctions)


Préface

Cet article vous apprendra ce qu'est un groupe d'événements et comment l'utiliser.

1. Concept de groupe événementiel

Un groupe d’événements est généralement une structure de données composée d’un ensemble de bits dont chacun correspond à un événement spécifique. Chaque bit peut être activé ou effacé pour indiquer que l'événement correspondant s'est produit ou ne s'est pas produit. Cette combinaison de bits forme une collection similaire à un nombre binaire, chaque bit représentant un état ou un événement spécifique. Par conséquent, le groupe d’événements peut être considéré comme une structure de données composée d’une série de bits binaires, chaque bit représentant un état d’événement indépendant.

Chaque bit du groupe d'événements peut représenter un événement ou un statut spécifique, et la tâche peut effectuer le traitement correspondant en fonction de ces événements ou statuts. En définissant ou en effaçant ces bits, la logique de traitement d'événement correspondante peut être déclenchée ou annulée. Les bits d'un groupe d'événements sont généralement utilisés pour indiquer si certains événements se sont produits, se sont terminés ou nécessitent un traitement ultérieur. Cette flexibilité fait des composants d'événement un outil puissant pour la synchronisation, la communication et la collaboration entre les tâches.

Lorsque vous utilisez des groupes d'événements, vous pouvez implémenter une gestion de tâches et un traitement d'événements complexes en manipulant des bits individuels pour représenter différents événements ou états. En réglant et en effaçant les bits de manière appropriée, les tâches peuvent être coordonnées pour répondre aux exigences spécifiques des applications. Ce contrôle au niveau bit des groupes d'événements en fait un outil efficace pour gérer la communication et la synchronisation entre les tâches.

Insérer la description de l'image ici

事件组的位数:

Si configUSE_16_BIT_TICKS est défini sur 1 (activé), le groupe d'événements comporte 16 bits, dont les 8 bits les plus élevés (du bit le plus élevé au 9ème bit) sont utilisés pour la gestion du noyau, tandis que les 8 bits inférieurs restants sont réservés à l'utilisateur. événements définis.

Si configUSE_16_BIT_TICKS est défini sur 0 (désactivé), le groupe d'événements comporte 32 bits, dont les 8 bits les plus élevés (du bit le plus élevé au bit 25) sont utilisés pour la gestion du noyau, tandis que les 24 bits inférieurs restants sont réservés aux tâches définies par l'utilisateur. événements.

2. La différence entre les groupes d'événements, les sémaphores et les files d'attente

1.事件组(Event Group):

Concept : Un groupe d'événements est une structure de données composée de plusieurs bits utilisés pour représenter l'état de plusieurs événements. Les tâches peuvent synchroniser les tâches en attendant qu'un bit spécifique ou une combinaison de bits dans un groupe d'événements soit défini.

Objectif : les groupes d'événements sont souvent utilisés pour la notification d'événements et la synchronisation entre les tâches. Une tâche peut attendre qu'un ou plusieurs événements se produisent simultanément, ou elle peut attendre que tous les événements se produisent avant de continuer.

Caractéristiques : les groupes d'événements permettent aux tâches d'attendre plusieurs événements, offrant ainsi un mécanisme de synchronisation plus flexible.

2.信号量(Semaphore):

Concept : Un sémaphore est un compteur utilisé pour contrôler l'accès aux ressources partagées par plusieurs tâches. La valeur du sémaphore représente le nombre de ressources disponibles. Les tâches peuvent demander ou libérer des ressources. Le sémaphore est chargé de suivre le nombre de ressources disponibles.

Objectif : les sémaphores sont souvent utilisés pour contrôler l'accès aux ressources partagées et empêcher plusieurs tâches d'accéder aux ressources partagées en même temps afin d'éviter les conditions de concurrence.

Caractéristiques : Un sémaphore est un compteur qui peut être utilisé pour contrôler le nombre et l'allocation des ressources.

2.队列(Queue):

Concept : Une file d'attente est une structure de données utilisée pour transférer des données entre les tâches. Une tâche peut envoyer des données à la file d'attente et une autre tâche peut recevoir les données de la file d'attente.

Objectif : les files d'attente sont souvent utilisées pour le transfert de données entre les tâches, permettant aux tâches d'envoyer et de recevoir des données de manière asynchrone pour réaliser le découplage et la communication.

Caractéristiques : La file d'attente est un tampon de données qui peut être utilisé pour stocker et transférer des données. Le transfert de données entre les tâches est asynchrone.

区别总结:

Les groupes d'événements sont utilisés pour la notification d'événements et la synchronisation entre les tâches. Les tâches peuvent attendre l'apparition de plusieurs événements.

Les sémaphores sont utilisés pour contrôler l'accès aux ressources partagées et empêcher plusieurs tâches d'accéder aux ressources en même temps.

Les files d'attente sont utilisées pour le transfert de données entre les tâches, et les tâches peuvent envoyer et recevoir des données de manière asynchrone.

3. Fonctions liées aux groupes d'événements

xEventGroupCreate() - 创建事件组

EventGroupHandle_t xEventGroupCreate(void);

Paramètres : Aucun
Valeur de retour : Descripteur de groupe d'événements (EventGroupHandle_t)
Signification : Utilisé pour créer un groupe d'événements. Cette fonction renvoie un handle au groupe d'événements pour les opérations ultérieures.

xEventGroupSetBits() - 设置事件组位

EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet);

Paramètres :
xEventGroup : le handle du groupe d'événements
uxBitsToSet : le bit à définir, en utilisant généralement un masque de bits pour représenter l'événement bit à définir
Valeur de retour : l'état du groupe d'événements défini, y compris l'état actuel de tous les bits d'événement
Signification : utilisé pour définir un ou plusieurs bits du groupe d'événements, indiquant que l'événement se produit. Vous pouvez utiliser un masque de bits pour transmettre les bits à définir sur cette fonction.

xEventGroupClearBits() - 清除事件组位

EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear);

Paramètres :
xEventGroup : handle du groupe d'événements
uxBitsToClear : bits à effacer, en utilisant généralement un masque de bits pour représenter les bits d'événement à être effacé
Valeur de retour : état du groupe d'événements effacé, y compris l'état actuel de tous les bits d'événement
Signification : utilisé pour effacer un ou plusieurs bits du groupe d'événements, indiquant que l'événement ne s'est pas produit. Les bits à effacer peuvent être transmis à cette fonction à l'aide d'un masque de bits.

xEventGroupWaitBits() - 等待事件组位的设置

EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, BaseType_t xClearOnExit, BaseType_t xWaitForAllBits, TickType_t xTicksToWait);

Paramètres :
xEventGroup : le handle du groupe d'événements
uxBitsToWaitFor : le bit à attendre, utilisant généralement un masque de bits pour représenter l'événement bit to wait< /span>
a> Signification : utilisé pour attendre que des bits spécifiques du groupe d'événements soient définis. En fonction du réglage du paramètre, vous pouvez choisir d'attendre que tous les bits soient définis ou d'attendre seulement que l'un d'entre eux soit défini, ou vous pouvez choisir d'effacer le bit d'attente une fois l'attente terminée. Retour value : renvoie l'état actuel du groupe d'événements, y compris l'état actuel de tous les bits d'événement xTicksToWait : Le temps d'attente maximum (en ticks d'horloge), s'il est défini sur 0, il attendra indéfiniment
xWaitForAllBits : Spécifie s'il faut attendre que tous les bits soient définis (facultatif paramètre) xClearOnExit : Spécifie s'il faut effacer les bits en attente à la sortie (paramètre facultatif)


xEventGroupSync() 函数用于同步多个任务的操作,使它们能够在相同的时间点上等待一组特定的事件。它通过等待事件组的特定位或位组合被设置来实现同步。

EventBits_t xEventGroupSync(
    EventGroupHandle_t xEventGroup,
    const EventBits_t uxBitsToSet,
    const EventBits_t uxBitsToWaitFor,
    TickType_t xTicksToWait
);

paramètre:

xEventGroup : Handle du groupe d’événements à synchroniser.
uxBitsToSet : les bits qui doivent être définis, généralement en utilisant un masque de bits pour représenter les bits d'événement à définir.
uxBitsToWaitFor : les bits qui doivent être attendus. Un masque de bits est généralement utilisé pour représenter les bits d'événement qui doivent être attendus.
xTicksToWait : Le temps d'attente maximum (en ticks d'horloge), s'il est défini sur 0, il attendra indéfiniment.
Valeur de retour :

Cette fonction renvoie l'état actuel du groupe d'événements, y compris l'état actuel de tous les bits d'événement.

importance:

Le but de la fonction xEventGroupSync() est d'attendre que les bits spécifiés soient définis et de se synchroniser lorsque ces bits sont définis.

Lorsque la fonction xEventGroupSync() est appelée, la tâche appelante attend que le bit spécifié dans le groupe d'événements soit défini pendant qu'un autre ensemble de bits est défini. Une fois que tous les bits spécifiés dans le groupe d'événements sont définis, la tâche appelante poursuivra son exécution.

Si le temps d'attente spécifié (déterminé par le paramètre xTicksToWait) est dépassé sans que le bit spécifié dans le groupe d'événements soit défini, la tâche appelante prendra une action en fonction du comportement du délai d'attente.

通过 xEventGroupSync() 函数,你可以实现任务间的同步操作,确保多个任务在特定事件发生时同时执行。这对于某些需要多任务协作的场景非常有用,例如在任务需要同时开始执行某个操作时,或者需要等待某些条件满足后再执行后续操作时。

3. Exemples d'application de groupes d'événements

1. Attendez plusieurs événements

Le code suivant crée trois tâches, à savoir laver les légumes, faire du feu et cuisiner. La tâche de cuisson doit attendre la fin du lavage des légumes et de l'allumage du feu avant de pouvoir continuer à s'exécuter, sinon elle sera bloquée et ne pourra pas être exécutée.

/* 事件组句柄 */
EventGroupHandle_t xEventGroup;

/* bit0: 洗菜
 * bit1: 生火
 * bit2: 炒菜
 */
#define WASHING  (1<<0)
#define FIRING   (1<<1)
#define COOKING  (1<<2)

static void vWashingTask( void *pvParameters )
{
    
    
	int i = 0;
	
	/* 无限循环 */
	for( ;; )
	{
    
    
		printf("I am washing %d time....\r\n", i++);
		
		/* 发出事件: 我洗完菜了 */
		xEventGroupSetBits(xEventGroup, WASHING);	
		
		/* 等待大厨炒完菜, 再继续洗菜 */
		xEventGroupWaitBits(xEventGroup, COOKING, pdTRUE, pdTRUE, portMAX_DELAY);
	}
}

static void vFiringTask( void *pvParameters )
{
    
    
	int i = 0;
	
	/* 无限循环 */
	for( ;; )
	{
    
    
		/* 等待洗完菜, 才生火 */
		xEventGroupWaitBits(xEventGroup, WASHING, pdFALSE, pdTRUE, portMAX_DELAY);
		
		printf("I am firing %d time....\r\n", i++);

		/* 发出事件: 我生好火了 */
		xEventGroupSetBits(xEventGroup, FIRING);			
	}
}

static void vCookingTask( void *pvParameters )
{
    
    
	int i = 0;
	
	/* 无限循环 */
	for( ;; )
	{
    
    
		/* 等待2件事: 洗菜, 生火 */
		xEventGroupWaitBits(xEventGroup, WASHING|FIRING, pdTRUE, pdTRUE, portMAX_DELAY);
		
		printf("I am cooking %d time....\r\n", i++);
		
		/* 发出事件: 我炒好菜了 */
		xEventGroupSetBits(xEventGroup, COOKING);			
	}
}

//创建事件组
xEventGroup = xEventGroupCreate( );

/* 创建3个任务: 洗菜/生火/炒菜
*/
xTaskCreate( vWashingTask, "Task1", 1000, NULL, 1, NULL );
xTaskCreate( vFiringTask,  "Task2", 1000, NULL, 2, NULL );
xTaskCreate( vCookingTask, "Task3", 1000, NULL, 3, NULL );


2. Synchronisation des tâches

#include <FreeRTOS.h>
#include <task.h>
#include <event_groups.h>

// 定义事件组句柄
EventGroupHandle_t xEventGroup;

// 生产者任务
void vProducerTask(void *pvParameters) {
    
    
    // 生产数据过程
    for (int i = 1; i <= 5; i++) {
    
    
        // 生产数据,假设为整数 i
        printf("Producing data: %d\n", i);
        xEventGroupSetBits(xEventGroup, 0x01); // 设置位0(表示数据可用)
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 模拟生产数据需要时间
    }
}

// 消费者任务
void vConsumerTask(void *pvParameters) {
    
    
    // 等待数据可用
    xEventGroupSync(
        xEventGroup,
        0x01,     // 设置位0,表示数据可用
        0x01,     // 等待位0被设置
        portMAX_DELAY  // 无限等待
    );

    // 开始处理数据
    printf("Consumer task started!\n");
    while (1) {
    
    
        // 处理数据
        printf("Consuming data\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 模拟处理数据需要时间
    }
}

int main(void) {
    
    
    // 创建事件组
    xEventGroup = xEventGroupCreate();

    // 创建生产者任务
    xTaskCreate(vProducerTask, "Producer", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    // 创建消费者任务
    xTaskCreate(vConsumerTask, "Consumer", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 这里不会执行,因为任务是永远不会返回的
    return 0;
}

Résumer

Cet article explique principalement le concept de groupes d'événements, les fonctions spécifiques et les méthodes d'utilisation.

Je suppose que tu aimes

Origine blog.csdn.net/m0_49476241/article/details/133953870
conseillé
Classement