I have 2 Tasks, both will give turns in printing a string (shared resource) on the serial monitor. I’m using a ESP-32 microcontroller and FreeRTOS, also the Arduino IDE.
I’m trying to use binary semaphores for mutual exclusion as practice (instead of mutexes)
Here is my work in an emulator:
https://wokwi.com/projects/403426133978368001
I implemented the binary semaphores, but for some reason I’m not achieving mutual exclusion.
Here’s my code:
// Choose the core, if this macro (found in sdkconfig of ESP-32 configuration system files)
#if CONFIG_FREERTOS_UNICORE //this will return false (reading from config in freertos.h file), so we’ll set it to run on the second core app_cpu=1
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
// Global variables
// Message
char buffer[] = "Mary had a little lamb";
// Binary semaphore
SemaphoreHandle_t bin_sem;
// Task1
void Task1_Function(void *params)
{
uint8_t i;
uint8_t msg_len = strlen(buffer);
while (1)
{
// Take the binary semaphore, value of bin_sem now 0
xSemaphoreTake(bin_sem, portMAX_DELAY);
/******* CRITICAL SECTION START *******/
// Read (print) whatever is in the buffer
Serial.print("Task1: ");
for (i = 0; i < msg_len; i++)
{
Serial.print(buffer[i]);
}
Serial.println();
/******* CRITICAL SECTION END *******/
// Give the semaphore, value of bin_sem now back to 1
xSemaphoreGive(bin_sem);
vTaskDelay(pdMS_TO_TICKS(1000)); // Adjust the delay as necessary
}
}
// Task2
void Task2_Function(void *params)
{
uint8_t i;
uint8_t msg_len = strlen(buffer);
while (1)
{
// Take the binary semaphore, value of bin_sem now 0
xSemaphoreTake(bin_sem, portMAX_DELAY);
/******* CRITICAL SECTION START *******/
// Read (print) whatever is in the buffer
Serial.print("Task2: ");
for (i = 0; i < msg_len; i++)
{
Serial.print(buffer[i]);
}
Serial.println();
/******* CRITICAL SECTION END *******/
// Give the semaphore, value of bin_sem now back to 1
xSemaphoreGive(bin_sem);
vTaskDelay(pdMS_TO_TICKS(1000)); // Adjust the delay as necessary
}
}
void setup()
{
// Initialize Serial monitor
Serial.begin(9600);
BaseType_t status;
TaskHandle_t task1_handler, task2_handler;
// Create binary semaphore
bin_sem = xSemaphoreCreateBinary(); // Note this is initialized to 0
xSemaphoreGive(bin_sem); // bin sem now 1, ready to be taken
// Task 1 Creation
status = xTaskCreatePinnedToCore(Task1_Function,
"Task-1-Function",
1024, // This is stack size in words, in bytes for a 32bit miccrocontroller each word is 4 bytes. so 1024*4 = 4096 bytes
NULL, // No parameters passed
1, // Priority
&task1_handler,
app_cpu
);
// Check if task creation, memory allocation was successful
if (status != pdTRUE)
{
Serial.println("Error Task1 creation failed"); // Using Arduino IDE
}
// Or you can use the assert
// configASSERT(status == pdTRUE);
// Task 2 Creation
status = xTaskCreatePinnedToCore(Task2_Function,
"Task-2-Function",
1024, // This is stack size in words, in bytes for a 32bit miccrocontroller each word is 4 bytes. so 1024*4 = 4096 bytes
NULL, // No parameters passed
1, // Priority
&task2_handler,
app_cpu
);
// Check if task creation, memory allocation was successful
if (status != pdTRUE)
{
Serial.println("Error Task2 creation failed"); // Using Arduino IDE
}
// Or you can use the assert
// configASSERT(status == pdTRUE);
}
void loop()
{
// put your main code here, to run repeatedly:
}
The output:
mode:DIO, clock div:2
load:0x3fff0030,len:1156
load:0x40078000,len:11456
ho 0 tail 12 room 4
load:0x40080400,len:2972
entry 0x400805dc
Task1: Mary had a little lamb
Task2: Mary had a little lamb
Task1: Mary had a little lamb
The tasks execute fine at first but then they get stuck, there’s also sometimes where a message while printing gets interrupted.
I honestly don’t know why the code is wrong, so any help is greatly appreciated.
0