All checks were successful
ci/woodpecker/push/build Pipeline was successful
- Add stack high-water mark logging to WiFi/IP event handlers (DEBUG level) - Document coexistence findings: BLE not used, Thread uses external RCP - Document event handler stack safety: ~1200-1500 bytes worst case, 3584 bytes available (>50% margin) - Clarify wifi_manager uses event-driven pattern (no dedicated task) Stack monitoring: - log_event_handler_stack() called after disconnect and got_ip handling - Rate-limited to avoid spam (30s interval) - Warns if usage exceeds 70% of event loop stack Analysis (CG-51): - Coexistence NOT required: provisioning uses SoftAP, not BLE - Event handler stack is safe with >50% margin - Current event-driven architecture is appropriate 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
ClearGrow Controller Firmware
ESP32-S3 gateway with 4.3" touchscreen, Thread Border Router, and WiFi.
Commands
# Setup
source ~/esp/esp-idf/export.sh
cd /opt/repos/controller
# Build and flash
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
# Production build (with security)
idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.prod" build
# Other
idf.py fullclean # Clean build
idf.py menuconfig # Configuration
idf.py size-components # Size analysis
Code Style
- C11 with
snake_casefunctions,SCREAMING_SNAKEconstants - Include guards (
#ifndef), not#pragma once - Logging:
ESP_LOGI(TAG, "msg"),ESP_LOGW(),ESP_LOGE() - Errors: Always check return values, use
ESP_ERROR_CHECK()for fatal,ESP_RETURN_ON_ERROR()for recoverable
Critical Rules
NEVER call vTaskStartScheduler() - scheduler already running when app_main() is called
NEVER call lv_timer_handler() directly - handled by esp_lvgl_port
LVGL version is 8.x - NOT 9.x! APIs differ significantly
Memory allocation:
>4KBbuffers →heap_caps_malloc(size, MALLOC_CAP_SPIRAM)- DMA buffers →
heap_caps_malloc(size, MALLOC_CAP_DMA)(MUST be internal SRAM) - Performance-critical →
heap_caps_malloc(size, MALLOC_CAP_INTERNAL)
Architecture
- Core 0: WiFi, Thread BR, MQTT, REST API
- Core 1: LVGL UI, Sensor Hub, Automation
- Entry:
app_main()inmain/app_main.c
Key Components
| Component | Purpose |
|---|---|
ui/ |
LVGL screens (see ui/CLAUDE.md) |
display/ |
LCD driver, GT911 touch |
sensor_hub/ |
CoAP probe data aggregation |
thread_manager/ |
OpenThread Border Router |
wifi_manager/ |
WiFi state machine (event-driven, no dedicated task) |
settings/ |
NVS configuration |
automation/ |
Alert rules, webhooks |
network_api/ |
REST API, MQTT |
ota_manager/ |
Firmware updates |
Thread/OpenThread Version Requirements
| Component | Version | Notes |
|---|---|---|
| ESP-IDF | >=5.2.0 | Required for Thread 1.3 support |
| OpenThread | Thread 1.3 | Bundled with ESP-IDF component |
| RCP Firmware | >=1.3.0 | nRF52840 probe firmware |
The controller verifies RCP firmware version at initialization. Incompatible versions will prevent Thread network startup with ESP_ERR_NOT_SUPPORTED.
Version constants defined in components/thread_manager/include/thread_br.h:
THREAD_RCP_MIN_VERSION: Minimum version string ("1.3.0")THREAD_RCP_MIN_VERSION_MAJOR/MINOR/PATCH: Numeric version components
Hardware
- Display: 800x480 RGB LCD, 16bpp
- Touch: GT911 capacitive (I2C)
- Memory: 512KB SRAM, 8MB PSRAM, 16MB Flash
- Pinout: See
main/pin_config.h
Testing
# Unit tests (host-based)
cd test && idf.py build && ./build/test_app
# On device
idf.py flash monitor
Documentation
Full technical docs: /opt/repos/docs/reference/firmware/controller/