Best practices for exchanging variables between tasks
Posted: Thu Apr 01, 2021 7:54 am
Hello team!
I have a question concerning some best practices regarding data sharing between different tasks on the ESP32. My current (abstract) setup is described in the following and it works as expected, but I would highly appreciate your input regarding best practices, e.g., to avoid race conditions or undefined states when different tasks operate on the same data:
main.c:
- Declare global struct A with members B and C (again structs) and initialize them via corresponding macros:
- Setting up networking and event loop
- Starting webserver
- Setting the user_ctx of some httpd_uri_t variables, e.g.:
- Start of FreeRTOS Tasks for SPI communication and pass pointer to struct A to xTaskCreate, such that the code in the task can access its members B, C for read and write operations.
webserver.h
- Declare httpd_uri_t Variables, set those that are also modified in main.c as "extern" (e.g., uri_siteA, uri_siteB).
webserver.c:
- Actual webserver code with corresponding GET and POST handlers
- Generate JSON from user_ctx, i.e., from A.B and serve upon GET request.
- Read received JSON and set values in A.C via provided user_ctx pointer upon POST request.
task.c:
- Init SPI bus and create while(1) loop that does the SPI transmission by filling receive and send buffers based on the the passed reference to struct A.
What do you think about this setup? Does it make sense to you? What can be done to avoid race conditions? Should I use something like binary semaphores or mutexes to ensure that only one task accesses struct A at the same time?
Best, Tom
I have a question concerning some best practices regarding data sharing between different tasks on the ESP32. My current (abstract) setup is described in the following and it works as expected, but I would highly appreciate your input regarding best practices, e.g., to avoid race conditions or undefined states when different tasks operate on the same data:
main.c:
- Declare global struct A with members B and C (again structs) and initialize them via corresponding macros:
Code: Select all
struct A {
struct B;
struct C;
};
INIT_B(A.B);
INIT_C(A.C);
- Starting webserver
- Setting the user_ctx of some httpd_uri_t variables, e.g.:
Code: Select all
uri_siteA.user_ctx = &(A.B);
uri_siteB.user_ctx = &(A.C);
webserver.h
- Declare httpd_uri_t Variables, set those that are also modified in main.c as "extern" (e.g., uri_siteA, uri_siteB).
webserver.c:
- Actual webserver code with corresponding GET and POST handlers
- Generate JSON from user_ctx, i.e., from A.B and serve upon GET request.
- Read received JSON and set values in A.C via provided user_ctx pointer upon POST request.
task.c:
- Init SPI bus and create while(1) loop that does the SPI transmission by filling receive and send buffers based on the the passed reference to struct A.
What do you think about this setup? Does it make sense to you? What can be done to avoid race conditions? Should I use something like binary semaphores or mutexes to ensure that only one task accesses struct A at the same time?
Best, Tom