/**
* My solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
// Settings
static const int led_pin = LED_BUILTIN;
static const uint8_t buf_len = 100; // this value cannot be too big. Otherwise, it will lead to <cache disable> error message.
// Globals
static SemaphoreHandle_t mutex;
// Task: Toggle the LED with the given delay.
void blink(void* parameter) {
// Settings.
char buf_blink[buf_len];
// Take the mutex before the critical section.
xSemaphoreTake(mutex, portMAX_DELAY);
int num = *(int*)parameter;
// Release the mutex so that the setup() can finish.
xSemaphoreGive(mutex);
// Print the message.
sprintf(buf_blink, "Received LED delay %d ms from user. ", num);
Serial.println(buf_blink);
memset(buf_blink, 0, buf_len);
// Serial.print("Received: ");
// Serial.println(num);
while (1) {
digitalWrite(led_pin, HIGH);
vTaskDelay(num / portTICK_PERIOD_MS);
digitalWrite(led_pin, LOW);
vTaskDelay(num / portTICK_PERIOD_MS);
}
}
void setup() {
// put your setup code here, to run once:
// Settings.
long int led_delay;
char buf[buf_len];
// Pin configuration.
pinMode(led_pin, OUTPUT);
// Serial configuration
Serial.begin(115200);
// Wait a moment to start (so we don't miss Serial output)
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println();
Serial.println("---FreeRTOS Mutex Solution---");
Serial.println("Enter a number for delay (milliseconds)");
// Wait for the input from user.
while (Serial.available() <= 0);
// Get the input number from the user.
led_delay = Serial.parseInt();
sprintf(buf, "Send LED delay %d ms to LED. ", led_delay);
Serial.println(buf);
memset(buf, 0, buf_len);
// Serial.print("Sending: ");
// Serial.println(led_delay);
// Use mutex so that I can properly pass the delay as a parameter.
mutex = xSemaphoreCreateMutex();
// Task to make the LED blink with passed number.
xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS.
blink, // Function to be called.
"Blink", // Name of task.
1024, // Stack size (bytes in ESP32, words in FreeRTOS).
(void*)&led_delay, // Parameter to pass to function.
1, // Task priority (o to configMAX_PRIORITIES - 1)
NULL, // Task handle
app_cpu); // Run on one core for demo purposes (ESP32 only)
// Make 1 tick delay to make sure mutex is acquired by other tasks.
vTaskDelay(portTICK_PERIOD_MS);
// Take mutex (this will be block until blink() releases it.)
xSemaphoreTake(mutex, portMAX_DELAY);
Serial.println("Done! ");
// //Delete "setup and loop" task.
// vTaskDelete(NULL);
}
void loop() {
// put your main code here, to run repeatedly:
// Do nothing but allow yielding to lower-priority tasks.
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// /**
// * FreeRTOS Mutex Solution
// *
// * Pass a parameter to a task using a mutex.
// *
// * Date: January 20, 2021
// * Author: Shawn Hymel
// * License: 0BSD
// */
// // You'll likely need this on vanilla FreeRTOS
// //#include <semphr.h>
// // Use only core 1 for demo purposes
// #if CONFIG_FREERTOS_UNICORE
// static const BaseType_t app_cpu = 0;
// #else
// static const BaseType_t app_cpu = 1;
// #endif
// // Pins (change this if your Arduino board does not have LED_BUILTIN defined)
// static const int led_pin = LED_BUILTIN;
// // Globals
// static SemaphoreHandle_t mutex;
// //*****************************************************************************
// // Tasks
// // Blink LED based on rate passed by parameter
// void blinkLED(void *parameters) {
// // Take the mutex -> this our critical section
// xSemaphoreTake(mutex, portMAX_DELAY);
// // Copy the parameter into a local variable
// int num = *(int *)parameters;
// // Release the mutex so that setup() function can finish
// xSemaphoreGive(mutex);
// // Print the parameter
// Serial.print("Received: ");
// Serial.println(num);
// // Blink forever and ever
// while (1) {
// digitalWrite(led_pin, HIGH);
// vTaskDelay(num / portTICK_PERIOD_MS);
// digitalWrite(led_pin, LOW);
// vTaskDelay(num / portTICK_PERIOD_MS);
// }
// }
// //*****************************************************************************
// // Main (runs as its own task with priority 1 on core 1)
// void setup() {
// long int delay_arg;
// // Configure the LED pin
// pinMode(led_pin, OUTPUT);
// // Configure Serial
// Serial.begin(115200);
// // Wait a moment to start (so we don't miss Serial output)
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// Serial.println();
// Serial.println("---FreeRTOS Mutex Solution---");
// Serial.println("Enter a number for delay (milliseconds)");
// // Wait for input from Serial
// while (Serial.available() <= 0);
// // Read integer value
// delay_arg = Serial.parseInt();
// Serial.print("Sending: ");
// Serial.println(delay_arg);
// // Create mutex before starting tasks
// mutex = xSemaphoreCreateMutex();
// // Start task 1
// xTaskCreatePinnedToCore(blinkLED,
// "Blink LED",
// 1024,
// (void *)&delay_arg,
// 1,
// NULL,
// app_cpu);
// // one tick delay to make sure mutex is acquired by other task
// vTaskDelay(portTICK_PERIOD_MS);
// // take mutex (this will be blocked until blinkLED releases it)
// xSemaphoreTake(mutex, portMAX_DELAY);
// // Show that we accomplished our task of passing the stack-based argument
// Serial.println("Done!");
// }
// void loop() {
// // Do nothing but allow yielding to lower-priority tasks
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// }