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

// Tạo handle cho mutex. Nó sẽ được sử dụng để tham chiếu mutex
SemaphoreHandle_t xMutex;

void setup()
{
  // Kích hoạt module Serial của Arduino với tốc độ baud 9600
  Serial.begin(9600);
  // Tạo mutex và gán nó vào handler đã được tạo
  xMutex = xSemaphoreCreateMutex();
  // Tạo hai instance của task "OutputTask" để hiển thị chuỗi trên 
  // màn hình serial của Arduino. Chúng ta truyền các chuỗi như là tham số cho các task này như "Task 1 #####################Task1" và "Task 2 ---------------------Task2". Ưu tiên của một instance cao hơn instance kia
  xTaskCreate(OutputTask, "Printer Task 1", 128, (void *)"Task 1 #####################Task1 \r\n", 1, NULL);
  xTaskCreate(OutputTask, "Printer Task 2", 128, (void *)"Task 2 ---------------------Task2 \r\n", 2, NULL);    
}

void loop() {}

// Đây là định nghĩa của các task
void OutputTask(void *pvParameters)
{
  char *pcStringToPrint;
  pcStringToPrint = (char *)pvParameters;
  while(1)
  {
    printer(pcStringToPrint);
    vTaskDelay(pdMS_TO_TICKS(1000)); // Đặt độ trễ 1000ms để dễ quan sát
  }
}

// Task printer này gửi dữ liệu đến màn hình serial của Arduino
// Nó cũng là tài nguyên được chia sẻ giữa cả hai instance của các task
void printer(const char* pcString)
{
  // Lấy mutex
  xSemaphoreTake(xMutex, portMAX_DELAY);
  Serial.println(pcString); // Gửi chuỗi đến màn hình serial
  xSemaphoreGive(xMutex); // Giải phóng mutex
}