Skip to content

Commit 87be4ab

Browse files
committed
Moved doc from Mutex to README
1 parent 1c6a435 commit 87be4ab

File tree

2 files changed

+127
-31
lines changed

2 files changed

+127
-31
lines changed

libraries/MultiThreading/examples/Mutex/Mutex.ino

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,4 @@
1-
/*
2-
This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading.
3-
Please refer to other examples in this folder to better understand usage of tasks.
4-
It is also advised to read documentation on FreeRTOS web pages:
5-
https://www.freertos.org/a00106.html
6-
7-
This example creates 2 task with same implementation - they write into shared
8-
variable and then read it and check if it is the same as what they have written.
9-
In single thread programming like on Arduino this is of no concern and will be always ok, however when
10-
multi threading is used the tasks execution is switched by the FreeRTOS and the value can be rewritten from other task before reading again.
11-
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.
12-
Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them.
13-
Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches!
14-
15-
Theory:
16-
Mutex is a specialized version of Semaphore (please see the Semaphore example for more info).
17-
In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked).
18-
When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example
19-
that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task
20-
which will write to this variable and when the previous task runs again it will read something different.
21-
22-
Mutexes and binary semaphores are very similar but have some subtle differences:
23-
Mutexes include a priority inheritance mechanism, binary semaphores do not.
24-
This makes binary semaphores the better choice for implementing
25-
synchronisation (between tasks or between tasks and an interrupt), and mutexes the better
26-
choice for implementing simple mutual exclusion.
27-
28-
You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access.
29-
*/
1+
// Please read file README.md in the folder containing this example.
302

313
#define USE_MUTEX
324
int shared_variable = 0;
@@ -46,7 +18,6 @@ void setup() {
4618
shared_var_mutex = xSemaphoreCreateMutex(); // Create the mutex
4719
#endif
4820

49-
5021
// Set up two tasks to run the same function independently.
5122
static int task_number0 = 0;
5223
xTaskCreate(
@@ -104,7 +75,7 @@ void Task(void *pvParameters){ // This is a task.
10475
//Serial.printf("Task %d after write: reading %d\n", task_num, shared_variable);
10576

10677
if(shared_variable != new_value){
107-
Serial.printf("%s\n", task_num ? " Mismatch! |" : " | Mismatch!");
78+
Serial.printf("%s\n", task_num ? " Mismatch! |" : " | Mismatch!");
10879
//Serial.printf("Task %d: detected race condition - the value changed!\n", task_num);
10980
}
11081

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Mutex
2+
3+
This example demonstrates basic usage of FreeRTOS Mutually Exclusive Locks (Mutex) for securing access to shared resources in multi threading.
4+
Please refer to other examples in this folder to better understand usage of tasks.
5+
It is also advised to read documentation on FreeRTOS web pages:
6+
https://www.freertos.org/a00106.html
7+
8+
This example creates 2 task with same implementation - they write into shared
9+
variable and then read it and check if it is the same as what they have written.
10+
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.
11+
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.
12+
Watch the writes and read in secure mode when using the mutex (default) as the results are as you would expect them.
13+
Then try to comment the USE_MUTEX and watch again - there will be a lots of mismatches!
14+
15+
### Theory:
16+
Mutex is a specialized version of Semaphore (please see the Semaphore example for more info).
17+
In essence the mutex is a variable whose value determines if the mutes is taken (locked) or given (unlocked).
18+
When two or more processes access the same resource (variable, peripheral, etc) it might happen, for example
19+
that when one task starts to read a variable and the operating system (FreeRTOS) will schedule execution of another task
20+
which will write to this variable and when the previous task runs again it will read something different.
21+
22+
Mutexes and binary semaphores are very similar but have some subtle differences:
23+
Mutexes include a priority inheritance mechanism, binary semaphores do not.
24+
This makes binary semaphores the better choice for implementing
25+
synchronisation (between tasks or between tasks and an interrupt), and mutexes the better
26+
choice for implementing simple mutual exclusion.
27+
28+
Wha is priority inheritance?
29+
If a low priority task holds the Mutex, but gets interrupted by a Higher priority task, which
30+
then tries to take the Mutex, the low priority task will temporarily ‘inherit’ the high priority so a middle
31+
priority task can't block the low priority task, and thus also block the high priority task.
32+
Semaphores don't have logic to handle this, in part because Semaphores aren't 'owned' by the task that takes them.
33+
34+
Mutex can also be recursive - if a task that holds the mutex takes it again, it will succeed, and the mutex will be released
35+
for other tasks only when it is given the same number of time which it was taken.
36+
37+
You can check the danger by commenting the definition of USE_MUTEX which will disable the mutex and present the danger of concurrent access.
38+
39+
40+
# Supported Targets
41+
42+
This example supports all ESP32 SoCs.
43+
44+
## How to Use Example
45+
46+
Flash and observe serial output.
47+
48+
Comment the `USE_MUTEX` definition, save and flash again and observe the behavior of unprotected access to shared variable.
49+
50+
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
51+
52+
#### Using Arduino IDE
53+
54+
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
55+
56+
* Before Compile/Verify, select the correct board: `Tools -> Board`.
57+
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
58+
59+
#### Using Platform IO
60+
61+
* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file.
62+
63+
## Example Log Output
64+
65+
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.
66+
67+
```
68+
Task 0 | Task 1
69+
| Starting
70+
| 0 <- 227
71+
Starting |
72+
| R: 227
73+
227 <- 737 |
74+
R: 737 |
75+
| 737 <- 282
76+
| R: 282
77+
282 <- 267 |
78+
```
79+
80+
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!
81+
82+
```
83+
Task 0 | Task 1
84+
| Starting
85+
| 0 <- 333
86+
Starting |
87+
333 <- 620 |
88+
R: 620 |
89+
620 <- 244 |
90+
| R: 244
91+
| Mismatch!
92+
| 244 <- 131
93+
R: 131 |
94+
Mismatch! |
95+
131 <- 584 |
96+
| R: 584
97+
| Mismatch!
98+
| 584 <- 134
99+
| R: 134
100+
| 134 <- 554
101+
R: 554 |
102+
Mismatch! |
103+
554 <- 313 |
104+
```
105+
106+
## Troubleshooting
107+
108+
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source***
109+
110+
## Contribute
111+
112+
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
113+
114+
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!
115+
116+
Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else.
117+
118+
## Resources
119+
120+
* Official ESP32 Forum: [Link](https://esp32.com)
121+
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
122+
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
123+
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
124+
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
125+
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)

0 commit comments

Comments
 (0)