Используем мьютексы в системе FreeRTOS на базе платы Arduino Nano в среде программирования Arduino IDE.

Мьютекс — это механизм блокировки. То есть, пока не выполниться одна задача, вторая не запускается. 

Для примера у нас есть два датчика которые передают данные по USART, и если они одновременно будут передавать данные, мы получим не понятный набор данных, так как они будут перемешанные. Используя мьютекс, мы запрещаем одному датчику передавать данные, до тех пор, пока второй датчик не закончит свою передачу.

В качестве примера рассмотрим три светодиода, которые будут символизировать три задачи, которые должны выполняться друг за другом (по аналогии передачи данных), и одна задача (четвертый светодиод, который находиться на плате), которая будет выполняться сама по себе:

#include <Arduino_FreeRTOS.h>
#include <semphr.h>

SemaphoreHandle_t mutex;
void setup() {
Serial.begin(9600);
mutex = xSemaphoreCreateMutex();
if(mutex == NULL){
Serial.println("Mutex can not be created");
}
xTaskCreate(Task1,"Task1",128, NULL,1,NULL);
xTaskCreate(Task2,"Task2",128, NULL,1,NULL);
xTaskCreate(Task3,"Task3",128, NULL,1,NULL);
xTaskCreate(TaskBlink,"TaskBlink",128, NULL,1,NULL);

}

void loop() {}
void Task1(void *pvParameters)
{
pinMode(10, OUTPUT);
while(1)
{
xSemaphoreTake(mutex,portMAX_DELAY);
Serial.println("TASK1");
digitalWrite(10, HIGH);
vTaskDelay( 500 / portTICK_PERIOD_MS );
digitalWrite(10, LOW);
xSemaphoreGive(mutex);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

void Task2(void *pvParameters)
{
pinMode(9, OUTPUT);
while(1)
{
xSemaphoreTake(mutex,portMAX_DELAY);
Serial.println("TASK2");
digitalWrite(9, HIGH);
vTaskDelay( 500 / portTICK_PERIOD_MS );
digitalWrite(9, LOW);
xSemaphoreGive(mutex);
vTaskDelay(pdMS_TO_TICKS(500));
}
}

void Task3(void *pvParameters)
{
pinMode(8, OUTPUT);
while(1)
{
xSemaphoreTake(mutex,portMAX_DELAY);
Serial.println("TASK3");
digitalWrite(8, HIGH);
vTaskDelay( 500 / portTICK_PERIOD_MS );
digitalWrite(8, LOW);
xSemaphoreGive(mutex);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}

void TaskBlink(void *pvParameters)
{
(void) pvParameters;
pinMode(LED_BUILTIN, OUTPUT);
for (;;)
{
digitalWrite(LED_BUILTIN, HIGH);
vTaskDelay( 500 / portTICK_PERIOD_MS );
digitalWrite(LED_BUILTIN, LOW);
vTaskDelay( 500 / portTICK_PERIOD_MS );
}
}

Рассмотрим основные команды работы мьютексов:

xSemaphoreCreateMutex() — создание мьютекса.

xSemaphoreTake(xSemaphore, xTicksToWait) — получение доступа, где:

xSemaphore —  имя мьютекса

xTicksToWait: — время, которое задача будет ждать в состоянии блокировки

xSemaphoreGive(xSemaphore)  — передача мьютекса.