ESP32 Firmware Development Skill
Overview
This skill provides expertise for ESP32 firmware development using ESP-IDF framework and FreeRTOS.
Project Structure Reference
xiaozhi-esp32_vietnam2/
├── main/ # Main application code
│ ├── application.cc # Core application logic
│ ├── application.h
│ ├── protocols/ # Communication protocols (MQTT, WebSocket)
│ ├── audio/ # Audio processing, codec
│ ├── display/ # LCD, LVGL UI
│ └── boards/ # Board-specific configurations
├── components/ # ESP-IDF components
├── sdkconfig # Project configuration
├── CMakeLists.txt
└── partitions.csv # Flash partition table
ESP-IDF Core Concepts
1. Build System
# Configure project
idf.py menuconfig
# Build
idf.py build
# Flash and monitor
idf.py -p /dev/cu.usbmodemXXXX flash monitor
# Clean build
idf.py fullclean
2. Logging
#include "esp_log.h"
static const char *TAG = "MyComponent";
ESP_LOGI(TAG, "Info message");
ESP_LOGW(TAG, "Warning: %s", error_msg);
ESP_LOGE(TAG, "Error code: %d", err);
ESP_LOGD(TAG, "Debug details");
3. Memory Management
// Heap allocation
void* ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
heap_caps_free(ptr);
// Check memory
ESP_LOGI(TAG, "Free heap: %lu", esp_get_free_heap_size());
ESP_LOGI(TAG, "Free PSRAM: %lu", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
4. FreeRTOS Tasks
// Create task
xTaskCreate(task_function, "TaskName", 4096, NULL, 5, &task_handle);
// Task with specific core
xTaskCreatePinnedToCore(task_function, "TaskName", 4096, NULL, 5, &task_handle, 0);
// Delay
vTaskDelay(pdMS_TO_TICKS(100));
// Event groups
EventGroupHandle_t event_group = xEventGroupCreate();
xEventGroupSetBits(event_group, BIT0);
xEventGroupWaitBits(event_group, BIT0, pdTRUE, pdTRUE, portMAX_DELAY);
5. WiFi Connection
#include "esp_wifi.h"
#include "esp_event.h"
// Initialize WiFi
esp_netif_init();
esp_event_loop_create_default();
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_start();
6. NVS (Non-Volatile Storage)
#include "nvs_flash.h"
#include "nvs.h"
// Initialize
nvs_flash_init();
// Read/Write
nvs_handle_t handle;
nvs_open("storage", NVS_READWRITE, &handle);
nvs_set_str(handle, "key", "value");
nvs_commit(handle);
nvs_close(handle);
Xiaozhi ESP32 Specific Patterns
Application State Machine
enum DeviceState {
kDeviceStateIdle,
kDeviceStateConnecting,
kDeviceStateListening,
kDeviceStateSpeaking
};
void Application::SetDeviceState(DeviceState state) {
device_state_ = state;
// Update display, audio, etc.
}
Protocol Pattern
class Protocol {
public:
virtual bool Start() = 0;
virtual void SendText(const std::string& text) = 0;
virtual bool IsAudioChannelOpened() = 0;
virtual void OpenAudioChannel() = 0;
virtual void CloseAudioChannel() = 0;
};
Scheduled Tasks Pattern
void Application::Schedule(std::function<void()> callback) {
std::lock_guard<std::mutex> lock(mutex_);
main_tasks_.push_back(std::move(callback));
xEventGroupSetBits(event_group_, MAIN_EVENT_SCHEDULE);
}
Common Issues & Solutions
1. Stack Overflow
// Increase task stack size
xTaskCreate(task, "name", 8192, NULL, 5, NULL); // 8KB stack
2. Memory Fragmentation
// Use PSRAM for large allocations
void* buffer = heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
3. WiFi Reconnection
esp_wifi_connect(); // In disconnect event handler
4. Watchdog Timeout
// Feed watchdog in long loops
esp_task_wdt_reset();
Build Configuration (sdkconfig)
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
CONFIG_FREERTOS_HZ=1000
References
- Original Xiaozhi: https://github.com/78/xiaozhi-esp32
- ESP-IDF: https://docs.espressif.com/projects/esp-idf/
- Arduino-ESP32: https://github.com/espressif/arduino-esp32