# GMF Board Manager A comprehensive board configuration management system for projects, designed to simplify hardware abstraction and device management across different development boards. ## Overview GMF Board Manager provides a unified interface for managing board peripherals and devices through YAML configuration files. It automatically generates C code for peripheral and device initialization, making it easy to support multiple boards with minimal code changes. ## Key Features ### 🎯 **Multi-Path Board Scanning** - **Main boards directory**: Default board configurations - **Custom customer path**: User-defined board configurations via `BOARD_CUSTOMER_PATH` - **Component boards**: Automatic scanning of `components/` directories for board configurations ### 🔧 **Automatic Board Selection** - Reads `sdkconfig` to determine selected board via `CONFIG_BOARD_XX=y` configuration - Supports menuconfig integration for easy board selection - Fallback to default board if no selection is found ### 📝 **YAML-Based Configuration** - **board_peripherals.yaml**: Define I2C, I2S, GPIO, SPI, and other peripherals - **board_devices.yaml**: Configure audio codecs, SD cards, sensors, and other devices - **board_info.yaml**: Board metadata and version information ### 🔄 **Automatic Code Generation** - Generates C configuration structures from YAML files - Creates peripheral and device handles - Supports custom parser extensions for new peripheral/device types ## Project Structure ``` gmf_board_manager/ ├── boards/ # Board configuration directories │ ├── esp32_s3_korvo2_v3/ # Example board │ │ ├── board_peripherals.yaml # Peripheral definitions │ │ ├── board_devices.yaml # Device definitions │ │ ├── board_info.yaml # Board information │ │ ├── Kconfig # Board-specific Kconfig │ │ ├── periph_gpio.c # Board-specific peripheral implementation │ │ └── dev_sdcard.c # Board-specific device implementation │ ├── esp32_s3_korvo2l/ # Other board configurations │ ├── esp32c5_spot/ │ └── ... ├── devices/ # Device parser implementations │ ├── dev_audio_codec.c # Audio codec device │ ├── dev_display_lcd.c # LCD display device │ ├── dev_sdcard.c # SD card device │ └── ... ├── peripherals/ # Peripheral parser implementations │ ├── periph_i2c.c # I2C peripheral │ ├── periph_i2s.c # I2S peripheral │ ├── periph_gpio.c # GPIO peripheral │ ├── periph_uart.c # UART peripheral │ └── ... ├── test_apps/ # Test applications and examples ├── scripts/ # Utility scripts ├── docs/ # Documentation ├── board_manager.c # Main board manager implementation ├── board_manager.h # Public API header ├── board_devices.c # Device management ├── board_periph.c # Peripheral management ├── gen_config_codes.py # Code generation script ├── gen_unified_kconfig.py # Kconfig generation script └── CMakeLists.txt # Build configuration ``` ## Quick Start ### 1. Basic Usage ```bash # In your project directory idf.py menuconfig # Navigate to: GMF Board Manager Configuration → Select target board # Choose your board and save idf.py build ``` ### 2. Adding Custom Boards There are two ways to add custom boards: #### Method 1: Add as Component (Recommended) Create a component in your project's `components/` directory: ``` your_project/ ├── components/ │ └── board_customer/ # Custom board component │ └── boards/ │ ├── your_board_name/ │ │ ├── board_peripherals.yaml │ │ ├── board_devices.yaml │ │ ├── board_info.yaml │ │ └── Kconfig │ └── another_board/ │ ├── board_peripherals.yaml │ ├── board_devices.yaml │ ├── board_info.yaml │ └── Kconfig └── main/ ``` Example: `esp-gmf/packages/gmf_board_manager/test_apps/components/board_customer/boards/` #### Method 2: Specify Custom Board Path In your project's `CMakeLists.txt`: ```cmake set(BOARD_CUSTOMER_PATH "path/to/your/boards") ``` Or via command line: ```bash idf.py -DBOARD_CUSTOMER_PATH="path/to/your/boards" build ``` ### 3. Using Board Manager API ```c #include "board_manager.h" #include "board_periph.h" #include "board_devices.h" void app_main(void) { // Initialize board manager (initializes all peripherals and devices) esp_err_t ret = board_manager_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Board manager initialization failed: %d", ret); return; } ESP_LOGI(TAG, "Board manager initialized successfully"); // Print board information board_manager_print_board_info(); board_manager_print(); // Example 1: Get I2C peripheral handle (already initialized) void *i2c_handle = NULL; ret = board_manager_get_periph_handle("i2c-0", &i2c_handle); if (ret == ESP_OK && i2c_handle) { // Use i2c_handle for I2C operations ESP_LOGI(TAG, "I2C peripheral handle obtained successfully"); } // Example 2: Get GPIO peripheral handle (already initialized) void *gpio_handle = NULL; ret = board_manager_get_periph_handle("gpio-48", &gpio_handle); if (ret == ESP_OK && gpio_handle) { // Use gpio_handle for GPIO operations ESP_LOGI(TAG, "GPIO peripheral handle obtained successfully"); } // Example 3: Get SD card device handle (already initialized) sdmmc_card_t *card = NULL; ret = board_manager_get_device_handle("sdcard", (void **)&card); if (ret == ESP_OK && card) { // Use card handle for SD card operations ESP_LOGI(TAG, "SD card device handle obtained successfully"); } // Example 4: Get audio DAC device handle (already initialized) dev_audio_codec_handles_t *dac_handles = NULL; ret = board_manager_get_device_handle("audio_dac", (void **)&dac_handles); if (ret == ESP_OK && dac_handles) { // Use dac_handles for audio DAC operations ESP_LOGI(TAG, "Audio DAC device handle obtained successfully"); } // Example 5: Get audio ADC device handle (already initialized) dev_audio_codec_handles_t *adc_handles = NULL; ret = board_manager_get_device_handle("audio_adc", (void **)&adc_handles); if (ret == ESP_OK && adc_handles) { // Use adc_handles for audio ADC operations ESP_LOGI(TAG, "Audio ADC device handle obtained successfully"); } // Cleanup ret = board_manager_deinit(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Board manager deinitialization failed: %d", ret); } else { ESP_LOGI(TAG, "Board manager deinitialized successfully"); } } ``` ## Configuration Files ### Board Peripherals (board_peripherals.yaml) ```yaml peripherals: - name: i2c-0 type: i2c role: master config: port: 0 enable_internal_pullup: true glitch_count: 7 pins: sda: 17 scl: 18 - name: i2s-0-0 type: i2s role: master format: std-out config: sample_rate_hz: 48000 mclk_multiple: 256 bclk_div: 8 data_bit_width: 16 slot_mode: STEREO pins: mclk: 16 bclk: 9 ws: 45 dout: 8 din: 10 ``` ### Board Devices (board_devices.yaml) ```yaml devices: - name: audio_dac chip: es8311 type: audio_codec version: default config: adc_enabled: false dac_enabled: true dac_max_channel: 1 dac_channel_mask: "1" dac_init_gain: 0 mclk_enabled: false aec: false eq: false alc: true peripherals: - name: gpio-48 gain: 6 active_level: 1 - name: i2s-0-0 - name: i2c-0 address: 0x30 frequency: 400000 ``` ## Supported Peripherals | Peripheral | Support Status | Features | |------------|----------------|----------| | **I2C** | ✅ Fully Supported | Master/slave mode, configurable pins, pullup, glitch filter | | **I2S** | ✅ Fully Supported | Standard format, configurable sample rate, bit width, slot mode | | **GPIO** | ✅ Fully Supported | Input/output modes, pullup/pulldown, interrupt configuration | | **SPI** | 🔄 In Development | Master/slave mode, configurable pins, frequency, mode | | **UART** | 🔄 In Development | Configurable baud rate, data bits, stop bits, parity | | **PWM** | 📋 Planned | Configurable frequency, duty cycle, channels | | **ADC** | 📋 Planned | Configurable resolution, channels, attenuation | ## Supported Boards | Board Name | Description | Chip | Audio | SDCard | LCD | Touch | IMU | |------------|-------------|------|-------|--------|-----|-------|-----| | **ESP32-S3 Korvo2 V3** | ESP32-S3 Korvo2 V3 Development Board | ESP32-S3 | ✅ ES8311 + ES7210 | ✅ SDMMC | ❌ | ❌ | ❌ | | **ESP32-S3 Korvo2L** | ESP32-S3 Korvo 2L | ESP32-S3 | ✅ ES8311 | ✅ SDMMC | ❌ | ❌ | ❌ | | **ESP32 Lyrat Mini V1.1** | ESP32 Lyrat Mini V1.1 Development Board | ESP32 | ❌ | ✅ SDMMC | ❌ | ❌ | ❌ | | **ESP32-C5 Spot** | ESP32-C5 Spot AI Voice Interaction Module | ESP32-C5 | ✅ ES8311 (Dual) | ❌ | ❌ | ❌ | ❌ | | **ESP32-C6 DevKit** | ESP32-C6 Development Kit | ESP32-C6 | ❌ | ❌ | ❌ | ❌ | ❌ | | **ESP32-S3 Box Lite** | ESP32-S3 Box Lite | ESP32-S3 | ❌ | ❌ | ❌ | ❌ | ❌ | | **ESP32-P4 Function EV Board** | ESP32-P4 Function Evaluation Board | ESP32-P4 | ❌ | ❌ | ❌ | ❌ | ❌ | | **Echoear Core Board V1.0** | Echoear Core Board V1.0 | ESP32-S3 | ❌ | ❌ | ❌ | ❌ | ❌ | **Legend:** - ✅ **Supported** - Fully implemented and tested - ❌ **Not Supported** - No implementation available - 🔄 **In Development** - Implementation in progress ## Supported Devices | Device Type | Support Status | Supported Models | Features | |-------------|----------------|------------------|----------| | **Audio Codecs** | ✅ Fully Supported | ES8311, ES7210, ES7243, ES8388 | DAC/ADC, gain control, ALC, EQ | | **SD Cards** | ✅ Fully Supported | SD/SDHC/SDXC | SDMMC interface, configurable pins | | **Sensors** | 🔄 In Development | BMI270 (IMU) | I2C/SPI interface, calibration | | **Displays** | 📋 Planned | LCD, OLED | Various interfaces (SPI, I2C, Parallel) | | **Custom Devices** | ✅ Extensible | User-defined | Parser system for custom implementations | ## Extending the System ### Adding New Peripheral Types 1. Create parser in `peripherals`: ```python # peripherals/parse_my_periph.py def parse_my_periph(config): # Parse configuration and return C structure return { 'port': config.get('port', 0), 'frequency': config.get('frequency', 1000000), # ... other fields } ``` 2. Register in `peripheral_parser.py`: ```python from peripherals.parse_my_periph import parse_my_periph PERIPHERAL_PARSERS = { 'my_periph': parse_my_periph, # ... existing parsers } ``` ### Adding New Device Types 1. Create parser in `devices`: ```python # devices/parse_my_device.py def parse_my_device(config, peripherals): # Parse device configuration return { 'device_type': 'MY_DEVICE', 'config': config, 'peripherals': peripherals } ``` 2. Register in `device_parser.py`: ```python from devices.parse_my_device import parse_my_device DEVICE_PARSERS = { 'my_device': parse_my_device, # ... existing parsers } ``` ## Build System Integration The board manager integrates seamlessly with ESP-IDF build system: - **Automatic code generation** during build process - **Menuconfig integration** for board selection - **Component-based architecture** for easy integration - **CMake support** for custom board paths ## Error Handling The system provides comprehensive error handling: - **Board not found**: Detailed error with available boards list - **Missing configuration files**: Clear error messages with file paths - **Invalid configurations**: Validation with helpful error messages - **Runtime errors**: ESP-IDF error codes with descriptive messages ## Testing Run the test suite: ```bash cd board_manager python test_main.py ``` The test suite covers: - Board directory scanning - SDKConfig parsing - Configuration file validation - Code generation verification ## Examples See the `main/` directory for complete example applications demonstrating: - Basic board manager usage - Audio codec initialization - SD card operations - Custom device integration ## Contributing 1. Follow the existing code structure and naming conventions 2. Add tests for new features 3. Update documentation for new peripherals/devices 4. Ensure backward compatibility ## License This project is licensed under the Espressif Modified MIT License - see the LICENSE file for details.
idf.py add-dependency "jason-mao/gmf_board_manager^0.1.1"