0
0
FreeRTOSprogramming~7 mins

Resource manager task pattern in FreeRTOS

Choose your learning style9 modes available
Introduction

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.

When multiple tasks need to use a shared hardware device like a sensor or communication port.
When you want to serialize access to a resource to prevent data corruption.
When you want to centralize resource control for easier debugging and maintenance.
When tasks have different priorities but must share a resource fairly.
When you want to avoid blocking tasks directly on resource access.
Syntax
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.

Examples
A client task sends a request struct to the resource manager via a queue.
FreeRTOS
// Example: Sending a request to resource manager
ResourceRequest req = { .taskHandle = xTaskGetCurrentTaskHandle(), .action = READ };
xQueueSend(resourceQueue, &req, portMAX_DELAY);
The resource manager waits for requests, processes them, then notifies the requesting task.
FreeRTOS
// Resource manager receives and processes request
ResourceRequest req;
xQueueReceive(resourceQueue, &req, portMAX_DELAY);
// Perform resource action
ProcessRequest(req);
// Notify client task
xTaskNotifyGive(req.taskHandle);
Sample Program

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.

FreeRTOS
#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;
}
OutputSuccess
Important Notes

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.

Summary

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.