I’m working on an ESP32 project and would appreciate some insights on software architecture, particularly regarding inter-task communication (ITC) and robust error handling. I thought I might get broader architectural perspectives here, as my questions are more about general design patterns for a multi-tasking system.
I’ve started development, but the code isn’t quite in a shareable state yet, and I believe my questions are more conceptual at this stage, focusing on the overall software architecture rather than a specific bug.
Here’s an overview of the system I’m aiming for:
Goal:
To build a critical system that is as self-healing as possible.
Components & Task Structure:
The system involves several components, each running as its own FreeRTOS task:
- []Mesh Wi-Fi task
[]SoftAP with a basic HTTPS server task
[]MQTT client task
[]Buttons (input handling) task
[]Relays (output control) task
[]LCD display task - A dedicated error_handler task/module
Each component task will expose public functions for its lifecycle management:
Code: Select all
init(), start(), stop(), update(), deinitialize()Code: Select all
mqtt_publish_message(), relay_set_state(), lcd_display_text()Each component reports errors to the calling function/module.
Error Handling and Recovery Mechanism:
Using an
Code: Select all
ERROR_CHECK- []Capture return error codes
[]Feed them into a centralized state machine (inandCode: Select all
main_callback.c)Code: Select all
main_polling.c - Trigger recovery actions (e.g., task restart or full system reset)
Lifecycle functions are invoked from the central management modules:
Code: Select all
main_callback.c / main_polling.cComponent tasks use mutexes with
Code: Select all
portMAX_DELAYMutex Discipline:
Strict acquire/release for all mutex-requiring functions or critical sections.
Inter-Component Data Exchange (Current thought):
Using getter/setter functions with built-in mutex protection.
Now, for my main questions:
I’m considering the following for ITC (Inter-Task Communication):
- Polling with Mutexes & Getters/Setters:
Tasks poll shared state exposed via thread-safe getter/setter functions. - esp_event:
ESP-IDF’s event loop for an event-driven approach between tasks. - FreeRTOS Queues:
Using queues for structured, direct task-to-task message passing.
Which of these approaches (or combination) best ensures:
- []Concurrency safety
[]Liveness (no deadlocks) - Timeliness (meeting deadlines)
Seeking Your Experience:
- []What ITC mechanisms do you typically use in ESP32/FreeRTOS multi-tasking projects, and why?
[]How do you approach error handling and achieving self-healing in systems with multiple independent tasks?
[]Do you have a flowchart or conceptual diagram you use in similar architectures?
[]How rigorously do you check every return code in ESP-IDF/FreeRTOS? Any shortcuts you apply?
[]Do you trust returned data from functions likeif the return was successful, or validate it further?Code: Select all
xQueueReceive
[]Should pointers from successful function calls still be checked for NULL as a best practice? - How do you balance defensive coding vs. clean/readable code, especially regarding stable libraries?
Thanks in advance for your time and insights!