3.3.7
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
/* 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)
|
||||
|
||||
// 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);
|
||||
|
||||
// Create the queue which will have <QueueElementSize> number of elements, each of size `message_t` and pass the address to <QueueHandle>.
|
||||
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 be sent as a 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 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
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
# 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.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
## 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)
|
||||
* 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)
|
||||
Reference in New Issue
Block a user