From 335e56fc1e27fd2572b026bda11fc2b39c11bc09 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 4 Jan 2023 13:20:20 +0100 Subject: [PATCH 01/22] Moved and renamed example ESP32/FreeRTOS to MultiThreading/BasicMultiThreading --- .../examples/BasicMultiThreading/BasicMultiThreading.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/{ESP32/examples/FreeRTOS/FreeRTOS.ino => MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino} (100%) diff --git a/libraries/ESP32/examples/FreeRTOS/FreeRTOS.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino similarity index 100% rename from libraries/ESP32/examples/FreeRTOS/FreeRTOS.ino rename to libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino From dd2e47416166bbeeb490ff8e68c17f9e7693646f Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 4 Jan 2023 14:13:44 +0100 Subject: [PATCH 02/22] Added dummy files --- libraries/MultiThreading/keywords.txt | 17 +++++++++++++++++ libraries/MultiThreading/library.properties | 9 +++++++++ libraries/MultiThreading/src/dummy.h | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 libraries/MultiThreading/keywords.txt create mode 100644 libraries/MultiThreading/library.properties create mode 100644 libraries/MultiThreading/src/dummy.h diff --git a/libraries/MultiThreading/keywords.txt b/libraries/MultiThreading/keywords.txt new file mode 100644 index 00000000000..631ad8f81c8 --- /dev/null +++ b/libraries/MultiThreading/keywords.txt @@ -0,0 +1,17 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + +RGB_BUILTIN LITERAL1 \ No newline at end of file diff --git a/libraries/MultiThreading/library.properties b/libraries/MultiThreading/library.properties new file mode 100644 index 00000000000..19b9733bb8d --- /dev/null +++ b/libraries/MultiThreading/library.properties @@ -0,0 +1,9 @@ +name=MultiThreading +version=2.0.0 +author=Tomas Pilny +maintainer=Tomas Pilny +sentence=MultiThreading, tasks, queues, mutexes adn semaphores +paragraph= +category=FreeRTOS +url= +architectures=esp32 diff --git a/libraries/MultiThreading/src/dummy.h b/libraries/MultiThreading/src/dummy.h new file mode 100644 index 00000000000..d8a140eda61 --- /dev/null +++ b/libraries/MultiThreading/src/dummy.h @@ -0,0 +1,2 @@ +// This file is here only to silence warnings from Arduino IDE +// Currently IDE doesn't support no-code libraries, like this collection of example sketches. From f189822ab9fc14a3c50923fd152fe0281a83e43e Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 4 Jan 2023 14:22:50 +0100 Subject: [PATCH 03/22] Modified original example --- .../BasicMultiThreading.ino | 81 ++++++++++++------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index c9ba0eca6aa..3ed9be12edb 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -1,3 +1,24 @@ +/* + This example demonstrates basic usage of FreeRTOS Task for multi threading. + Please refer to other examples in this folder to better utilize their the full potential and safe-guard potential problems. + It is also advised to read documentation on FreeRTOS web pages: + https://www.freertos.org/a00106.html + + This example will blink builtin LED and read analog data. + Additionally this example demonstrates usage of task handle, simply by deleting the analog + read task after 10 seconds from main loop by calling the function `vTaskDelete`. + + Theory: + A task is simply a function which runs when the operating system (FreeeRTOS) sees fit. + This task can have an infinite loop inside if you want to do some work periodically for the entirety of the program run. + This however can create a problem - no other task will ever run and also the Watch Dog will trigger and your program will restart. + A nice behaving tasks knows when it useless to keep the processor for itself and gives it away for other tasks to be used. + This can be achieved by many ways, but the simplest is calling `delay(milliseconds)`. + During that delay any other task may run and do it's job. + When the delay runs out the Operating System gives the processor to the task which can continue. + For other ways to yield the CPU in task please see other examples in this folder. +*/ + #if CONFIG_FREERTOS_UNICORE #define ARDUINO_RUNNING_CORE 0 #else @@ -8,50 +29,55 @@ #define LED_BUILTIN 13 #endif -// define two tasks for Blink & AnalogRead +// Define two tasks for Blink & AnalogRead. void TaskBlink( void *pvParameters ); void TaskAnalogReadA3( void *pvParameters ); +TaskHandle_t task_handle; // You can (don't have to) use this to be able to manipulate a task from somewhere else. -// the setup function runs once when you press reset or power the board +// The setup function runs once when you press reset or power on the board. void setup() { - - // initialize serial communication at 115200 bits per second: + // Initialize serial communication at 115200 bits per second: Serial.begin(115200); - // Now set up two tasks to run independently. - xTaskCreatePinnedToCore( + // Set up two tasks to run independently. + uint32_t blink_delay = 1000; // Delay between changing state on LED pin + xTaskCreate( TaskBlink - , "TaskBlink" // A name just for humans - , 1024 // This stack size can be checked & adjusted by reading the Stack Highwater - , NULL + , "TaskBlink" // A name just for humans + , 1024 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);` + , (void*) &blink_delay // Task parameter which can modify the task behavior. This must be passed as pointer to void. , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. - , NULL - , ARDUINO_RUNNING_CORE); + , NULL // Task handle is not used here + ); + // This variant of task creation can also for the task to run specified core xTaskCreatePinnedToCore( TaskAnalogReadA3 , "AnalogReadA3" , 1024 // Stack size - , NULL + , NULL // When no parameter is used, simply pass NULL , 1 // Priority - , NULL - , ARDUINO_RUNNING_CORE); + , task_handle // With task handle we will be able to manipulate with this task. + , ARDUINO_RUNNING_CORE // Core on which the task will run + ); // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. } -void loop() -{ - // Empty. Things are done in Tasks. +void loop(){ + if(task_handle != NULL){ // Make sure that the task actually exists + delay(10000); + vTaskDelete(task_handle); // Delete task + task_handle = NULL; // prevent calling vTaskDelete on non-existing task + } } /*--------------------------------------------------*/ /*---------------------- Tasks ---------------------*/ /*--------------------------------------------------*/ -void TaskBlink(void *pvParameters) // This is a task. -{ - (void) pvParameters; +void TaskBlink(void *pvParameters){ // This is a task. + uint32_t blink_delay = (uint32_t) *pvParameters; /* Blink @@ -64,19 +90,17 @@ void TaskBlink(void *pvParameters) // This is a task. // initialize digital LED_BUILTIN on pin 13 as an output. pinMode(LED_BUILTIN, OUTPUT); - for (;;) // A Task shall never return or exit. - { + for (;;){ // A Task shall never return or exit. digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) // arduino-esp32 has FreeRTOS configured to have a tick-rate of 1000Hz and portTICK_PERIOD_MS // refers to how many milliseconds the period between each ticks is, ie. 1ms. - vTaskDelay(1000 / portTICK_PERIOD_MS ); // vTaskDelay wants ticks, not milliseconds + delay(blink_delay); digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW - vTaskDelay(1000 / portTICK_PERIOD_MS); // 1 second delay + delay(blink_delay); } } -void TaskAnalogReadA3(void *pvParameters) // This is a task. -{ +void TaskAnalogReadA3(void *pvParameters){ // This is a task. (void) pvParameters; /* @@ -88,12 +112,11 @@ void TaskAnalogReadA3(void *pvParameters) // This is a task. This example code is in the public domain. */ - for (;;) - { + for (;;){ // read the input on analog pin A3: int sensorValueA3 = analogRead(A3); // print out the value you read: Serial.println(sensorValueA3); - vTaskDelay(100 / portTICK_PERIOD_MS); // 100ms delay + delay(100); // 100ms delay } } From ad2968c1bb6b00bef8f0fb9ff8d395124969d37e Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 4 Jan 2023 16:49:46 +0100 Subject: [PATCH 04/22] Fixed BasicMultiThreading.ino --- .../examples/BasicMultiThreading/BasicMultiThreading.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index 3ed9be12edb..c4e3c1ce701 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -57,7 +57,7 @@ void setup() { , 1024 // Stack size , NULL // When no parameter is used, simply pass NULL , 1 // Priority - , task_handle // With task handle we will be able to manipulate with this task. + , &task_handle // With task handle we will be able to manipulate with this task. , ARDUINO_RUNNING_CORE // Core on which the task will run ); @@ -65,11 +65,13 @@ void setup() { } void loop(){ + /* if(task_handle != NULL){ // Make sure that the task actually exists delay(10000); vTaskDelete(task_handle); // Delete task task_handle = NULL; // prevent calling vTaskDelete on non-existing task } + */ } /*--------------------------------------------------*/ @@ -77,7 +79,7 @@ void loop(){ /*--------------------------------------------------*/ void TaskBlink(void *pvParameters){ // This is a task. - uint32_t blink_delay = (uint32_t) *pvParameters; + uint32_t blink_delay = *((uint32_t*)pvParameters); /* Blink From c18d355df312704326c295080550b5152005be2d Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Thu, 5 Jan 2023 13:46:14 +0100 Subject: [PATCH 05/22] Added Example demonstrating use of queues --- .../MultiThreading/examples/Queues/Queues.ino | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 libraries/MultiThreading/examples/Queues/Queues.ino diff --git a/libraries/MultiThreading/examples/Queues/Queues.ino b/libraries/MultiThreading/examples/Queues/Queues.ino new file mode 100644 index 00000000000..6169ae61e4b --- /dev/null +++ b/libraries/MultiThreading/examples/Queues/Queues.ino @@ -0,0 +1,127 @@ +/* + This example demonstrates basic usage of FreeRTOS Queues which enable tasks to pass data between each other in a secure asynchronous way. + Please refer to other examples in this folder to better understand usage of tasks. + It is also advised to read documentation on FreeRTOS web pages: + https://www.freertos.org/a00106.html + + This example read data received on serial port (sent by user) pass it vie queue to another task which will send it back on Serial Output. + + Theory: + A queue is a simple to use data structure (in the most basic way) controlled by `xQueueSend` and `xQueueReceive` functions. + Usually one task writes into the queue and the other task reads from it. + Usage of queues enables the reading task to yield the CPU until there are data in the queue and therefore not waste precious computation time. +*/ + +#define MAX_LINE_LENGTH (64) + +// Define two tasks for reading and writing from and to the serial port. +void TaskWriteToSerial(void *pvParameters); +void TaskReadFromSerial(void *pvParameters); + +// Define Queue handle +QueueHandle_t QueueHandle; +const int QueueElementSize = 10; +typedef struct{ + char line[MAX_LINE_LENGTH]; + uint8_t line_length; +} message_t; + +// The setup function runs once when you press reset or power on the board. +void setup() { + // Initialize serial communication at 115200 bits per second: + Serial.begin(115200); + while(!Serial){delay(10);} + + // Create the queue which will have number of elements, each of size `message_t` and pass the address to . + QueueHandle = xQueueCreate(QueueElementSize, sizeof(message_t)); + + // Check if the queue was successfully created + if(QueueHandle == NULL){ + Serial.println("Queue could not be created. Halt."); + while(1) delay(1000); // Halt at this point as is not possible to continue + } + + // Set up two tasks to run independently. + xTaskCreate( + TaskWriteToSerial + , "Task Write To Serial" // A name just for humans + , 2048 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);` + , NULL // No parameter is used + , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. + , NULL // Task handle is not used here + ); + + xTaskCreate( + TaskReadFromSerial + , "Task Read From Serial" + , 2048 // Stack size + , NULL // No parameter is used + , 1 // Priority + , NULL // Task handle is not used here + ); + + // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. + Serial.printf("\nAnything you write will return as echo.\nMaximum line length is %d characters (+ terminating '0').\nAnything longer will sent as separate line.\n\n", MAX_LINE_LENGTH-1); +} + +void loop(){ + // Loop is free to do any other work + + delay(1000); // While not being used yield the CPU to other tasks +} + +/*--------------------------------------------------*/ +/*---------------------- Tasks ---------------------*/ +/*--------------------------------------------------*/ + +void TaskWriteToSerial(void *pvParameters){ // This is a task. + message_t message; + for (;;){ // A Task shall never return or exit. + // One approach would be to poll the function (uxQueueMessagesWaiting(QueueHandle) and call delay if nothing is waiting. + // The other approach is to use infinite time to wait defined by constant `portMAX_DELAY`: + if(QueueHandle != NULL){ // Sanity check just to make sure the queue actually exists + int ret = xQueueReceive(QueueHandle, &message, portMAX_DELAY); + if(ret == pdPASS){ + // The message was successfully received - send it back to Serial port and "Echo: " + //Serial.printf("Echo: \"%s\"\n", line); + Serial.printf("Echo line of size %d: \"%s\"\n", message.line_length, message.line); + // The item is queued by copy, not by reference, so lets free the buffer after use. + }else if(ret == pdFALSE){ + Serial.println("The `TaskWriteToSerial` was unable to receive data from the Queue"); + } + } // Sanity check + } // Infinite loop +} + +void TaskReadFromSerial(void *pvParameters){ // This is a task. + message_t message; + for (;;){ + // Check if any data are waiting in the Serial buffer + message.line_length = Serial.available(); + if(message.line_length > 0){ + // Check if the queue exists AND if there is any free space in the queue + if(QueueHandle != NULL && uxQueueSpacesAvailable(QueueHandle) > 0){ + int max_length = message.line_length < MAX_LINE_LENGTH ? message.line_length : MAX_LINE_LENGTH-1; + for(int i = 0; i < max_length; ++i){ + message.line[i] = Serial.read(); + } + message.line_length = max_length; + message.line[message.line_length] = 0; // Add the terminating nul char + + // The line needs to be passed as pointer to void. + // The last parameter states how many milliseconds should wait (keep trying to send) if is not possible to send right away. + // When the wait parameter is 0 it will not wait and if the send is not possible the function will return errQUEUE_FULL + int ret = xQueueSend(QueueHandle, (void*) &message, 0); + if(ret == pdTRUE){ + // The message was successfully sent. + }else if(ret == errQUEUE_FULL){ + // Since we are checking uxQueueSpacesAvailable this should not occur, however if more than one task should + // write into the same queue it can fill-up between the test and actual send attempt + Serial.println("The `TaskReadFromSerial` was unable to send data into the Queue"); + } // Queue send check + } // Queue sanity check + }else{ + delay(100); // Allow other tasks to run when there is nothing to read + } // Serial buffer check + } // Infinite loop +} From 84725b3c9384951658e41af3a48f35270a59410b Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Thu, 5 Jan 2023 13:50:34 +0100 Subject: [PATCH 06/22] Extended info in BasicMultiThreading --- .../BasicMultiThreading.ino | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index c4e3c1ce701..c01af9c2162 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -17,6 +17,23 @@ During that delay any other task may run and do it's job. When the delay runs out the Operating System gives the processor to the task which can continue. For other ways to yield the CPU in task please see other examples in this folder. + + Task creation has few parameter you should understand: + xTaskCreate(TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) + + - pxTaskCode is the name of your function which will run as a task + - pcName is a string of human readable description for your task + - usStackDepth is number of words (word = 4B) available to the task. If you see error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it + - pvParameters is a parameter which will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. + - uxPriority is number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is lowest priority. + - pxCreatedTask task handle is basically a pointer to the task which allows you to manipulate with the task - delete it, suspend and resume. + If you don't need to do anything special with you task, simply pass NULL for this parameter. + You can read more about task control here: https://www.freertos.org/a00112.html */ #if CONFIG_FREERTOS_UNICORE @@ -43,17 +60,17 @@ void setup() { uint32_t blink_delay = 1000; // Delay between changing state on LED pin xTaskCreate( TaskBlink - , "TaskBlink" // A name just for humans + , "Task Blink" // A name just for humans , 1024 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);` , (void*) &blink_delay // Task parameter which can modify the task behavior. This must be passed as pointer to void. - , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. - , NULL // Task handle is not used here + , 2 // Priority + , NULL // Task handle is not used here - simply pass NULL ); // This variant of task creation can also for the task to run specified core xTaskCreatePinnedToCore( TaskAnalogReadA3 - , "AnalogReadA3" + , "Analog Read A3" , 1024 // Stack size , NULL // When no parameter is used, simply pass NULL , 1 // Priority From e3212292356286838a2ce7cd036f663964a1447d Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Fri, 6 Jan 2023 11:33:12 +0100 Subject: [PATCH 07/22] Renamed Queues to singular Queue --- .../examples/{Queues/Queues.ino => Queue/Queue.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/MultiThreading/examples/{Queues/Queues.ino => Queue/Queue.ino} (100%) diff --git a/libraries/MultiThreading/examples/Queues/Queues.ino b/libraries/MultiThreading/examples/Queue/Queue.ino similarity index 100% rename from libraries/MultiThreading/examples/Queues/Queues.ino rename to libraries/MultiThreading/examples/Queue/Queue.ino From 3a9fa4e2f88a1194df3bae9341c89ce73c02eaf6 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Fri, 6 Jan 2023 13:27:55 +0100 Subject: [PATCH 08/22] Added Mutex example --- .../MultiThreading/examples/Mutex/Mutex.ino | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 libraries/MultiThreading/examples/Mutex/Mutex.ino diff --git a/libraries/MultiThreading/examples/Mutex/Mutex.ino b/libraries/MultiThreading/examples/Mutex/Mutex.ino new file mode 100644 index 00000000000..8aee7e9ba1b --- /dev/null +++ b/libraries/MultiThreading/examples/Mutex/Mutex.ino @@ -0,0 +1,120 @@ +/* + This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading. + Please refer to other examples in this folder to better understand usage of tasks. + It is also advised to read documentation on FreeRTOS web pages: + https://www.freertos.org/a00106.html + + This example creates 2 task with same implementation - they write into shared + variable and then read it and check if it is the same as what they have written. + In single thread programming like on Arduino this is of no concern and will be always ok, however when + multi threading is used the tasks execution is switched by the FreeRTOS and the value can be rewritten from other task before reading again. + The tasks print write and read operation - each in their own column for better reading. Task 0 is on the left and Task 1 is on the right. + Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them. + Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches! + + Theory: + Mutex is a specialized version of Semaphore (please see the Semaphore example for more info). + In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked). + When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example + that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task + which will write to this variable and when the previous task runs again it will read something different. + + Mutexes and binary semaphores are very similar but have some subtle differences: + Mutexes include a priority inheritance mechanism, binary semaphores do not. + This makes binary semaphores the better choice for implementing + synchronisation (between tasks or between tasks and an interrupt), and mutexes the better + choice for implementing simple mutual exclusion. + + You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access. +*/ + +#define USE_MUTEX +int shared_variable = 0; +SemaphoreHandle_t shared_var_mutex = NULL; + +// Define a task function +void Task( void *pvParameters ); + +// The setup function runs once when you press reset or power on the board. +void setup() { + // Initialize serial communication at 115200 bits per second: + Serial.begin(115200); + while(!Serial) delay(100); + Serial.printf(" Task 0 | Task 1\n"); + +#ifdef USE_MUTEX + shared_var_mutex = xSemaphoreCreateMutex(); // Create the mutex +#endif + + + // Set up two tasks to run the same function independently. + static int task_number0 = 0; + xTaskCreate( + Task + , "Task 0" // A name just for humans + , 2048 // The stack size + , (void*)&task_number0 // Pass reference to a variable describing the task number + //, 5 // High priority + , 1 // priority + , NULL // Task handle is not used here - simply pass NULL + ); + + static int task_number1 = 1; + xTaskCreate( + Task + , "Task 1" + , 2048 // Stack size + , (void*)&task_number1 // Pass reference to a variable describing the task number + , 1 // Low priority + , NULL // Task handle is not used here - simply pass NULL + ); + + // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. +} + +void loop(){ +} + +/*--------------------------------------------------*/ +/*---------------------- Tasks ---------------------*/ +/*--------------------------------------------------*/ + +void Task(void *pvParameters){ // This is a task. + int task_num = *((int*)pvParameters); + Serial.printf("%s\n", task_num ? " Starting |" : " | Starting"); + for (;;){ // A Task shall never return or exit. +#ifdef USE_MUTEX + if(shared_var_mutex != NULL){ // Sanity check if the mutex exists + // Try to take the mutex and wait indefintly if needed + if(xSemaphoreTake(shared_var_mutex, portMAX_DELAY) == pdTRUE){ + // Mutex successfully taken +#endif + int new_value = random(1000); + + char str0[32]; sprintf(str0, " %d <- %d |", shared_variable, new_value); + char str1[32]; sprintf(str1, " | %d <- %d", shared_variable, new_value); + Serial.printf("%s\n", task_num ? str0 : str1); + + shared_variable = new_value; + delay(random(100)); // wait random time of max 100 ms - simulating some computation + + sprintf(str0, " R: %d |", shared_variable); + sprintf(str1, " | R: %d", shared_variable); + Serial.printf("%s\n", task_num ? str0 : str1); + //Serial.printf("Task %d after write: reading %d\n", task_num, shared_variable); + + if(shared_variable != new_value){ + Serial.printf("%s\n", task_num ? " Mismatch! |" : " | Mismatch!"); + //Serial.printf("Task %d: detected race condition - the value changed!\n", task_num); + } + +#ifdef USE_MUTEX + xSemaphoreGive(shared_var_mutex); // After accessing the shared resource give the mutex and allow other processes to access it + }else{ + // We could not obtain the semaphore and can therefore not access the shared resource safely. + } // mutex take + } // sanity check +#endif + delay(10); // Allow other task to be scheduled + } // Infinite loop +} \ No newline at end of file From 1a203179667c4b2b8a1c3b50675cc43e3a38ba5a Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Tue, 10 Jan 2023 18:05:07 +0100 Subject: [PATCH 09/22] Added Semaphore example --- .../examples/Semaphore/Semaphore.ino | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 libraries/MultiThreading/examples/Semaphore/Semaphore.ino diff --git a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino new file mode 100644 index 00000000000..8c3e7a424f5 --- /dev/null +++ b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino @@ -0,0 +1,73 @@ +/* + This example demonstrates basic usage of FreeRTOS Semaphores and queue sets for coordination between tasks for multi threading. + Please refer to other examples in this folder to better understand usage of tasks. + It is also advised to read documentation on FreeRTOS web pages: + https://www.freertos.org/a00106.html + + Theory: + Semaphore is in essence a variable. Tasks can set the value, wait until one or more + semaphores are set and thus communicate between each other their state. + A binary semaphore is a semaphore that has a maximum count of 1, hence the 'binary' name. + A task can only 'take' the semaphore if it is available, and the semaphore is only available if its count is 1. + + Semaphore can be controlled from any number of tasks. If you use semaphore as a one-way + signalization with only one task giving and only one task taking there is much faster option + called Task Notifications - please see FreeRTOS documentation read more about them: https://www.freertos.org/RTOS-task-notifications.html + + The example: + We'll use a semaphore to signal when a package is delivered to a warehouse by multiple + delivery trucks, and multiple workers are waiting to receive the package. +*/ +#include + + +SemaphoreHandle_t package_delivered_semaphore; + +void delivery_truck_task(void *pvParameters) { + int truck_number = (int) pvParameters; + while(1) { + // Wait for a package to be delivered + // ... + // Notify the warehouse that a package has been delivered + xSemaphoreGive(package_delivered_semaphore); + Serial.print("Package delivered by truck: "); + Serial.println(truck_number); + //wait for some time + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +void warehouse_worker_task(void *pvParameters) { + int worker_number = (int) pvParameters; + while(1) { + // Wait for a package to be delivered + xSemaphoreTake(package_delivered_semaphore, portMAX_DELAY); + Serial.print("Package received by worker: "); + Serial.println(worker_number); + // Receive the package + // ... + } +} + +void setup() { + Serial.begin(115200); + // Create the semaphore + package_delivered_semaphore = xSemaphoreCreateCounting(10, 0); + + // Create multiple delivery truck tasks + for (int i = 0; i < 5; i++) { + xTaskCreate(delivery_truck_task, "Delivery Truck", 1024, (void *)i, tskIDLE_PRIORITY, NULL); + } + + // Create multiple warehouse worker tasks + for (int i = 0; i < 3; i++) { + xTaskCreate(warehouse_worker_task, "Warehouse Worker", 1024, (void *)i, tskIDLE_PRIORITY, NULL); + } + + // Start the RTOS scheduler + vTaskStartScheduler(); +} + +void loop() { + // Empty loop +} \ No newline at end of file From 1c6a4351e8da1ef5949c4b422e7e1ff11a17b3e3 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Tue, 17 Jan 2023 14:14:03 +0100 Subject: [PATCH 10/22] Moved info from example to README --- .../BasicMultiThreading.ino | 60 +++-------- .../examples/BasicMultiThreading/README.md | 101 ++++++++++++++++++ 2 files changed, 113 insertions(+), 48 deletions(-) create mode 100644 libraries/MultiThreading/examples/BasicMultiThreading/README.md diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index c01af9c2162..0ed52155579 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -1,40 +1,4 @@ -/* - This example demonstrates basic usage of FreeRTOS Task for multi threading. - Please refer to other examples in this folder to better utilize their the full potential and safe-guard potential problems. - It is also advised to read documentation on FreeRTOS web pages: - https://www.freertos.org/a00106.html - - This example will blink builtin LED and read analog data. - Additionally this example demonstrates usage of task handle, simply by deleting the analog - read task after 10 seconds from main loop by calling the function `vTaskDelete`. - - Theory: - A task is simply a function which runs when the operating system (FreeeRTOS) sees fit. - This task can have an infinite loop inside if you want to do some work periodically for the entirety of the program run. - This however can create a problem - no other task will ever run and also the Watch Dog will trigger and your program will restart. - A nice behaving tasks knows when it useless to keep the processor for itself and gives it away for other tasks to be used. - This can be achieved by many ways, but the simplest is calling `delay(milliseconds)`. - During that delay any other task may run and do it's job. - When the delay runs out the Operating System gives the processor to the task which can continue. - For other ways to yield the CPU in task please see other examples in this folder. - - Task creation has few parameter you should understand: - xTaskCreate(TaskFunction_t pxTaskCode, - const char * const pcName, - const uint16_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask ) - - - pxTaskCode is the name of your function which will run as a task - - pcName is a string of human readable description for your task - - usStackDepth is number of words (word = 4B) available to the task. If you see error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it - - pvParameters is a parameter which will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. - - uxPriority is number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is lowest priority. - - pxCreatedTask task handle is basically a pointer to the task which allows you to manipulate with the task - delete it, suspend and resume. - If you don't need to do anything special with you task, simply pass NULL for this parameter. - You can read more about task control here: https://www.freertos.org/a00112.html -*/ +// Please read file README.md in the folder containing this example. #if CONFIG_FREERTOS_UNICORE #define ARDUINO_RUNNING_CORE 0 @@ -42,13 +6,15 @@ #define ARDUINO_RUNNING_CORE 1 #endif +#define ANALOG_INPUT_PIN 27 + #ifndef LED_BUILTIN -#define LED_BUILTIN 13 + #define LED_BUILTIN 13 // Specify the on which is your LED #endif // Define two tasks for Blink & AnalogRead. void TaskBlink( void *pvParameters ); -void TaskAnalogReadA3( void *pvParameters ); +void TaskAnalogRead( void *pvParameters ); TaskHandle_t task_handle; // You can (don't have to) use this to be able to manipulate a task from somewhere else. // The setup function runs once when you press reset or power on the board. @@ -67,10 +33,10 @@ void setup() { , NULL // Task handle is not used here - simply pass NULL ); - // This variant of task creation can also for the task to run specified core + // This variant of task creation can also specify on which core it will be run (only relevant for multi-core ESPs) xTaskCreatePinnedToCore( - TaskAnalogReadA3 - , "Analog Read A3" + TaskAnalogRead + , "Analog Read" , 1024 // Stack size , NULL // When no parameter is used, simply pass NULL , 1 // Priority @@ -82,13 +48,11 @@ void setup() { } void loop(){ - /* if(task_handle != NULL){ // Make sure that the task actually exists delay(10000); vTaskDelete(task_handle); // Delete task task_handle = NULL; // prevent calling vTaskDelete on non-existing task } - */ } /*--------------------------------------------------*/ @@ -119,7 +83,7 @@ void TaskBlink(void *pvParameters){ // This is a task. } } -void TaskAnalogReadA3(void *pvParameters){ // This is a task. +void TaskAnalogRead(void *pvParameters){ // This is a task. (void) pvParameters; /* @@ -132,10 +96,10 @@ void TaskAnalogReadA3(void *pvParameters){ // This is a task. */ for (;;){ - // read the input on analog pin A3: - int sensorValueA3 = analogRead(A3); + // read the input on analog pin: + int sensorValue = analogRead(ANALOG_INPUT_PIN); // print out the value you read: - Serial.println(sensorValueA3); + Serial.println(sensorValue); delay(100); // 100ms delay } } diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/MultiThreading/examples/BasicMultiThreading/README.md new file mode 100644 index 00000000000..dc94d4ef381 --- /dev/null +++ b/libraries/MultiThreading/examples/BasicMultiThreading/README.md @@ -0,0 +1,101 @@ +# Basic Multi Threading + +This example demonstrates basic usage of FreeRTOS Tasks for multi threading. + +Please refer to other examples in this folder to better utilize their the full potential and safe-guard potential problems. +It is also advised to read documentation on FreeRTOS web pages: +[https://www.freertos.org/a00106.html](https://www.freertos.org/a00106.html) + +This example will blink builtin LED and read analog data. + Additionally this example demonstrates usage of task handle, simply by deleting the analog + read task after 10 seconds from main loop by calling the function `vTaskDelete`. + +### Theory: +A task is simply a function which runs when the operating system (FreeeRTOS) sees fit. +This task can have an infinite loop inside if you want to do some work periodically for the entirety of the program run. +This however can create a problem - no other task will ever run and also the Watch Dog will trigger and your program will restart. +A nice behaving tasks knows when it is useless to keep the processor for itself and gives it away for other tasks to be used. +This can be achieved by many ways, but the simplest is calling `delay(milliseconds)`. +During that delay any other task may run and do it's job. +When the delay runs out the Operating System gives the processor to the task which can continue. +For other ways to yield the CPU in task please see other examples in this folder. +It is also worth mentioning that two or more tasks running the exact same function will run them with separated stack, so if you want to run the same code (could be differentiated by the argument) there is no need to have multiple copies of the same function. + +**Task creation has few parameters you should understand:** +``` + xTaskCreate(TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) +``` + - **pxTaskCode** is the name of your function which will run as a task + - **pcName** is a string of human readable description for your task + - **usStackDepth** is number of words (word = 4B) available to the task. If you see error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it + - **pvParameters** is a parameter which will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. + - **uxPriority** is number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is lowest priority. + - **pxCreatedTask** task handle is basically a pointer to the task which allows you to manipulate with the task - delete it, suspend and resume. + If you don't need to do anything special with you task, simply pass NULL for this parameter. + You can read more about task control here: https://www.freertos.org/a00112.html + +# Supported Targets + +This example supports all SoCs. + +## How to Use Example + +Read this documentation and the code and try to understand it. +When you flash it to your ESP, open a Serial Plotter and observe the analog signal. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +### Hardware Connection + +If your board does not have built in LED, please connect one to the pin specified by the `LED_BUILTIN` in code (you can also change the number and connect it on pin you desire). + +Optionally you can connect analog element to pin ? such as variable resistor, or analog input such as audio signal, or any signal generator. However if the pin is left unconnected it will receive background noise and you will also see change in the signal when the pin is touched by finger. +Please refer to the ESP-IDF ADC documentation for specific SoC for info which pins are available: +[ESP32](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32/api-reference/peripherals/adc.html), + [ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s2/api-reference/peripherals/adc.html), + [ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s3/api-reference/peripherals/adc.html), + [ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32c3/api-reference/peripherals/adc.html) + + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) From 87be4abd7a4edea7ba8c33a79e2b74d2afdc5043 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Tue, 17 Jan 2023 14:59:41 +0100 Subject: [PATCH 11/22] Moved doc from Mutex to README --- .../MultiThreading/examples/Mutex/Mutex.ino | 33 +---- .../MultiThreading/examples/Mutex/README.md | 125 ++++++++++++++++++ 2 files changed, 127 insertions(+), 31 deletions(-) create mode 100644 libraries/MultiThreading/examples/Mutex/README.md diff --git a/libraries/MultiThreading/examples/Mutex/Mutex.ino b/libraries/MultiThreading/examples/Mutex/Mutex.ino index 8aee7e9ba1b..9fbd5ec5d22 100644 --- a/libraries/MultiThreading/examples/Mutex/Mutex.ino +++ b/libraries/MultiThreading/examples/Mutex/Mutex.ino @@ -1,32 +1,4 @@ -/* - This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading. - Please refer to other examples in this folder to better understand usage of tasks. - It is also advised to read documentation on FreeRTOS web pages: - https://www.freertos.org/a00106.html - - This example creates 2 task with same implementation - they write into shared - variable and then read it and check if it is the same as what they have written. - In single thread programming like on Arduino this is of no concern and will be always ok, however when - multi threading is used the tasks execution is switched by the FreeRTOS and the value can be rewritten from other task before reading again. - The tasks print write and read operation - each in their own column for better reading. Task 0 is on the left and Task 1 is on the right. - Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them. - Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches! - - Theory: - Mutex is a specialized version of Semaphore (please see the Semaphore example for more info). - In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked). - When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example - that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task - which will write to this variable and when the previous task runs again it will read something different. - - Mutexes and binary semaphores are very similar but have some subtle differences: - Mutexes include a priority inheritance mechanism, binary semaphores do not. - This makes binary semaphores the better choice for implementing - synchronisation (between tasks or between tasks and an interrupt), and mutexes the better - choice for implementing simple mutual exclusion. - - You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access. -*/ +// Please read file README.md in the folder containing this example. #define USE_MUTEX int shared_variable = 0; @@ -46,7 +18,6 @@ void setup() { shared_var_mutex = xSemaphoreCreateMutex(); // Create the mutex #endif - // Set up two tasks to run the same function independently. static int task_number0 = 0; xTaskCreate( @@ -104,7 +75,7 @@ void Task(void *pvParameters){ // This is a task. //Serial.printf("Task %d after write: reading %d\n", task_num, shared_variable); if(shared_variable != new_value){ - Serial.printf("%s\n", task_num ? " Mismatch! |" : " | Mismatch!"); + Serial.printf("%s\n", task_num ? " Mismatch! |" : " | Mismatch!"); //Serial.printf("Task %d: detected race condition - the value changed!\n", task_num); } diff --git a/libraries/MultiThreading/examples/Mutex/README.md b/libraries/MultiThreading/examples/Mutex/README.md new file mode 100644 index 00000000000..e6e5c615996 --- /dev/null +++ b/libraries/MultiThreading/examples/Mutex/README.md @@ -0,0 +1,125 @@ +# Mutex + +This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading. +Please refer to other examples in this folder to better understand usage of tasks. +It is also advised to read documentation on FreeRTOS web pages: +https://www.freertos.org/a00106.html + +This example creates 2 task with same implementation - they write into shared +variable and then read it and check if it is the same as what they have written. +In single thread programming like on Arduino this is of no concern and will be always ok, however when multi threading is used the tasks execution is switched by the FreeRTOS and the value can be rewritten from other task before reading again. +The tasks print write and read operation - each in their own column for better reading. Task 0 is on the left and Task 1 is on the right. +Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them. +Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches! + +### Theory: +Mutex is a specialized version of Semaphore (please see the Semaphore example for more info). +In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked). +When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example +that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task +which will write to this variable and when the previous task runs again it will read something different. + +Mutexes and binary semaphores are very similar but have some subtle differences: +Mutexes include a priority inheritance mechanism, binary semaphores do not. +This makes binary semaphores the better choice for implementing +synchronisation (between tasks or between tasks and an interrupt), and mutexes the better +choice for implementing simple mutual exclusion. + +Wha is priority inheritance? +If a low priority task holds the Mutex, but gets interrupted by a Higher priority task, which +then tries to take the Mutex, the low priority task will temporarily ‘inherit’ the high priority so a middle +priority task can't block the low priority task, and thus also block the high priority task. +Semaphores don't have logic to handle this, in part because Semaphores aren't 'owned' by the task that takes them. + +Mutex can also be recursive - if a task that holds the mutex takes it again, it will succeed, and the mutex will be released +for other tasks only when it is given the same number of time which it was taken. + +You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access. + + +# Supported Targets + +This example supports all ESP32 SoCs. + +## How to Use Example + +Flash and observe serial output. + +Comment the `USE_MUTEX` definition, save and flash again and observe the behavior of unprotected access to shared variable. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. + +## Example Log Output + +Expected output of shared variable protected by mutex demonstrates mutually exclusive acces from tasks - the do not interrupt each other and do not rewrite the value before the other task has read it back. + +``` + Task 0 | Task 1 + | Starting + | 0 <- 227 + Starting | + | R: 227 + 227 <- 737 | + R: 737 | + | 737 <- 282 + | R: 282 + 282 <- 267 | +``` + +Output of unprotected access to shared variable - ot happens often that a task is interrupted after writing and before reading the other task write a different value - a corruption occurred! + +``` + Task 0 | Task 1 + | Starting + | 0 <- 333 + Starting | + 333 <- 620 | + R: 620 | + 620 <- 244 | + | R: 244 + | Mismatch! + | 244 <- 131 + R: 131 | + Mismatch! | + 131 <- 584 | + | R: 584 + | Mismatch! + | 584 <- 134 + | R: 134 + | 134 <- 554 + R: 554 | + Mismatch! | + 554 <- 313 | +``` + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) From ae79f677de656e28cdc2b96b1d5722c043372e84 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 18 Jan 2023 10:22:25 +0100 Subject: [PATCH 12/22] Added Queue README --- .../MultiThreading/examples/Queue/Queue.ino | 16 +--- .../MultiThreading/examples/Queue/README.md | 74 +++++++++++++++++++ 2 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 libraries/MultiThreading/examples/Queue/README.md diff --git a/libraries/MultiThreading/examples/Queue/Queue.ino b/libraries/MultiThreading/examples/Queue/Queue.ino index 6169ae61e4b..0227017fd25 100644 --- a/libraries/MultiThreading/examples/Queue/Queue.ino +++ b/libraries/MultiThreading/examples/Queue/Queue.ino @@ -1,16 +1,4 @@ -/* - This example demonstrates basic usage of FreeRTOS Queues which enable tasks to pass data between each other in a secure asynchronous way. - Please refer to other examples in this folder to better understand usage of tasks. - It is also advised to read documentation on FreeRTOS web pages: - https://www.freertos.org/a00106.html - - This example read data received on serial port (sent by user) pass it vie queue to another task which will send it back on Serial Output. - - Theory: - A queue is a simple to use data structure (in the most basic way) controlled by `xQueueSend` and `xQueueReceive` functions. - Usually one task writes into the queue and the other task reads from it. - Usage of queues enables the reading task to yield the CPU until there are data in the queue and therefore not waste precious computation time. -*/ +// Please read file README.md in the folder containing this example./* #define MAX_LINE_LENGTH (64) @@ -61,7 +49,7 @@ void setup() { ); // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. - Serial.printf("\nAnything you write will return as echo.\nMaximum line length is %d characters (+ terminating '0').\nAnything longer will sent as separate line.\n\n", MAX_LINE_LENGTH-1); + Serial.printf("\nAnything you write will return as echo.\nMaximum line length is %d characters (+ terminating '0').\nAnything longer will be sent as a separate line.\n\n", MAX_LINE_LENGTH-1); } void loop(){ diff --git a/libraries/MultiThreading/examples/Queue/README.md b/libraries/MultiThreading/examples/Queue/README.md new file mode 100644 index 00000000000..b0353d327de --- /dev/null +++ b/libraries/MultiThreading/examples/Queue/README.md @@ -0,0 +1,74 @@ +# Queue + +This example demonstrates basic usage of FreeRTOS Queues which enables tasks to pass data between each other in a secure asynchronous way. +Please refer to other examples in this folder to better understand usage of tasks. +It is also advised to read documentation on FreeRTOS web pages: +[https://www.freertos.org/a00106.html](https://www.freertos.org/a00106.html) + +This example reads data received on serial port (sent by user) pass it via queue to another task which will send it back on Serial Output. + +### Theory: +A queue is a simple to use data structure (in the most basic way) controlled by `xQueueSend` and `xQueueReceive` functions. +Usually one task writes into the queue and the other task reads from it. +Usage of queues enables the reading task to yield the CPU until there are data in the queue and therefore not waste precious computation time. + +# Supported Targets + +This example supports all ESP32 SoCs. + +## How to Use Example + +Flash and write anything to serial input. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. + +## Example Log Output + +``` +Anything you write will return as echo. +Maximum line length is 63 characters (+ terminating '0'). +Anything longer will be sent as a separate line. + +``` +< Input text "Short input" + +``Echo line of size 11: "Short input"`` + +< Input text "An example of very long input which is longer than default 63 characters will be split." + +``` +Echo line of size 63: "An example of very long input which is longer than default 63 c" +Echo line of size 24: "haracters will be split." +``` + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) From 5af4f89dd0c8f72df707b5a2404b0c90f019758d Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 18 Jan 2023 15:19:55 +0100 Subject: [PATCH 13/22] Removed unecesary text --- .../examples/BasicMultiThreading/README.md | 13 --------- .../examples/Semaphore/Semaphore.ino | 29 +++---------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/MultiThreading/examples/BasicMultiThreading/README.md index dc94d4ef381..2479a324189 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/README.md +++ b/libraries/MultiThreading/examples/BasicMultiThreading/README.md @@ -43,13 +43,6 @@ It is also worth mentioning that two or more tasks running the exact same functi This example supports all SoCs. -## How to Use Example - -Read this documentation and the code and try to understand it. -When you flash it to your ESP, open a Serial Plotter and observe the analog signal. - -* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). - ### Hardware Connection If your board does not have built in LED, please connect one to the pin specified by the `LED_BUILTIN` in code (you can also change the number and connect it on pin you desire). @@ -77,12 +70,6 @@ To get more information about the Espressif boards see [Espressif Development Ki ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** -* **LED not blinking:** Check the wiring connection and the IO selection. -* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. -* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. - -If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). - ## Contribute To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) diff --git a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino index 8c3e7a424f5..9c980745fc5 100644 --- a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino +++ b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino @@ -1,26 +1,7 @@ -/* - This example demonstrates basic usage of FreeRTOS Semaphores and queue sets for coordination between tasks for multi threading. - Please refer to other examples in this folder to better understand usage of tasks. - It is also advised to read documentation on FreeRTOS web pages: - https://www.freertos.org/a00106.html +// Please read file README.md in the folder containing this example. - Theory: - Semaphore is in essence a variable. Tasks can set the value, wait until one or more - semaphores are set and thus communicate between each other their state. - A binary semaphore is a semaphore that has a maximum count of 1, hence the 'binary' name. - A task can only 'take' the semaphore if it is available, and the semaphore is only available if its count is 1. - - Semaphore can be controlled from any number of tasks. If you use semaphore as a one-way - signalization with only one task giving and only one task taking there is much faster option - called Task Notifications - please see FreeRTOS documentation read more about them: https://www.freertos.org/RTOS-task-notifications.html - - The example: - We'll use a semaphore to signal when a package is delivered to a warehouse by multiple - delivery trucks, and multiple workers are waiting to receive the package. -*/ #include - SemaphoreHandle_t package_delivered_semaphore; void delivery_truck_task(void *pvParameters) { @@ -51,21 +32,19 @@ void warehouse_worker_task(void *pvParameters) { void setup() { Serial.begin(115200); + while(!Serial){ delay(100); } // Create the semaphore package_delivered_semaphore = xSemaphoreCreateCounting(10, 0); // Create multiple delivery truck tasks for (int i = 0; i < 5; i++) { - xTaskCreate(delivery_truck_task, "Delivery Truck", 1024, (void *)i, tskIDLE_PRIORITY, NULL); + xTaskCreate(delivery_truck_task, "Delivery Truck", 512, (void *)i, tskIDLE_PRIORITY, NULL); } // Create multiple warehouse worker tasks for (int i = 0; i < 3; i++) { - xTaskCreate(warehouse_worker_task, "Warehouse Worker", 1024, (void *)i, tskIDLE_PRIORITY, NULL); + xTaskCreate(warehouse_worker_task, "Warehouse Worker", 512, (void *)i, tskIDLE_PRIORITY, NULL); } - - // Start the RTOS scheduler - vTaskStartScheduler(); } void loop() { From f3b840f679d0b89584242089091c816dcc08873b Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Fri, 20 Jan 2023 11:36:56 +0100 Subject: [PATCH 14/22] Fixed grammar --- .../examples/BasicMultiThreading/README.md | 50 +++++++++---------- .../MultiThreading/examples/Mutex/README.md | 49 ++++++++---------- .../MultiThreading/examples/Queue/README.md | 12 ++--- 3 files changed, 53 insertions(+), 58 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/MultiThreading/examples/BasicMultiThreading/README.md index 2479a324189..ec10f0b5929 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/README.md +++ b/libraries/MultiThreading/examples/BasicMultiThreading/README.md @@ -1,27 +1,27 @@ # Basic Multi Threading -This example demonstrates basic usage of FreeRTOS Tasks for multi threading. +This example demonstrates the basic usage of FreeRTOS Tasks for multi threading. -Please refer to other examples in this folder to better utilize their the full potential and safe-guard potential problems. -It is also advised to read documentation on FreeRTOS web pages: +Please refer to other examples in this folder to better utilize their full potential and safeguard potential problems. +It is also advised to read the documentation on FreeRTOS web pages: [https://www.freertos.org/a00106.html](https://www.freertos.org/a00106.html) -This example will blink builtin LED and read analog data. - Additionally this example demonstrates usage of task handle, simply by deleting the analog - read task after 10 seconds from main loop by calling the function `vTaskDelete`. +This example will blink the built-in LED and read analog data. +Additionally, this example demonstrates the usage of the task handle, simply by deleting the analog +read task after 10 seconds from the main loop by calling the function `vTaskDelete`. ### Theory: -A task is simply a function which runs when the operating system (FreeeRTOS) sees fit. +A task is simply a function that runs when the operating system (FreeeRTOS) sees fit. This task can have an infinite loop inside if you want to do some work periodically for the entirety of the program run. -This however can create a problem - no other task will ever run and also the Watch Dog will trigger and your program will restart. -A nice behaving tasks knows when it is useless to keep the processor for itself and gives it away for other tasks to be used. -This can be achieved by many ways, but the simplest is calling `delay(milliseconds)`. -During that delay any other task may run and do it's job. -When the delay runs out the Operating System gives the processor to the task which can continue. -For other ways to yield the CPU in task please see other examples in this folder. -It is also worth mentioning that two or more tasks running the exact same function will run them with separated stack, so if you want to run the same code (could be differentiated by the argument) there is no need to have multiple copies of the same function. - -**Task creation has few parameters you should understand:** +This, however, can create a problem - no other task will ever run and also the Watch Dog will trigger and your program will restart. +A nice behaving tasks know when it is useless to keep the processor for itself and give it away for other tasks to be used. +This can be achieved in many ways, but the simplest is called `delay(`milliseconds)`. +During that delay, any other task may run and do its job. +When the delay runs out the Operating System gives the processor the task which can continue. +For other ways to yield the CPU in a task please see other examples in this folder. +It is also worth mentioning that two or more tasks running the same function will run them with separate stacks, so if you want to run the same code (which could be differentiated by the argument) there is no need to have multiple copies of the same function. + +**Task creation has a few parameters you should understand:** ``` xTaskCreate(TaskFunction_t pxTaskCode, const char * const pcName, @@ -31,12 +31,12 @@ It is also worth mentioning that two or more tasks running the exact same functi TaskHandle_t * const pxCreatedTask ) ``` - **pxTaskCode** is the name of your function which will run as a task - - **pcName** is a string of human readable description for your task - - **usStackDepth** is number of words (word = 4B) available to the task. If you see error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it - - **pvParameters** is a parameter which will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. - - **uxPriority** is number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is lowest priority. - - **pxCreatedTask** task handle is basically a pointer to the task which allows you to manipulate with the task - delete it, suspend and resume. - If you don't need to do anything special with you task, simply pass NULL for this parameter. + - **pcName** is a string of human-readable descriptions for your task + - **usStackDepth** is the number of words (word = 4B) available to the task. If you see an error similar to this "Debug exception reason: Stack canary watchpoint triggered (Task Blink)" you should increase it + - **pvParameters** is a parameter that will be passed to the task function - it must be explicitly converted to (void*) and in your function explicitly converted back to the intended data type. + - **uxPriority** is a number from 0 to configMAX_PRIORITIES which determines how the FreeRTOS will allow the tasks to run. 0 is the lowest priority. + - **pxCreatedTask** task handle is a pointer to the task which allows you to manipulate the task - delete it, suspend and resume. + If you don't need to do anything special with your task, simply pass NULL for this parameter. You can read more about task control here: https://www.freertos.org/a00112.html # Supported Targets @@ -45,10 +45,10 @@ This example supports all SoCs. ### Hardware Connection -If your board does not have built in LED, please connect one to the pin specified by the `LED_BUILTIN` in code (you can also change the number and connect it on pin you desire). +If your board does not have a built-in LED, please connect one to the pin specified by the `LED_BUILTIN` in the code (you can also change the number and connect it to the pin you desire). -Optionally you can connect analog element to pin ? such as variable resistor, or analog input such as audio signal, or any signal generator. However if the pin is left unconnected it will receive background noise and you will also see change in the signal when the pin is touched by finger. -Please refer to the ESP-IDF ADC documentation for specific SoC for info which pins are available: +Optionally you can connect the analog element to the pin. such as a variable resistor, analog input such as an audio signal, or any signal generator. However, if the pin is left unconnected it will receive background noise and you will also see a change in the signal when the pin is touched by a finger. +Please refer to the ESP-IDF ADC documentation for specific SoC for info on which pins are available: [ESP32](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32/api-reference/peripherals/adc.html), [ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s2/api-reference/peripherals/adc.html), [ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s3/api-reference/peripherals/adc.html), diff --git a/libraries/MultiThreading/examples/Mutex/README.md b/libraries/MultiThreading/examples/Mutex/README.md index e6e5c615996..ae67d9f2543 100644 --- a/libraries/MultiThreading/examples/Mutex/README.md +++ b/libraries/MultiThreading/examples/Mutex/README.md @@ -1,40 +1,35 @@ # Mutex -This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading. -Please refer to other examples in this folder to better understand usage of tasks. -It is also advised to read documentation on FreeRTOS web pages: +This example demonstrates the basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi-threading. +Please refer to other examples in this folder to better understand the usage of tasks. +It is also advised to read the documentation on FreeRTOS web pages: https://www.freertos.org/a00106.html -This example creates 2 task with same implementation - they write into shared -variable and then read it and check if it is the same as what they have written. -In single thread programming like on Arduino this is of no concern and will be always ok, however when multi threading is used the tasks execution is switched by the FreeRTOS and the value can be rewritten from other task before reading again. -The tasks print write and read operation - each in their own column for better reading. Task 0 is on the left and Task 1 is on the right. +This example creates 2 tasks with the same implementation - they write into a shared variable and then read it and check if it is the same as what they have written. +In single-thread programming like on Arduino this is of no concern and will be always ok, however when multi-threading is used the execution of the task is switched by the FreeRTOS and the value can be rewritten from another task before reading again. +The tasks print write and read operation - each in their column for better reading. Task 0 is on the left and Task 1 is on the right. Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them. -Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches! +Then try to comment the USE_MUTEX and watch again - there will be a lot of mismatches! ### Theory: Mutex is a specialized version of Semaphore (please see the Semaphore example for more info). -In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked). -When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example -that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task +In essence, the mutex is a variable whose value determines if the mute is taken (locked) or given (unlocked). +When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example, that when one task starts to read a variable and the operating system (FreeRTOS) will schedule the execution of another task which will write to this variable and when the previous task runs again it will read something different. Mutexes and binary semaphores are very similar but have some subtle differences: -Mutexes include a priority inheritance mechanism, binary semaphores do not. -This makes binary semaphores the better choice for implementing -synchronisation (between tasks or between tasks and an interrupt), and mutexes the better +Mutexes include a priority inheritance mechanism, whereas binary semaphores do not. +This makes binary semaphores the better choice for implementing synchronization (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion. +What is priority inheritance? +If a low-priority task holds the Mutex but gets interrupted by a Higher priority task, which +then tries to take the Mutex, the low-priority task will temporarily ‘inherit’ the high priority so a middle-priority task can't block the low-priority task, and thus also block the high priority task. +Semaphores don't have the logic to handle this, in part because Semaphores aren't 'owned' by the task that takes them. -Wha is priority inheritance? -If a low priority task holds the Mutex, but gets interrupted by a Higher priority task, which -then tries to take the Mutex, the low priority task will temporarily ‘inherit’ the high priority so a middle -priority task can't block the low priority task, and thus also block the high priority task. -Semaphores don't have logic to handle this, in part because Semaphores aren't 'owned' by the task that takes them. +A mutex can also be recursive - if a task that holds the mutex takes it again, it will succeed, and the mutex will be released +for other tasks only when it is given the same number of times that it was taken. -Mutex can also be recursive - if a task that holds the mutex takes it again, it will succeed, and the mutex will be released -for other tasks only when it is given the same number of time which it was taken. - -You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access. +You can check the danger by commenting on the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access. # Supported Targets @@ -43,9 +38,9 @@ This example supports all ESP32 SoCs. ## How to Use Example -Flash and observe serial output. +Flash and observe the serial output. -Comment the `USE_MUTEX` definition, save and flash again and observe the behavior of unprotected access to shared variable. +Comment the `USE_MUTEX` definition, save and flash again and observe the behavior of unprotected access to the shared variable. * How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). @@ -62,7 +57,7 @@ To get more information about the Espressif boards see [Espressif Development Ki ## Example Log Output -Expected output of shared variable protected by mutex demonstrates mutually exclusive acces from tasks - the do not interrupt each other and do not rewrite the value before the other task has read it back. +The expected output of shared variables protected by mutex demonstrates mutually exclusive access from tasks - they do not interrupt each other and do not rewrite the value before the other task has read it back. ``` Task 0 | Task 1 @@ -77,7 +72,7 @@ Expected output of shared variable protected by mutex demonstrates mutually excl 282 <- 267 | ``` -Output of unprotected access to shared variable - ot happens often that a task is interrupted after writing and before reading the other task write a different value - a corruption occurred! +The output of unprotected access to shared variable - it happens often that a task is interrupted after writing and before reading the other task write a different value - a corruption occurred! ``` Task 0 | Task 1 diff --git a/libraries/MultiThreading/examples/Queue/README.md b/libraries/MultiThreading/examples/Queue/README.md index b0353d327de..a381110fe2a 100644 --- a/libraries/MultiThreading/examples/Queue/README.md +++ b/libraries/MultiThreading/examples/Queue/README.md @@ -1,15 +1,15 @@ # Queue -This example demonstrates basic usage of FreeRTOS Queues which enables tasks to pass data between each other in a secure asynchronous way. -Please refer to other examples in this folder to better understand usage of tasks. -It is also advised to read documentation on FreeRTOS web pages: +This example demonstrates the basic usage of FreeRTOS Queues which enables tasks to pass data between each other in a secure asynchronous way. +Please refer to other examples in this folder to better understand the usage of tasks. +It is also advised to read the documentation on FreeRTOS web pages: [https://www.freertos.org/a00106.html](https://www.freertos.org/a00106.html) -This example reads data received on serial port (sent by user) pass it via queue to another task which will send it back on Serial Output. +This example reads data received on the serial port (sent by the user) pass it via queue to another task which will send it back on Serial Output. ### Theory: -A queue is a simple to use data structure (in the most basic way) controlled by `xQueueSend` and `xQueueReceive` functions. -Usually one task writes into the queue and the other task reads from it. +A queue is a simple-to-use data structure (in the most basic way) controlled by `xQueueSend` and `xQueueReceive` functions. +Usually, one task writes into the queue and the other task reads from it. Usage of queues enables the reading task to yield the CPU until there are data in the queue and therefore not waste precious computation time. # Supported Targets From a1dcca8485dd5b480c0b1ce83beab6c221e6a2b8 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 23 Jan 2023 14:14:18 +0100 Subject: [PATCH 15/22] Increased stack size for Sempahore example --- .../MultiThreading/examples/Semaphore/Semaphore.ino | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino index 9c980745fc5..e5b017d5708 100644 --- a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino +++ b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino @@ -11,8 +11,7 @@ void delivery_truck_task(void *pvParameters) { // ... // Notify the warehouse that a package has been delivered xSemaphoreGive(package_delivered_semaphore); - Serial.print("Package delivered by truck: "); - Serial.println(truck_number); + Serial.printf("Package delivered by truck: %d\n", truck_number); //wait for some time vTaskDelay(1000 / portTICK_PERIOD_MS); } @@ -23,8 +22,7 @@ void warehouse_worker_task(void *pvParameters) { while(1) { // Wait for a package to be delivered xSemaphoreTake(package_delivered_semaphore, portMAX_DELAY); - Serial.print("Package received by worker: "); - Serial.println(worker_number); + Serial.printf("Package received by worker: %d\n", worker_number); // Receive the package // ... } @@ -38,12 +36,12 @@ void setup() { // Create multiple delivery truck tasks for (int i = 0; i < 5; i++) { - xTaskCreate(delivery_truck_task, "Delivery Truck", 512, (void *)i, tskIDLE_PRIORITY, NULL); + xTaskCreate(delivery_truck_task, "Delivery Truck", 2048, (void *)i, tskIDLE_PRIORITY, NULL); } // Create multiple warehouse worker tasks for (int i = 0; i < 3; i++) { - xTaskCreate(warehouse_worker_task, "Warehouse Worker", 512, (void *)i, tskIDLE_PRIORITY, NULL); + xTaskCreate(warehouse_worker_task, "Warehouse Worker", 2048, (void *)i, tskIDLE_PRIORITY, NULL); } } From 3f2b231dbd028beaa8e1c461457ec029b2afe2b4 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 23 Jan 2023 14:17:10 +0100 Subject: [PATCH 16/22] Added headers into .ino files --- .../examples/BasicMultiThreading/BasicMultiThreading.ino | 6 ++++++ libraries/MultiThreading/examples/Mutex/Mutex.ino | 6 ++++++ libraries/MultiThreading/examples/Queue/Queue.ino | 6 ++++++ libraries/MultiThreading/examples/Semaphore/Semaphore.ino | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index 0ed52155579..0a344bee9e9 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -1,3 +1,9 @@ +/* Basic Multi Threading Arduino Example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ // Please read file README.md in the folder containing this example. #if CONFIG_FREERTOS_UNICORE diff --git a/libraries/MultiThreading/examples/Mutex/Mutex.ino b/libraries/MultiThreading/examples/Mutex/Mutex.ino index 9fbd5ec5d22..157c5742e69 100644 --- a/libraries/MultiThreading/examples/Mutex/Mutex.ino +++ b/libraries/MultiThreading/examples/Mutex/Mutex.ino @@ -1,3 +1,9 @@ +/* Basic Multi Threading Arduino Example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ // Please read file README.md in the folder containing this example. #define USE_MUTEX diff --git a/libraries/MultiThreading/examples/Queue/Queue.ino b/libraries/MultiThreading/examples/Queue/Queue.ino index 0227017fd25..29131ee2139 100644 --- a/libraries/MultiThreading/examples/Queue/Queue.ino +++ b/libraries/MultiThreading/examples/Queue/Queue.ino @@ -1,3 +1,9 @@ +/* Basic Multi Threading Arduino Example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ // Please read file README.md in the folder containing this example./* #define MAX_LINE_LENGTH (64) diff --git a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino index e5b017d5708..ae3b3fd1bf7 100644 --- a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino +++ b/libraries/MultiThreading/examples/Semaphore/Semaphore.ino @@ -1,3 +1,9 @@ +/* Basic Multi Threading Arduino Example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ // Please read file README.md in the folder containing this example. #include From 289452c6f163df83c158590b2b1eb2834d419188 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 23 Jan 2023 14:20:01 +0100 Subject: [PATCH 17/22] Added word Example at the end of title in README --- libraries/MultiThreading/examples/BasicMultiThreading/README.md | 2 +- libraries/MultiThreading/examples/Mutex/README.md | 2 +- libraries/MultiThreading/examples/Queue/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/MultiThreading/examples/BasicMultiThreading/README.md index ec10f0b5929..329826dbd26 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/README.md +++ b/libraries/MultiThreading/examples/BasicMultiThreading/README.md @@ -1,4 +1,4 @@ -# Basic Multi Threading +# Basic Multi Threading Example This example demonstrates the basic usage of FreeRTOS Tasks for multi threading. diff --git a/libraries/MultiThreading/examples/Mutex/README.md b/libraries/MultiThreading/examples/Mutex/README.md index ae67d9f2543..02d0dab6249 100644 --- a/libraries/MultiThreading/examples/Mutex/README.md +++ b/libraries/MultiThreading/examples/Mutex/README.md @@ -1,4 +1,4 @@ -# Mutex +# Mutex Example This example demonstrates the basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi-threading. Please refer to other examples in this folder to better understand the usage of tasks. diff --git a/libraries/MultiThreading/examples/Queue/README.md b/libraries/MultiThreading/examples/Queue/README.md index a381110fe2a..044be0030f8 100644 --- a/libraries/MultiThreading/examples/Queue/README.md +++ b/libraries/MultiThreading/examples/Queue/README.md @@ -1,4 +1,4 @@ -# Queue +# Queue Example This example demonstrates the basic usage of FreeRTOS Queues which enables tasks to pass data between each other in a secure asynchronous way. Please refer to other examples in this folder to better understand the usage of tasks. From 81660e67fea4f9739bb10e304dd058e57d9b4264 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 23 Jan 2023 14:21:24 +0100 Subject: [PATCH 18/22] removed unused line --- libraries/MultiThreading/examples/Queue/Queue.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/MultiThreading/examples/Queue/Queue.ino b/libraries/MultiThreading/examples/Queue/Queue.ino index 29131ee2139..a26ee3310d6 100644 --- a/libraries/MultiThreading/examples/Queue/Queue.ino +++ b/libraries/MultiThreading/examples/Queue/Queue.ino @@ -77,7 +77,6 @@ void TaskWriteToSerial(void *pvParameters){ // This is a task. int ret = xQueueReceive(QueueHandle, &message, portMAX_DELAY); if(ret == pdPASS){ // The message was successfully received - send it back to Serial port and "Echo: " - //Serial.printf("Echo: \"%s\"\n", line); Serial.printf("Echo line of size %d: \"%s\"\n", message.line_length, message.line); // The item is queued by copy, not by reference, so lets free the buffer after use. }else if(ret == pdFALSE){ From f4dbaf254ff4f8e292dfa7220db72fe03d1524ff Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 30 Jan 2023 11:06:48 +0100 Subject: [PATCH 19/22] Added forgotten README --- .../examples/Semaphore/README.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 libraries/MultiThreading/examples/Semaphore/README.md diff --git a/libraries/MultiThreading/examples/Semaphore/README.md b/libraries/MultiThreading/examples/Semaphore/README.md new file mode 100644 index 00000000000..4d46f3f3498 --- /dev/null +++ b/libraries/MultiThreading/examples/Semaphore/README.md @@ -0,0 +1,80 @@ +# Semaphore Example + +This example demonstrates the basic usage of FreeRTOS Semaphores and queue sets for coordination between tasks for multi-threading. +Please refer to other examples in this folder to better understand the usage of tasks. +It is also advised to read the documentation on FreeRTOS web pages: +[https://www.freertos.org/a00106.html](https://www.freertos.org/a00106.html) + +### Theory: +Semaphore is in essence a variable. Tasks can set the value, wait until one or more +semaphores are set and thus communicate between each other their state. +A binary semaphore is a semaphore that has a maximum count of 1, hence the 'binary' name. +A task can only 'take' the semaphore if it is available, and the semaphore is only available if its count is 1. + +Semaphores can be controlled by any number of tasks. If you use semaphore as a one-way +signalization with only one task giving and only one task taking there is a much faster option +called Task Notifications - please see FreeRTOS documentation and read more about them: [https://www.freertos.org/RTOS-task-notifications.html](https://www.freertos.org/RTOS-task-notifications.html) + +This example uses a semaphore to signal when a package is delivered to a warehouse by multiple +delivery trucks, and multiple workers are waiting to receive the package. + +# Supported Targets + +This example supports all ESP32 SoCs. + +## How to Use Example + +Read the code and try to understand it, then flash and observe the Serial output. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file. + +## Example Log Output + +``` +Anything you write will return as echo. +Maximum line length is 63 characters (+ terminating '0'). +Anything longer will be sent as a separate line. + +``` +< Input text "Short input" + +``Echo line of size 11: "Short input"`` + +< Input text "An example of very long input which is longer than default 63 characters will be split." + +``` +Echo line of size 63: "An example of very long input which is longer than default 63 c" +Echo line of size 24: "haracters will be split." +``` + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) From 0bec759cb372e45adc38f0c565e17ecf040ebbef Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Mon, 30 Jan 2023 13:59:26 +0100 Subject: [PATCH 20/22] Modified BasicMultiThreading example --- .../BasicMultiThreading.ino | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino index 0a344bee9e9..745d5b6a46c 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino +++ b/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino @@ -12,7 +12,7 @@ #define ARDUINO_RUNNING_CORE 1 #endif -#define ANALOG_INPUT_PIN 27 +#define ANALOG_INPUT_PIN A0 #ifndef LED_BUILTIN #define LED_BUILTIN 13 // Specify the on which is your LED @@ -21,19 +21,18 @@ // Define two tasks for Blink & AnalogRead. void TaskBlink( void *pvParameters ); void TaskAnalogRead( void *pvParameters ); -TaskHandle_t task_handle; // You can (don't have to) use this to be able to manipulate a task from somewhere else. +TaskHandle_t analog_read_task_handle; // You can (don't have to) use this to be able to manipulate a task from somewhere else. // The setup function runs once when you press reset or power on the board. void setup() { // Initialize serial communication at 115200 bits per second: Serial.begin(115200); - // Set up two tasks to run independently. uint32_t blink_delay = 1000; // Delay between changing state on LED pin xTaskCreate( TaskBlink , "Task Blink" // A name just for humans - , 1024 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);` + , 2048 // The stack size can be checked by calling `uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);` , (void*) &blink_delay // Task parameter which can modify the task behavior. This must be passed as pointer to void. , 2 // Priority , NULL // Task handle is not used here - simply pass NULL @@ -43,21 +42,22 @@ void setup() { xTaskCreatePinnedToCore( TaskAnalogRead , "Analog Read" - , 1024 // Stack size + , 2048 // Stack size , NULL // When no parameter is used, simply pass NULL , 1 // Priority - , &task_handle // With task handle we will be able to manipulate with this task. + , &analog_read_task_handle // With task handle we will be able to manipulate with this task. , ARDUINO_RUNNING_CORE // Core on which the task will run ); + Serial.printf("Basic Multi Threading Arduino Example\n"); // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. } void loop(){ - if(task_handle != NULL){ // Make sure that the task actually exists + if(analog_read_task_handle != NULL){ // Make sure that the task actually exists delay(10000); - vTaskDelete(task_handle); // Delete task - task_handle = NULL; // prevent calling vTaskDelete on non-existing task + vTaskDelete(analog_read_task_handle); // Delete task + analog_read_task_handle = NULL; // prevent calling vTaskDelete on non-existing task } } @@ -91,6 +91,12 @@ void TaskBlink(void *pvParameters){ // This is a task. void TaskAnalogRead(void *pvParameters){ // This is a task. (void) pvParameters; + // Check if the given analog pin is usable - if not - delete this task + if(!adcAttachPin(ANALOG_INPUT_PIN)){ + Serial.printf("TaskAnalogRead cannot work because the given pin %d cannot be used for ADC - the task will delete itself.\n", ANALOG_INPUT_PIN); + analog_read_task_handle = NULL; // Prevent calling vTaskDelete on non-existing task + vTaskDelete(NULL); // Delete this task + } /* AnalogReadSerial From 7c68f7ef3e5520ad3ee0843c56033a52feccd65c Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 1 Feb 2023 11:10:46 +0100 Subject: [PATCH 21/22] Added missing S3 entry in README --- libraries/MultiThreading/examples/BasicMultiThreading/README.md | 1 + libraries/MultiThreading/examples/Mutex/README.md | 1 + libraries/MultiThreading/examples/Queue/README.md | 1 + libraries/MultiThreading/examples/Semaphore/README.md | 1 + 4 files changed, 4 insertions(+) diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/MultiThreading/examples/BasicMultiThreading/README.md index 329826dbd26..c7112e8b4f9 100644 --- a/libraries/MultiThreading/examples/BasicMultiThreading/README.md +++ b/libraries/MultiThreading/examples/BasicMultiThreading/README.md @@ -85,4 +85,5 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/MultiThreading/examples/Mutex/README.md b/libraries/MultiThreading/examples/Mutex/README.md index 02d0dab6249..d1c8c19e3be 100644 --- a/libraries/MultiThreading/examples/Mutex/README.md +++ b/libraries/MultiThreading/examples/Mutex/README.md @@ -117,4 +117,5 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/MultiThreading/examples/Queue/README.md b/libraries/MultiThreading/examples/Queue/README.md index 044be0030f8..745ce9e8db6 100644 --- a/libraries/MultiThreading/examples/Queue/README.md +++ b/libraries/MultiThreading/examples/Queue/README.md @@ -71,4 +71,5 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/MultiThreading/examples/Semaphore/README.md b/libraries/MultiThreading/examples/Semaphore/README.md index 4d46f3f3498..8f860a52db5 100644 --- a/libraries/MultiThreading/examples/Semaphore/README.md +++ b/libraries/MultiThreading/examples/Semaphore/README.md @@ -77,4 +77,5 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) From 7200582cacf81349e97638576e12b0444f518337 Mon Sep 17 00:00:00 2001 From: Tomas Pilny Date: Wed, 8 Feb 2023 14:27:22 +0100 Subject: [PATCH 22/22] moved location --- .../BasicMultiThreading/BasicMultiThreading.ino | 0 .../FreeRTOS}/BasicMultiThreading/README.md | 0 .../examples/FreeRTOS}/Mutex/Mutex.ino | 0 .../examples/FreeRTOS}/Mutex/README.md | 0 .../examples/FreeRTOS}/Queue/Queue.ino | 0 .../examples/FreeRTOS}/Queue/README.md | 0 .../examples/FreeRTOS}/Semaphore/README.md | 0 .../examples/FreeRTOS}/Semaphore/Semaphore.ino | 0 libraries/MultiThreading/keywords.txt | 17 ----------------- libraries/MultiThreading/library.properties | 9 --------- libraries/MultiThreading/src/dummy.h | 2 -- 11 files changed, 28 deletions(-) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/BasicMultiThreading/BasicMultiThreading.ino (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/BasicMultiThreading/README.md (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Mutex/Mutex.ino (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Mutex/README.md (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Queue/Queue.ino (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Queue/README.md (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Semaphore/README.md (100%) rename libraries/{MultiThreading/examples => ESP32/examples/FreeRTOS}/Semaphore/Semaphore.ino (100%) delete mode 100644 libraries/MultiThreading/keywords.txt delete mode 100644 libraries/MultiThreading/library.properties delete mode 100644 libraries/MultiThreading/src/dummy.h diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino similarity index 100% rename from libraries/MultiThreading/examples/BasicMultiThreading/BasicMultiThreading.ino rename to libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/BasicMultiThreading.ino diff --git a/libraries/MultiThreading/examples/BasicMultiThreading/README.md b/libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md similarity index 100% rename from libraries/MultiThreading/examples/BasicMultiThreading/README.md rename to libraries/ESP32/examples/FreeRTOS/BasicMultiThreading/README.md diff --git a/libraries/MultiThreading/examples/Mutex/Mutex.ino b/libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino similarity index 100% rename from libraries/MultiThreading/examples/Mutex/Mutex.ino rename to libraries/ESP32/examples/FreeRTOS/Mutex/Mutex.ino diff --git a/libraries/MultiThreading/examples/Mutex/README.md b/libraries/ESP32/examples/FreeRTOS/Mutex/README.md similarity index 100% rename from libraries/MultiThreading/examples/Mutex/README.md rename to libraries/ESP32/examples/FreeRTOS/Mutex/README.md diff --git a/libraries/MultiThreading/examples/Queue/Queue.ino b/libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino similarity index 100% rename from libraries/MultiThreading/examples/Queue/Queue.ino rename to libraries/ESP32/examples/FreeRTOS/Queue/Queue.ino diff --git a/libraries/MultiThreading/examples/Queue/README.md b/libraries/ESP32/examples/FreeRTOS/Queue/README.md similarity index 100% rename from libraries/MultiThreading/examples/Queue/README.md rename to libraries/ESP32/examples/FreeRTOS/Queue/README.md diff --git a/libraries/MultiThreading/examples/Semaphore/README.md b/libraries/ESP32/examples/FreeRTOS/Semaphore/README.md similarity index 100% rename from libraries/MultiThreading/examples/Semaphore/README.md rename to libraries/ESP32/examples/FreeRTOS/Semaphore/README.md diff --git a/libraries/MultiThreading/examples/Semaphore/Semaphore.ino b/libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino similarity index 100% rename from libraries/MultiThreading/examples/Semaphore/Semaphore.ino rename to libraries/ESP32/examples/FreeRTOS/Semaphore/Semaphore.ino diff --git a/libraries/MultiThreading/keywords.txt b/libraries/MultiThreading/keywords.txt deleted file mode 100644 index 631ad8f81c8..00000000000 --- a/libraries/MultiThreading/keywords.txt +++ /dev/null @@ -1,17 +0,0 @@ -####################################### -# Syntax Coloring Map -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - -RGB_BUILTIN LITERAL1 \ No newline at end of file diff --git a/libraries/MultiThreading/library.properties b/libraries/MultiThreading/library.properties deleted file mode 100644 index 19b9733bb8d..00000000000 --- a/libraries/MultiThreading/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=MultiThreading -version=2.0.0 -author=Tomas Pilny -maintainer=Tomas Pilny -sentence=MultiThreading, tasks, queues, mutexes adn semaphores -paragraph= -category=FreeRTOS -url= -architectures=esp32 diff --git a/libraries/MultiThreading/src/dummy.h b/libraries/MultiThreading/src/dummy.h deleted file mode 100644 index d8a140eda61..00000000000 --- a/libraries/MultiThreading/src/dummy.h +++ /dev/null @@ -1,2 +0,0 @@ -// This file is here only to silence warnings from Arduino IDE -// Currently IDE doesn't support no-code libraries, like this collection of example sketches.