The resource manager task pattern helps control access to shared resources safely in FreeRTOS. It avoids conflicts by letting one task manage the resource requests.
Resource manager task pattern in FreeRTOS
/* Pseudocode for resource manager task pattern in FreeRTOS */ // Resource manager task function void ResourceManagerTask(void *params) { for (;;) { // Wait for resource request message ResourceRequest req; ReceiveRequest(&req); // Process request (e.g., lock resource) AccessResource(req); // Notify requester when done NotifyRequester(req); } } // Other tasks send requests void ClientTask(void *params) { ResourceRequest req = CreateRequest(); SendRequestToManager(&req); WaitForResponse(&req); UseResource(); }
The resource manager task runs in a loop, handling requests one by one.
Communication between tasks usually uses queues or message buffers.
// Example: Sending a request to resource manager
ResourceRequest req = { .taskHandle = xTaskGetCurrentTaskHandle(), .action = READ };
xQueueSend(resourceQueue, &req, portMAX_DELAY);// Resource manager receives and processes request
ResourceRequest req;
xQueueReceive(resourceQueue, &req, portMAX_DELAY);
// Perform resource action
ProcessRequest(req);
// Notify client task
xTaskNotifyGive(req.taskHandle);This program creates a resource manager task and two client tasks. Clients send requests to the manager via a queue. The manager processes requests one by one and notifies clients when done.
#include "FreeRTOS.h" #include "task.h" #include "queue.h" #include <stdio.h> // Define a simple request struct typedef struct { TaskHandle_t requester; int action; // 0 = read, 1 = write } ResourceRequest; QueueHandle_t resourceQueue; void ResourceManagerTask(void *params) { ResourceRequest req; for (;;) { if (xQueueReceive(resourceQueue, &req, portMAX_DELAY) == pdPASS) { // Simulate resource access if (req.action == 0) { printf("ResourceManager: Reading resource for task %p\n", req.requester); } else { printf("ResourceManager: Writing resource for task %p\n", req.requester); } // Notify requester task xTaskNotifyGive(req.requester); } } } void ClientTask(void *params) { ResourceRequest req = { .requester = xTaskGetCurrentTaskHandle(), .action = (int)params }; printf("ClientTask %p: Sending request action %d\n", req.requester, req.action); xQueueSend(resourceQueue, &req, portMAX_DELAY); // Wait for resource manager to finish ulTaskNotifyTake(pdTRUE, portMAX_DELAY); printf("ClientTask %p: Resource access done\n", req.requester); vTaskDelete(NULL); } int main(void) { resourceQueue = xQueueCreate(5, sizeof(ResourceRequest)); xTaskCreate(ResourceManagerTask, "ResourceManager", 1000, NULL, 2, NULL); xTaskCreate(ClientTask, "Client1", 1000, (void *)0, 1, NULL); // read xTaskCreate(ClientTask, "Client2", 1000, (void *)1, 1, NULL); // write vTaskStartScheduler(); for (;;) {} return 0; }
Use queues or message buffers for communication between tasks.
Always notify the requesting task after resource access to avoid deadlocks.
Keep the resource manager task priority higher than clients to ensure timely handling.
The resource manager task pattern centralizes control of shared resources.
Tasks send requests to the manager instead of accessing resources directly.
This pattern prevents conflicts and makes resource sharing safe and organized.