Ive written some test-code to see how the FreeRTOS works. The code simply reads an input on the serial port and returns it with some extra text. It also blinks a LED. The code works fine, but one thing puzzels me. Why do I need the vTaskDelay() in the TaskTransmit(). Both threads have the same priority.
The code:
#include <Arduino_FreeRTOS.h>
#include <semphr.h>
// define two tasks for Blink & AnalogRead
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );
// Store the read in this structure.
SemaphoreHandle_t xSerialSemaphore;
typedef struct {
char str[64];
bool ready;
} Message_t;
volatile Message_t message;
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
}
if ( xSerialSemaphore == NULL ) // Check to confirm that the Serial Semaphore has not already been created.
{
xSerialSemaphore = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use to manage the Serial Port
if ( ( xSerialSemaphore ) != NULL )
xSemaphoreGive( ( xSerialSemaphore ) ); // Make the Serial Port available for use, by "Giving" the Semaphore.
}
// Now set up two tasks to run independently.
xTaskCreate(
TaskRead
, (const portCHAR *)"Read" // A name just for humans
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
, NULL );
xTaskCreate(
TaskTransmit
, (const portCHAR *) "Transmit"
, 128 // Stack size
, NULL
, 1 // Priority
, NULL );
// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}
void loop()
{
// Empty. Things are done in Tasks.
}
/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/
void TaskTransmit(void *pvParameters) // This is a task.
{
(void) pvParameters;
char buffer[64];
for (;;)
{
if (message.ready)
{
xSemaphoreTake( xSerialSemaphore, portMAX_DELAY );
strcpy( buffer, message.str );
message.ready = false;
xSemaphoreGive( xSerialSemaphore );
// Reflect the message back...
Serial.print("Answer: ");
Serial.print(buffer);
}
// Without this line nothing is transmitted back! And the LED will blink randomly.
vTaskDelay(0);
}
}
void myReadln(char *buffer)
{
bool eol = false;
unsigned int index = 0;
const char NEWLINE = 10;
while (!eol)
{
if (Serial.available())
{
char ch = Serial.read();
buffer[index++] = ch;
if (ch == NEWLINE || index > 62)
{
eol = true;
buffer[index] = 0;
}
}
}
}
void TaskRead(void *pvParameters) // This is a task.
{
(void) pvParameters;
pinMode(LED_BUILTIN, OUTPUT);
char buffer[64];
bool tmp = false;
for (;;)
{
digitalWrite(LED_BUILTIN, tmp);
tmp = !tmp;
if (message.ready == false)
if (Serial.available())
{
myReadln(buffer);
xSemaphoreTake( xSerialSemaphore, portMAX_DELAY );
strcpy(message.str, buffer);
message.ready = true;
xSemaphoreGive( xSerialSemaphore );
}
// vTaskDelay(1); // Not needed
}
}