generated from sirlilpanda/kicad-project-template-actionless
Added the zig_main project to software for zig based implementation of code for robot
This commit is contained in:
341
software/zig_main/docs/build-internals.md
Normal file
341
software/zig_main/docs/build-internals.md
Normal file
@@ -0,0 +1,341 @@
|
||||
## How does the mixin build-system work?
|
||||
|
||||
#### Intro
|
||||
|
||||
ESP-IDF uses the `idf.py` script as a wrapper around CMake. It's responsible for creating the build environment, running CMake to generate build files, and using Ninja to build the project.
|
||||
|
||||
The Zig build system (`build.zig`) is a wrapper around the Zig compiler and integrates with ESP-IDF's CMake infrastructure.
|
||||
|
||||
For more details about Zig commands, see [doc/zig-xtensa](zig-xtensa.md)
|
||||
|
||||
#### Building this project
|
||||
|
||||
After cloning this project, you need to install ESP-IDF and set up the environment:
|
||||
|
||||
1. **Install ESP-IDF** by following the official guide:
|
||||
- Clone ESP-IDF repository:
|
||||
```bash
|
||||
git clone --recursive https://github.com/espressif/esp-idf.git
|
||||
```
|
||||
- Run the installation script:
|
||||
- Windows: `install.bat` or `install.ps1`
|
||||
- POSIX: `./install.sh`
|
||||
|
||||
2. **Set up the ESP-IDF environment variables:**
|
||||
- Windows: run `export.bat` or `./export.ps1`
|
||||
- POSIX: `. ./export.sh`
|
||||
|
||||
Once the environment is set up, you can build the project using this scheme:
|
||||
|
||||

|
||||
|
||||
3. **Set the target ESP device** (if not already set):
|
||||
|
||||
```bash
|
||||
idf.py set-target <esp-device>
|
||||
```
|
||||
|
||||
**Supported targets:**
|
||||
- RISC-V: `esp32c2`, `esp32c3`, `esp32c5`, `esp32c6`, `esp32c61`, `esp32c61eco0`, `esp32h2`, `esp32h21`, `esp32h4`, `esp32s31`, `esp32p4`, `esp32p4eco4`
|
||||
- Xtensa: `esp32`, `esp32s2`, `esp32s3`
|
||||
|
||||
4. **Add managed components** (optional):
|
||||
```bash
|
||||
idf.py add-dependency espressif/led_strip
|
||||
idf.py add-dependency espressif/esp-dsp
|
||||
```
|
||||
|
||||
Managed components are automatically detected during build and their headers are included in the Zig bindings.
|
||||
|
||||
5. **Build the project:**
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
This will:
|
||||
- Configure CMake and detect managed components
|
||||
- Download/use appropriate Zig toolchain (espressif or upstream)
|
||||
- Generate `idf-sys.zig` bindings via `translate-c`
|
||||
- Apply target-specific patches
|
||||
- Build Zig code into object files
|
||||
- Link everything with ESP-IDF components
|
||||
|
||||
6. **Flash the firmware to your device:**
|
||||
```bash
|
||||
idf.py -p PORT flash
|
||||
```
|
||||
Replace `PORT` with your device's serial port (e.g., `COM3` on Windows or `/dev/ttyUSB0` on Linux)
|
||||
|
||||
7. **Monitor the device output:**
|
||||
```bash
|
||||
idf.py monitor
|
||||
```
|
||||
|
||||
**Additional useful commands:**
|
||||
- Clean the project: `idf.py clean`
|
||||
- Full clean and rebuild: `idf.py fullclean`
|
||||
- Build and flash in one command: `idf.py -p PORT flash monitor`
|
||||
- Show all targets: `idf.py --list-targets`
|
||||
- Configure project: `idf.py menuconfig`
|
||||
- Reconfigure (refresh component detection): `idf.py reconfigure`
|
||||
|
||||
---
|
||||
|
||||
### Current role of `build.zig`
|
||||
|
||||
Since the latest refactors (post [#37](https://github.com/kassane/zig-esp-idf-sample/pull/37) and related CMake changes), `build.zig` is **focused exclusively on Zig code compilation**:
|
||||
|
||||
**What `build.zig` handles:**
|
||||
- Defines Zig modules:
|
||||
- `esp_idf` → High-level facade module that re-exports safe wrappers from `imports/*.zig` (gpio, wifi, heap, rtos, led, etc.)
|
||||
- `sys` → Low-level module that imports the generated `idf-sys.zig` (raw C bindings)
|
||||
- Collects and compiles Zig source files
|
||||
- Uses pre-generated includes and dependencies from CMake
|
||||
- Generates object files (`app_zig.o`) that CMake links with ESP-IDF
|
||||
|
||||
**What has moved to CMake:**
|
||||
- Searching and linking IDF object files and `.a` libraries → handled by ESP-IDF's CMake system
|
||||
- Collecting include paths from IDF components → automatic via `zig-config.cmake`
|
||||
- Running `translate-c` on `stubs.h` to generate `idf-sys.zig` → fully automated in `cmake/` scripts
|
||||
- Applying target-specific patches → handled by `cmake/patch.cmake`
|
||||
- Detecting and including managed components → automatic detection in `zig-config.cmake`
|
||||
- Toolchain selection (espressif vs upstream Zig) → automatic based on target architecture
|
||||
|
||||
**This separation makes the project cleaner:**
|
||||
- **CMake** handles the complex C/ESP-IDF world (toolchain, bindings generation, component management)
|
||||
- **Zig** handles only modern, safe, comptime-friendly code compilation
|
||||
|
||||
---
|
||||
|
||||
### Managed Components Integration
|
||||
|
||||
The build system automatically detects managed components installed via `idf.py add-dependency`:
|
||||
|
||||
**Add extra-components like:**
|
||||
- `espressif/led_strip` → `HAS_LED_STRIP` define
|
||||
- `espressif/esp-dsp` → `HAS_ESP_DSP` define
|
||||
- `espressif/esp_bsp_devkit` → `HAS_ESP_BSP_DEVKIT` define
|
||||
|
||||
**How it works:**
|
||||
1. CMake detects components in `managed_components/` directory
|
||||
2. Adds component include paths to `INCLUDE_DIRS`
|
||||
3. Generates preprocessor defines (e.g., `HAS_LED_STRIP=1`)
|
||||
4. Passes defines to `translate-c` for binding generation
|
||||
5. Headers are conditionally included in `include/stubs.h`:
|
||||
```c
|
||||
#if HAS_LED_STRIP
|
||||
#include "led_strip.h"
|
||||
#endif
|
||||
```
|
||||
|
||||
**To add a new managed component:**
|
||||
1. Run: `idf.py add-dependency vendor/component`
|
||||
2. Add detection in `extra-components.cmake`:
|
||||
```cmake
|
||||
check_managed_component("Component Name" "vendor" "component" "HAS_COMPONENT")
|
||||
```
|
||||
3. Add conditional include in `include/stubs.h`
|
||||
4. Use in Zig via the wrapped API in `imports/`
|
||||
|
||||
---
|
||||
|
||||
### Toolchain Selection
|
||||
|
||||
The build system intelligently selects the appropriate Zig toolchain:
|
||||
|
||||
**RISC-V targets (all variants including H4/P4):**
|
||||
- Works with both **upstream Zig** and **Espressif's Zig fork**
|
||||
- Upstream Zig: uses generic `riscv32-freestanding-none` with feature flags (e.g. `+m+a+c+zicsr+zifencei`)
|
||||
- Espressif fork: uses named CPU models (e.g. `esp32c6`, `esp32p4`) with exact feature sets
|
||||
- Build system auto-detects which toolchain is in use and selects the right CPU model
|
||||
|
||||
**Xtensa targets (ESP32, ESP32-S2, ESP32-S3):**
|
||||
- Always uses **Espressif's Zig fork** (Xtensa support not in upstream)
|
||||
|
||||
The toolchain is automatically downloaded and cached in `build/zig-relsafe-*` if not found.
|
||||
|
||||
---
|
||||
|
||||
### Advanced: Build System Internals
|
||||
|
||||
For advanced users who want to understand or modify the build system:
|
||||
|
||||
**Key CMake files:**
|
||||
- `cmake/zig-config.cmake` → Main configuration, target detection, component discovery
|
||||
- `cmake/zig-download.cmake` → Automatic Zig toolchain download
|
||||
- `cmake/zig-runner.cmake` → Helper functions for running Zig commands
|
||||
- `cmake/bindings.cmake` → get esp-rs/esp-idf-sys bindings header
|
||||
- `cmake/extra-components.cmake` → helper to add more components
|
||||
- `cmake/patch.cmake` → Post-processing patches for generated bindings
|
||||
|
||||
**Bindings generation flow:**
|
||||
1. CMake collects all IDF component include paths
|
||||
2. Detects managed components and adds their paths
|
||||
3. Runs `zig translate-c` on `include/stubs.h` with all includes
|
||||
4. Generates `imports/idf-sys.zig` with raw C bindings
|
||||
5. Applies target-specific patches (ESP32-H2, H4, P4)
|
||||
6. Zig code imports via `@import("sys")` or high-level `@import("esp_idf")`
|
||||
|
||||
**Zig module structure:**
|
||||
```
|
||||
imports/
|
||||
├── idf-sys.zig # Generated C bindings (don't edit manually)
|
||||
├── esp_idf.zig # Main facade module
|
||||
├── gpio.zig # GPIO wrapper
|
||||
├── wifi.zig # WiFi wrapper
|
||||
├── heap.zig # Heap allocators
|
||||
├── rtos.zig # FreeRTOS wrappers
|
||||
├── led-strip.zig # LED strip wrapper (requires HAS_LED_STRIP)
|
||||
└── ... # Other high-level wrappers
|
||||
```
|
||||
|
||||
**In your Zig code:**
|
||||
```zig
|
||||
const idf = @import("esp_idf");
|
||||
const sys = idf.sys; // Access raw C bindings if needed
|
||||
const led = idf.led; // Use wrapped APIs (recommended)
|
||||
```
|
||||
|
||||
This architecture allows safe, idiomatic Zig code while maintaining full access to ESP-IDF's C APIs when necessary.
|
||||
|
||||
### Build Scheme Graph
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ ESP-IDF Build System │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ idf.py │
|
||||
│ (Python) │
|
||||
└───────┬───────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
▼ ▼
|
||||
┌───────────────┐ ┌──────────────────┐
|
||||
│ set-target │ │ add-dependency │
|
||||
│ (esp32c6) │ │ (managed_comps) │
|
||||
└───────┬───────┘ └────────┬─────────┘
|
||||
│ │
|
||||
└──────────────┬──────────────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ CMake │
|
||||
│ Configure │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌─────────────────────────┼─────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────────┐ ┌─────────────────────┐ ┌──────────────────┐
|
||||
│ ESP-IDF │ │ zig-config.cmake │ │ Component │
|
||||
│ Components │ │ • Detect target │ │ Detection │
|
||||
│ (.a libs) │ │ • Find toolchain │ │ (managed_comps) │
|
||||
└──────┬───────┘ │ • Collect includes │ └────────┬─────────┘
|
||||
│ │ • Check components │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────▼──────────┐ │
|
||||
│ │ bindings.cmake │ │
|
||||
│ │ • Build INCLUDE │◄────────────┘
|
||||
│ │ list with │
|
||||
│ │ managed_comps │
|
||||
│ │ • Generate defines │
|
||||
│ │ (HAS_COMP_NAME) │
|
||||
│ └──────────┬──────────┘
|
||||
│ │
|
||||
│ ┌──────────▼──────────┐
|
||||
│ │ zig translate-c │
|
||||
│ │ stubs.h → │
|
||||
│ │ idf-sys.zig │
|
||||
│ └──────────┬──────────┘
|
||||
│ │
|
||||
│ ┌──────────▼──────────┐
|
||||
│ │ patch.cmake │
|
||||
│ │ • Fix bitfields │
|
||||
│ │ • Target patches │
|
||||
│ │ (H2, H4, P4) │
|
||||
│ └──────────┬──────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌─────────────────────┐
|
||||
│ │ build.zig │◄─────────┐
|
||||
│ │ • Import idf-sys │ │
|
||||
│ │ • Define modules: │ │
|
||||
│ │ - esp_idf │ │
|
||||
│ │ - sys │ │
|
||||
│ │ • Compile Zig │ │
|
||||
│ │ sources │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Zig Compiler │ │
|
||||
│ │ (upstream or │ │
|
||||
│ │ espressif fork) │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ app_zig.o │ │
|
||||
│ │ (Zig object) │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
└───────────────────────┼─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Ninja / Make │
|
||||
│ Link all objects │
|
||||
│ + ESP-IDF libs │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ ELF Binary │
|
||||
│ ├─ bootloader.bin │
|
||||
│ ├─ partition.bin │
|
||||
│ └─ app.bin │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ idf.py flash │
|
||||
│ (esptool.py) │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐
|
||||
│ ESP32 │
|
||||
│ Device │
|
||||
└──────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Key Data Flows │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ 1. Component Discovery: CMake → managed_components/ → HAS_* defines │
|
||||
│ 2. Binding Generation: stubs.h + includes → translate-c → idf-sys.zig │
|
||||
│ 3. Zig Compilation: build.zig → zig build-obj → app_zig.o │
|
||||
│ 4. Final Link: ESP-IDF .a libs + app_zig.o → firmware.elf │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
### Led-dtrip component e.g:
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Managed Components Flow │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ idf.py add-dependency espressif/led_strip │
|
||||
│ ↓ │
|
||||
│ managed_components/espressif__led_strip/ │
|
||||
│ ↓ │
|
||||
│ zig-config.cmake detects component │
|
||||
│ ↓ │
|
||||
│ Adds: -DHAS_LED_STRIP=1 -I.../espressif__led_strip/include │
|
||||
│ ↓ │
|
||||
│ stubs.h: #if HAS_LED_STRIP → #include "led_strip.h" │
|
||||
│ ↓ │
|
||||
│ translate-c generates bindings │
|
||||
│ ↓ │
|
||||
│ Zig code: const led = @import("esp_idf").led; │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
BIN
software/zig_main/docs/build-scheme.png
Normal file
BIN
software/zig_main/docs/build-scheme.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
820
software/zig_main/docs/getting-started.md
Normal file
820
software/zig_main/docs/getting-started.md
Normal file
@@ -0,0 +1,820 @@
|
||||
# Getting Started with Zig ESP-IDF Sample
|
||||
|
||||
A complete guide to building ESP32 firmware using Zig and ESP-IDF.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Installation](#installation)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Project Structure](#project-structure)
|
||||
- [Building Your First Project](#building-your-first-project)
|
||||
- [Working with Components](#working-with-components)
|
||||
- [Examples](#examples)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Next Steps](#next-steps)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Required Software
|
||||
|
||||
- **Python 3.12+** (for ESP-IDF tools)
|
||||
- **Git** (for cloning repositories)
|
||||
- **CMake 3.16+** (bundled with ESP-IDF)
|
||||
- **Ninja** or **Make** (bundled with ESP-IDF)
|
||||
- **Zig compiler** (optional - will be auto-downloaded if not found)
|
||||
|
||||
### Supported Operating Systems
|
||||
|
||||
- **Linux** (Ubuntu 20.04+, Debian, Fedora, Arch)
|
||||
- **macOS** (10.15+)
|
||||
- **Windows** (10/11 with PowerShell or WSL2)
|
||||
- **Nix/NixOS** (via `flake.nix`)
|
||||
|
||||
### Supported ESP32 Targets
|
||||
|
||||
| Architecture | Targets |
|
||||
|--------------|---------|
|
||||
| **RISC-V** | ESP32-C2, C3, C5, C6, C61, H2, H21, H4, P4 |
|
||||
| **Xtensa** | ESP32, ESP32-S2, ESP32-S3 |
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Step 1: Install ESP-IDF
|
||||
|
||||
**Option A: Standard Installation**
|
||||
|
||||
```bash
|
||||
# Clone ESP-IDF
|
||||
git clone --recursive https://github.com/espressif/esp-idf.git
|
||||
cd esp-idf
|
||||
|
||||
# Linux/macOS:
|
||||
./install.sh
|
||||
|
||||
# Windows (PowerShell):
|
||||
.\install.ps1
|
||||
|
||||
# Windows (Command Prompt):
|
||||
install.bat
|
||||
```
|
||||
|
||||
**Option B: Using Nix Flakes** (Linux/macOS)
|
||||
|
||||
```bash
|
||||
# Enter development environment with all dependencies
|
||||
nix develop
|
||||
|
||||
# Or use direnv for automatic activation
|
||||
echo "use flake" > .envrc
|
||||
direnv allow
|
||||
```
|
||||
|
||||
**Option C: ESP-IDF installer** (Windows/macOS)
|
||||
|
||||
Download from: https://dl.espressif.com/dl/esp-idf/
|
||||
|
||||
### Step 2: Set up ESP-IDF Environment
|
||||
|
||||
Every time you open a new terminal, activate ESP-IDF:
|
||||
|
||||
```bash
|
||||
# Linux/macOS:
|
||||
. $HOME/esp/esp-idf/export.sh
|
||||
|
||||
# Windows (PowerShell):
|
||||
. $HOME/esp/esp-idf/export.ps1
|
||||
|
||||
# Windows (Command Prompt):
|
||||
%USERPROFILE%\esp\esp-idf\export.bat
|
||||
```
|
||||
|
||||
### Step 3: Clone This Project
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kassane/zig-esp-idf-sample.git
|
||||
cd zig-esp-idf-sample
|
||||
```
|
||||
|
||||
### Step 4: Verify Installation
|
||||
|
||||
```bash
|
||||
idf.py --version
|
||||
# Expected output: ESP-IDF v5.x.x or v6.x.x
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Set Your Target Device
|
||||
|
||||
```bash
|
||||
# For ESP32-C6 (RISC-V)
|
||||
idf.py set-target esp32c6
|
||||
|
||||
# For ESP32-S3 (Xtensa)
|
||||
idf.py set-target esp32s3
|
||||
|
||||
# For ESP32 (original, Xtensa)
|
||||
idf.py set-target esp32
|
||||
```
|
||||
|
||||
### 2. Build the Project
|
||||
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
**What happens during build:**
|
||||
- ✅ CMake detects your target and configures the build
|
||||
- ✅ Zig toolchain is automatically downloaded (if needed)
|
||||
- ✅ C bindings are generated from ESP-IDF headers
|
||||
- ✅ Target-specific patches are applied
|
||||
- ✅ Zig code is compiled to object files
|
||||
- ✅ Everything is linked with ESP-IDF libraries
|
||||
- ✅ Firmware binaries are generated
|
||||
|
||||
### 3. Flash to Device
|
||||
|
||||
```bash
|
||||
# Connect your ESP32 via USB, then:
|
||||
idf.py -p PORT flash
|
||||
|
||||
# Find your port:
|
||||
# Linux: /dev/ttyUSB0 or /dev/ttyACM0
|
||||
# macOS: /dev/cu.usbserial-*
|
||||
# Windows: COM3, COM4, etc.
|
||||
|
||||
# Example:
|
||||
idf.py -p /dev/ttyUSB0 flash
|
||||
```
|
||||
|
||||
### 4. Monitor Output
|
||||
|
||||
```bash
|
||||
idf.py -p PORT monitor
|
||||
|
||||
# Or combine flash + monitor:
|
||||
idf.py -p PORT flash monitor
|
||||
|
||||
# Exit monitor: Ctrl+]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
zig-esp-idf-sample/
|
||||
├── build.zig # Zig build script (compiles Zig code)
|
||||
├── build.zig.zon # Zig package manifest
|
||||
├── CMakeLists.txt # Root CMake config
|
||||
├── sdkconfig # ESP-IDF configuration (generated)
|
||||
├── sdkconfig.defaults # Default SDK config
|
||||
├── sdkconfig.defaults.esp32 # ESP32-specific defaults
|
||||
├── partitions_matter.csv # Custom partition table for Matter (3 MB app, 4 MB flash)
|
||||
├── dependencies.lock # Component version lock
|
||||
├── wokwi.toml # Wokwi simulator config
|
||||
│
|
||||
├── main/
|
||||
│ ├── CMakeLists.txt # Main component config
|
||||
│ ├── placeholder.c # Minimal C entry point (required by CMake)
|
||||
│ ├── matter_wrappers.cpp # C++ shims for esp_matter C++ API (activated when component present)
|
||||
│ ├── app.zig # Main Zig application entry
|
||||
│ ├── idf_component.yml # Component dependencies
|
||||
│ ├── Kconfig.projbuild # Project configuration options
|
||||
│ └── examples/
|
||||
│ ├── gpio-blink.zig # Toggle LED on GPIO2
|
||||
│ ├── uart-echo.zig # UART echo
|
||||
│ ├── i2c-scan.zig # I2C bus scan
|
||||
│ ├── wifi-station.zig # WiFi station
|
||||
│ ├── http-server.zig # HTTP server
|
||||
│ ├── ble-gatt-server.zig # BLE GATT server
|
||||
│ ├── smartled-rgb.zig # WS2812B LED strip
|
||||
│ ├── dsp-math.zig # DSP/FFT operations
|
||||
│ └── matter-light.zig # Matter On/Off Light
|
||||
│
|
||||
├── imports/ # Zig API wrappers and bindings
|
||||
│ ├── idf.zig # Main ESP-IDF facade module
|
||||
│ ├── idf-sys.zig # Generated C bindings (auto-generated)
|
||||
│ ├── sys.zig # Re-exports idf-sys
|
||||
│ ├── error.zig # esp_err_t → Zig error mapping
|
||||
│ ├── logger.zig # std.log integration (espLogFn)
|
||||
│ ├── version.zig # ESP-IDF version info (ver)
|
||||
│ ├── heap.zig # HeapCapsAllocator, MultiHeapAllocator
|
||||
│ ├── bootloader.zig # Partition/bootloader control
|
||||
│ ├── gpio.zig # GPIO wrapper
|
||||
│ ├── wifi.zig # WiFi station/AP/scan
|
||||
│ ├── uart.zig # UART driver
|
||||
│ ├── i2c.zig # I2C master
|
||||
│ ├── spi.zig # SPI master (+ SDSPI)
|
||||
│ ├── i2s.zig # I2S audio (STD, PDM, TDM)
|
||||
│ ├── http.zig # HTTP server + client
|
||||
│ ├── mqtt.zig # MQTT client
|
||||
│ ├── lwip.zig # lwIP sockets, DNS, SNTP
|
||||
│ ├── crc.zig # ESP-ROM CRC-8/16/32
|
||||
│ ├── bluetooth.zig # Bluedroid BLE
|
||||
│ ├── nimble.zig # NimBLE BLE (compile-time guarded)
|
||||
│ ├── now.zig # ESP-NOW protocol
|
||||
│ ├── nvs.zig # NVS flash key-value storage
|
||||
│ ├── partition.zig # Partition table operations
|
||||
│ ├── sleep.zig # Deep/light sleep + wakeup
|
||||
│ ├── event.zig # ESP event loop
|
||||
│ ├── wdt.zig # Task watchdog timer
|
||||
│ ├── rtos.zig # FreeRTOS tasks/queues/semaphores/timers
|
||||
│ ├── pcnt.zig # Pulse counter (pulse)
|
||||
│ ├── phy.zig # Wireless PHY / RF calibration
|
||||
│ ├── segger.zig # Segger SystemView profiling
|
||||
│ ├── led-strip.zig # LED strip — requires espressif/led_strip
|
||||
│ ├── dsp.zig # DSP/FFT — requires espressif/esp-dsp
|
||||
│ ├── hosted.zig # ESP-Hosted coexistence — requires espressif/esp_hosted
|
||||
│ ├── wifi_remote.zig # WiFi remote — requires espressif/esp_wifi_remote
|
||||
│ ├── timer.zig # High-resolution esp_timer (one-shot + periodic)
|
||||
│ ├── ledc.zig # LED PWM controller (duty, fade)
|
||||
│ ├── twai.zig # TWAI/CAN bus driver
|
||||
│ ├── pm.zig # Power management locks
|
||||
│ ├── pthread.zig # POSIX threads (FreeRTOS-backed)
|
||||
│ └── panic.zig # Zig panic handler
|
||||
│
|
||||
├── include/ # C headers for binding generation
|
||||
│ ├── stubs.h # Core ESP-IDF headers (input to zig translate-c)
|
||||
│ ├── wifi_stubs.h # WiFi macro wrappers
|
||||
│ ├── bt_stubs.h # Bluetooth macro wrappers
|
||||
│ ├── matter_stubs.h # C wrapper interface for esp_matter (C++ component)
|
||||
│ ├── matter_closure_patch.h # GCC 14 C++23 fix for closure-control cluster
|
||||
│ └── bindings.h # Additional bindings
|
||||
│
|
||||
├── cmake/ # CMake build system scripts
|
||||
│ ├── zig-config.cmake # Main Zig configuration
|
||||
│ ├── zig-download.cmake # Auto-download Zig toolchain
|
||||
│ ├── zig-runner.cmake # Helper functions for Zig
|
||||
│ ├── bindings.cmake # Binding generation
|
||||
│ ├── extra-components.cmake # Managed component detection
|
||||
│ └── patch.cmake # Post-processing patches
|
||||
│
|
||||
├── patches/ # Binding fixes for translate-c issues
|
||||
│ ├── *.zig
|
||||
│
|
||||
├── docs/ # Documentation
|
||||
│ ├── build-internals.md # Build system details
|
||||
│ ├── build-scheme.png # Build flow diagram
|
||||
│ └── zig-xtensa.md # Xtensa toolchain info
|
||||
│
|
||||
└── flake.nix # Nix development environment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Building Your First Project
|
||||
|
||||
### Example 1: Hello World
|
||||
|
||||
```zig
|
||||
const std = @import("std");
|
||||
const idf = @import("esp_idf");
|
||||
|
||||
comptime {
|
||||
@export(&main, .{ .name = "app_main" });
|
||||
}
|
||||
|
||||
fn main() callconv(.c) void {
|
||||
log.info("Hello from Zig on ESP32!", .{});
|
||||
log.info("Zig version: {s}", .{@import("builtin").zig_version_string});
|
||||
|
||||
// Show memory info
|
||||
var heap = idf.heap.HeapCapsAllocator.init(null); // default: MALLOC_CAP_DEFAULT
|
||||
log.info("Free heap: {} bytes", .{heap.freeSize()});
|
||||
|
||||
// Sleep forever
|
||||
while (true) {
|
||||
idf.rtos.Task.delayMs(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite zig std_options config
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = idf.log.espLogFn,
|
||||
};
|
||||
// rename log instance
|
||||
const log = std.log.scoped(.@"esp-idf");
|
||||
// overwrite std panic-handler
|
||||
pub const panic = idf.esp_panic.panic;
|
||||
```
|
||||
|
||||
**Build and run:**
|
||||
```bash
|
||||
idf.py build flash monitor
|
||||
```
|
||||
|
||||
### Example 2: Blinking LED
|
||||
|
||||
**Create `main/examples/blink.zig`:**
|
||||
|
||||
```zig
|
||||
const std = @import("std");
|
||||
const idf = @import("esp_idf");
|
||||
|
||||
const LED_PIN = .@"18"; // Change to your LED pin
|
||||
|
||||
comptime {
|
||||
@export(&main, .{ .name = "app_main" });
|
||||
}
|
||||
|
||||
fn main() callconv(.c) void {
|
||||
// Configure GPIO as output
|
||||
idf.gpio.Direction.set(LED_PIN, .output) catch {
|
||||
log.err("Failed to configure GPIO", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
log.info("Blinking LED on GPIO {d}", .{LED_PIN});
|
||||
|
||||
while (true) {
|
||||
// LED ON
|
||||
idf.gpio.Level.set(LED_PIN, 1) catch {};
|
||||
log.info("LED ON", .{});
|
||||
idf.rtos.Task.delayMs(1000);
|
||||
|
||||
// LED OFF
|
||||
idf.gpio.Level.set(LED_PIN, 0) catch {};
|
||||
log.info("LED OFF", .{});
|
||||
idf.rtos.Task.delayMs(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite zig std_options config
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = idf.log.espLogFn,
|
||||
};
|
||||
// rename log instance
|
||||
const log = std.log.scoped(.blink);
|
||||
// overwrite std panic-handler
|
||||
pub const panic = idf.esp_panic.panic;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Working with Components
|
||||
|
||||
### Adding Managed Components
|
||||
|
||||
Components are specified in `main/idf_component.yml`:
|
||||
|
||||
**Add a component:**
|
||||
|
||||
```bash
|
||||
# Use idf.py command:
|
||||
idf.py add-dependency espressif/led_strip
|
||||
# then
|
||||
idf.py reconfigure
|
||||
```
|
||||
|
||||
### Using LED Strip Component
|
||||
|
||||
**The build system automatically:**
|
||||
1. ✅ Detects components in `dependencies.lock`
|
||||
2. ✅ Adds include paths to binding generation
|
||||
3. ✅ Generates `HAS_*` defines (e.g., `HAS_LED_STRIP=1`)
|
||||
4. ✅ Includes headers in `include/stubs.h` conditionally
|
||||
5. ✅ Makes APIs available in Zig via `idf.*` modules
|
||||
|
||||
**1. Ensure LED strip is in `main/idf_component.yml`:**
|
||||
```yaml
|
||||
dependencies:
|
||||
espressif/led_strip: "*"
|
||||
```
|
||||
|
||||
**2. Reconfigure:**
|
||||
```bash
|
||||
idf.py reconfigure
|
||||
```
|
||||
|
||||
**3. Check provided example:**
|
||||
|
||||
The example in [examples/smartled-rgb.zig](../main/examples/smartled-rgb.zig) demonstrates:
|
||||
- Configuring WS2812B LED strip on GPIO 2
|
||||
- Setting individual pixel colors
|
||||
- Refreshing the display
|
||||
- Blinking pattern
|
||||
|
||||
### DSP basics (FFT + math)
|
||||
|
||||
[examples/dsp-math.zig](../main/examples/dsp-math.zig)
|
||||
|
||||
- Generates a sine tone (freq = 0.2 normalized)
|
||||
- Applies Hann window
|
||||
- Does FFT (1024 points, float32, radix-2)
|
||||
- Computes power spectrum in dB
|
||||
- Prints ASCII plot of the spectrum (64×10 chars, -120 to +40 dB)
|
||||
|
||||
### Using WiFi
|
||||
|
||||
**Use the WiFi station example:**
|
||||
[examples/wifi-station.zig](../main/examples/wifi-station.zig)
|
||||
|
||||
**Configure WiFi credentials:**
|
||||
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
# Navigate to: Example Configuration
|
||||
# Set WiFi SSID and Password
|
||||
```
|
||||
|
||||
Or edit [main/Kconfig.projbuild](../main/Kconfig.projbuild) to change default values.
|
||||
|
||||
### Available Wrapper APIs
|
||||
|
||||
The project provides comprehensive Zig wrappers in `imports/`:
|
||||
|
||||
| Module | Description | Notes |
|
||||
|--------|-------------|-------|
|
||||
| `idf.gpio` | GPIO control | Any target |
|
||||
| `idf.wifi` | WiFi station/AP/scan | Not on H2/H4/P4 |
|
||||
| `idf.bt` | Bluedroid BLE | Requires `CONFIG_BT_ENABLED` |
|
||||
| `idf.nimble` | NimBLE BLE | Requires `CONFIG_BT_NIMBLE_ENABLED` |
|
||||
| `idf.heap` | HeapCapsAllocator, MultiHeapAllocator | Any target |
|
||||
| `idf.rtos` | FreeRTOS tasks/queues/semaphores/timers | Any target |
|
||||
| `idf.nvs` | NVS flash key-value storage | Any target |
|
||||
| `idf.partition` | Partition table operations | Any target |
|
||||
| `idf.sleep` | Deep/light sleep + wakeup sources | Any target |
|
||||
| `idf.event` | ESP event loop | Any target |
|
||||
| `idf.wdt` | Task watchdog timer | Any target |
|
||||
| `idf.bl` | Bootloader/partition control | Any target |
|
||||
| `idf.i2c` | I2C master | Any target |
|
||||
| `idf.spi` | SPI master + SDSPI | Any target |
|
||||
| `idf.uart` | UART driver | Any target |
|
||||
| `idf.i2s` | I2S audio (STD, PDM, TDM) | Any target |
|
||||
| `idf.http` | HTTP server (httpd) + client | Any target |
|
||||
| `idf.mqtt` | MQTT client | Any target |
|
||||
| `idf.lwip` | lwIP sockets, DNS, SNTP | Any target |
|
||||
| `idf.crc` | ESP-ROM CRC-8/16/32 | Any target |
|
||||
| `idf.esp_now` | ESP-NOW protocol | Any target |
|
||||
| `idf.pulse` | Pulse counter (PCNT) | Any target |
|
||||
| `idf.phy` | Wireless PHY / RF calibration | Any target |
|
||||
| `idf.segger` | Segger SystemView profiling | Any target |
|
||||
| `idf.ver` | ESP-IDF version info | Any target |
|
||||
| `idf.led` | LED strip WS2812B | Requires `espressif/led_strip` |
|
||||
| `idf.dsp` | DSP/FFT operations | Requires `espressif/esp-dsp` |
|
||||
| `idf.esp_hosted` | ESP-Hosted coexistence | Requires `espressif/esp_hosted` |
|
||||
| `idf.wifi_remote` | WiFi via slave MCU | Requires `espressif/esp_wifi_remote` |
|
||||
| `idf.timer` | High-resolution esp_timer | Any target |
|
||||
| `idf.ledc` | LED PWM controller | Any target |
|
||||
| `idf.twai` | TWAI/CAN bus driver | Any target |
|
||||
| `idf.pm` | Power management locks | Any target |
|
||||
| `idf.pthread` | POSIX threads (FreeRTOS-backed) | Any target |
|
||||
| `idf.matter` | Matter/CHIP protocol | Requires `espressif/esp_matter` |
|
||||
| `idf.log` | std.log integration (`espLogFn`) | Any target |
|
||||
| `idf.err` | esp_err_t → Zig error mapping | Any target |
|
||||
| `idf.sys` | Raw C bindings | Direct ESP-IDF API access |
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### FreeRTOS Tasks
|
||||
|
||||
```zig
|
||||
const idf = @import("esp_idf");
|
||||
const std = @import("std");
|
||||
|
||||
// overwrite std panic-handler
|
||||
pub const panic = idf.esp_panic.panic;
|
||||
// overwrite std.log
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = idf.log.espLogFn,
|
||||
};
|
||||
|
||||
export fn myTask(_: ?*anyopaque) callconv(.c) void {
|
||||
const log = std.log.scoped(.task);
|
||||
while (true) {
|
||||
log.info("Task running!", .{});
|
||||
idf.rtos.Task.delayMs(1000);
|
||||
}
|
||||
}
|
||||
|
||||
export fn app_main() callconv(.c) void {
|
||||
_ = idf.rtos.Task.create(myTask, "my_task", 2048, null, 5) catch @panic("Failed to create task");
|
||||
|
||||
// Main task continues...
|
||||
while (true) {
|
||||
idf.rtos.Task.delayMs(1000);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using Custom Allocators
|
||||
|
||||
```zig
|
||||
const idf = @import("esp_idf");
|
||||
const std = @import("std");
|
||||
|
||||
export fn app_main() callconv(.c) void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var list: std.ArrayList(u32) = .empty;
|
||||
defer list.deinit(allocator);
|
||||
|
||||
list.append(allocator, 10) catch {};
|
||||
list.append(allocator, 20) catch {};
|
||||
list.append(allocator, 30) catch {};
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Accessing Raw C APIs
|
||||
|
||||
When wrappers aren't available, use raw bindings:
|
||||
|
||||
```zig
|
||||
const idf = @import("esp_idf");
|
||||
const std = @import("std");
|
||||
const sys = idf.sys;
|
||||
const log = std.log.scoped(.@"esp-idf");
|
||||
|
||||
export fn app_main() callconv(.c) void {
|
||||
var mac_addr: [6]u8 = undefined;
|
||||
|
||||
// Direct ESP-IDF C API call
|
||||
const result = sys.esp_efuse_mac_get_default(&mac_addr);
|
||||
if (result != sys.ESP_OK) {
|
||||
std.log.err("Failed to get MAC address", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("MAC: {X:0>2}:{X:0>2}:{X:0>2}:{X:0>2}:{X:0>2}:{X:0>2}", .{
|
||||
mac_addr[0], mac_addr[1], mac_addr[2],
|
||||
mac_addr[3], mac_addr[4], mac_addr[5],
|
||||
});
|
||||
}
|
||||
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = idf.log.espLogFn,
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Errors
|
||||
|
||||
**"zig: command not found"**
|
||||
- The Zig toolchain should auto-download. Check `build/zig-relsafe-*` directory
|
||||
- Or install manually: https://ziglang.org/download/
|
||||
- For Nix users: `nix develop`
|
||||
|
||||
**"Component not found: espressif__led_strip"**
|
||||
```bash
|
||||
# Check idf_component.yml
|
||||
cat main/idf_component.yml
|
||||
|
||||
# Reconfigure to download components
|
||||
idf.py reconfigure
|
||||
```
|
||||
|
||||
**"translate-c failed"**
|
||||
- Check `include/stubs.h` and `include/wifi_stubs.h` for syntax errors
|
||||
- Ensure managed components exist in `managed_components/`
|
||||
- Check that `HAS_*` defines match components in `cmake/extra-components.cmake`
|
||||
|
||||
**Binding generation errors**
|
||||
- The `patches/` directory contains fixes for common `translate-c` issues
|
||||
- If you see struct layout errors, a patch likely needs updating
|
||||
- Check `cmake/patch.cmake` for how patches are applied
|
||||
|
||||
### Flash Errors
|
||||
|
||||
**"Serial port not found"**
|
||||
```bash
|
||||
# Linux: Add user to dialout group
|
||||
sudo usermod -a -G dialout $USER
|
||||
# Log out and back in
|
||||
|
||||
# Check available ports
|
||||
ls /dev/tty*
|
||||
|
||||
# Windows: Check Device Manager for COM port
|
||||
```
|
||||
|
||||
**"Failed to connect to ESP32"**
|
||||
- Hold BOOT button while connecting
|
||||
- Try different USB cable/port (must be data cable, not power-only)
|
||||
- Verify target matches your device: `idf.py set-target esp32c6`
|
||||
- Check USB drivers are installed (CP210x or CH340)
|
||||
|
||||
### Runtime Errors
|
||||
|
||||
**"Guru Meditation Error: Core panic"**
|
||||
- Check stack size (increase in `xTaskCreate`, default 2048 often too small)
|
||||
- Verify GPIO pins match your hardware
|
||||
- Enable debug build: `idf.py menuconfig` → Compiler options → Debug (-Og)
|
||||
- Check `sdkconfig` for panic handler settings
|
||||
|
||||
**"Out of memory" / Heap errors**
|
||||
- Use arena allocators: `std.heap.ArenaAllocator`
|
||||
- Check available heap: `heap.freeSize()`
|
||||
- Reduce allocations in hot paths
|
||||
- Consider enabling PSRAM if available
|
||||
- Check `idf.py size-components` for memory usage
|
||||
|
||||
**WiFi not connecting**
|
||||
- Verify SSID and password in menuconfig
|
||||
- Check WiFi country code matches your region
|
||||
- Ensure 2.4GHz WiFi (5GHz not supported)
|
||||
- Check WiFi credentials don't contain special characters
|
||||
|
||||
**Matter example: "app partition is too small"**
|
||||
|
||||
The Matter binary is ~2.2 MB and requires a 4 MB flash chip and custom partition table:
|
||||
```bash
|
||||
# Ensure sdkconfig has 4 MB flash and custom partition:
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
# CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
# CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_matter.csv"
|
||||
|
||||
# If sdkconfig doesn't reflect sdkconfig.defaults changes, update it:
|
||||
idf.py reconfigure
|
||||
idf.py build -DCONFIG_ZIG_EXAMPLE_MATTER_LIGHT=y
|
||||
```
|
||||
|
||||
**Matter example: IDF version incompatibility**
|
||||
- `espressif/esp_matter` 1.4.x requires IDF **v5.x** (tested with v5.5)
|
||||
- Not compatible with IDF v6.x (depends on `json`/`mqtt` components removed in v6)
|
||||
- Check your IDF version: `idf.py --version`
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Learn More
|
||||
|
||||
- **Zig Language:** https://ziglang.org/documentation/master/
|
||||
- **ESP-IDF Docs:** https://docs.espressif.com/projects/esp-idf/
|
||||
- **Project Wiki:**
|
||||
- [Build Internals](./build-internals.md)
|
||||
- [Xtensa Toolchain](./zig-xtensa.md)
|
||||
|
||||
### Explore Examples
|
||||
|
||||
All examples are in `main/examples/`:
|
||||
- `gpio-blink.zig` - Toggle an LED on GPIO2 (any target)
|
||||
- `uart-echo.zig` - Read UART1 and echo back
|
||||
- `i2c-scan.zig` - Scan I2C bus for devices
|
||||
- `wifi-station.zig` - Connect to a WiFi AP
|
||||
- `http-server.zig` - Serve a web page over WiFi
|
||||
- `ble-gatt-server.zig` - BLE peripheral with GATT notifications (requires `CONFIG_BT_ENABLED`)
|
||||
- `smartled-rgb.zig` - WS2812B LED strip control (requires `espressif/led_strip`)
|
||||
- `dsp-math.zig` - FFT + power spectrum via DSP (requires `espressif/esp-dsp`)
|
||||
- `matter-light.zig` - Matter On/Off Light device (requires `espressif/esp_matter`, IDF v5.x, 4 MB flash)
|
||||
|
||||
### Configuration
|
||||
|
||||
```bash
|
||||
# Interactive configuration menu
|
||||
idf.py menuconfig
|
||||
|
||||
# Key settings to explore:
|
||||
# - Component config → FreeRTOS → Tick rate (Hz)
|
||||
# - Component config → ESP System Settings → Panic handler behavior
|
||||
# - Partition Table → Choose partition scheme
|
||||
# - Example Configuration → WiFi credentials
|
||||
# - Compiler options → Optimization level
|
||||
```
|
||||
|
||||
### Testing with Wokwi Simulator
|
||||
|
||||
The project includes `wokwi.toml` for simulation:
|
||||
|
||||
1. Install Wokwi CLI: https://docs.wokwi.com/wokwi-ci/idf-wokwi-usage
|
||||
2. Edit `wokwi.toml` to match your project
|
||||
3. Run: `idf.py wokwi --timeout 30000`
|
||||
|
||||
or use VSCode Extension
|
||||
|
||||
* More info: https://docs.wokwi.com/vscode/getting-started
|
||||
|
||||
### Advanced Topics
|
||||
|
||||
- **Custom Components:** Create reusable Zig modules in `imports/`
|
||||
- **WiFi & Networking:** HTTP servers, WebSockets, mDNS
|
||||
- **OTA Updates:** Over-the-air firmware updates
|
||||
- **Bluetooth:** BLE advertising, GATT services
|
||||
- **Deep Sleep:** Ultra-low power modes
|
||||
- **File Systems:** SPIFFS, FAT, LittleFS
|
||||
- **Cryptography:** Hardware-accelerated crypto
|
||||
|
||||
### Development Tips
|
||||
|
||||
**Use `sdkconfig.defaults` for version control:**
|
||||
- Base config: `sdkconfig.defaults`
|
||||
- Target-specific: `sdkconfig.defaults.esp32`
|
||||
- Don't commit `sdkconfig` (it's generated)
|
||||
|
||||
**Debugging:**
|
||||
```bash
|
||||
# Monitor with timestamps
|
||||
idf.py monitor --timestamps
|
||||
|
||||
# Filter logs by tag
|
||||
idf.py monitor --print-filter "tag:app"
|
||||
|
||||
# Save logs to file
|
||||
idf.py monitor | tee output.log
|
||||
```
|
||||
|
||||
**Clean builds when needed:**
|
||||
```bash
|
||||
# Clean Zig cache
|
||||
rm -rf .zig-cache
|
||||
|
||||
# Full CMake clean
|
||||
idf.py fullclean
|
||||
|
||||
# Regenerate bindings
|
||||
idf.py reconfigure
|
||||
```
|
||||
|
||||
### Contributing
|
||||
|
||||
Found a bug or want to contribute?
|
||||
- **GitHub:** https://github.com/kassane/zig-esp-idf-sample
|
||||
- **Issues:** https://github.com/kassane/zig-esp-idf-sample/issues
|
||||
- **Pull Requests:** See [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Common Commands
|
||||
|
||||
```bash
|
||||
# Setup
|
||||
idf.py set-target esp32c6 # Set target device
|
||||
idf.py reconfigure # Regenerate build config / update deps
|
||||
|
||||
# Build
|
||||
idf.py build # Build project
|
||||
idf.py clean # Clean build files
|
||||
idf.py fullclean # Full clean (including config)
|
||||
|
||||
# Flash
|
||||
idf.py -p PORT flash # Flash firmware
|
||||
idf.py -p PORT monitor # Monitor serial output
|
||||
idf.py -p PORT flash monitor # Flash and monitor
|
||||
idf.py -p PORT app-flash # Flash app only (faster)
|
||||
|
||||
# Config
|
||||
idf.py menuconfig # Interactive configuration
|
||||
idf.py size # Show binary sizes
|
||||
idf.py size-components # Component size breakdown
|
||||
|
||||
# Dependencies
|
||||
idf.py add-dependency PKG # Add managed component
|
||||
|
||||
# Help
|
||||
idf.py --help # Show all commands
|
||||
idf.py --list-targets # List supported targets
|
||||
```
|
||||
|
||||
### File Locations
|
||||
|
||||
- **Main app:** `main/app.zig`
|
||||
- **Examples:** `main/examples/*.zig`
|
||||
- **Dependencies:** `main/idf_component.yml`
|
||||
- **Configuration:** `sdkconfig`, `sdkconfig.defaults*`
|
||||
- **Bindings:** `imports/idf-sys.zig` (auto-generated)
|
||||
- **Wrappers:** `imports/*.zig`
|
||||
- **Build scripts:** `cmake/*.cmake`
|
||||
|
||||
### Pin Configuration
|
||||
|
||||
Check your board's pinout:
|
||||
- **GPIO Pins:** Varies by model (ESP32: 0-39, ESP32-C6: 0-30)
|
||||
- **Built-in LED:** Often GPIO 2, 8, or 18
|
||||
- **UART:** Usually GPIO 1 (TX), GPIO 3 (RX)
|
||||
- **I2C:** SDA/SCL pins vary by board
|
||||
- **SPI:** MOSI/MISO/CLK pins vary by board
|
||||
|
||||
### Hardware Requirements
|
||||
|
||||
- **ESP32 Development Board** (any supported variant)
|
||||
- **USB Cable** (must be data cable, not power-only)
|
||||
- **LEDs/Components** (optional, for examples)
|
||||
- **LED Strip WS2812B** (optional, for smartled-rgb example)
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation:** [docs/](.)
|
||||
- **Issues:** https://github.com/kassane/zig-esp-idf-sample/issues
|
||||
- **Discussions:** https://github.com/kassane/zig-esp-idf-sample/discussions
|
||||
184
software/zig_main/docs/zig-xtensa.md
Normal file
184
software/zig_main/docs/zig-xtensa.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Zig for Xtensa (Esp32, Esp8266 and Esp32-S series)
|
||||
|
||||
Like [esp-rs](https://github.com/espressif/rust-esp32-example/blob/main/docs/rust-on-xtensa.md), forked zig toolchain uses **LLVM codegen** for xtensa target.
|
||||
|
||||
**Current version:**
|
||||
|
||||
- **Zig**: v0.16.0 ([bootstrap fork](https://github.com/kassane/zig-espressif-bootstrap))
|
||||
- **LLVM**: v21.1.0 ([espressif-fork](https://github.com/espressif/llvm-project))
|
||||
|
||||
|
||||
### Commands
|
||||
|
||||
**Zig command line interface:**
|
||||
|
||||
- `build-lib`: build static-lib or shared-lib (add `-dynamic` flag);
|
||||
- `build-obj`: build object file, like `clang/gcc -c`.
|
||||
- `build-exe`: build executable
|
||||
- `build`: build-system mode, need `build.zig`.
|
||||
|
||||
**Clang command line interface:**
|
||||
|
||||
- `zig cc`: clang CLI
|
||||
- `zig c++`: clang++ CLI (uses `llvm-libc++` + `llvm-libunwind` by default)
|
||||
|
||||
**Note:** Zig toolchain does not change `libclang` codegen. However, the default config uses `-fsanitize=undefined`.
|
||||
|
||||
### Targets available
|
||||
|
||||
```bash
|
||||
$> zig build-lib --show-builtin -target xtensa-freestanding-none -mcpu=(empty or any text)
|
||||
|
||||
info: available CPUs for architecture 'xtensa':
|
||||
cnl
|
||||
esp32
|
||||
esp32s2
|
||||
esp32s3
|
||||
esp8266
|
||||
generic
|
||||
|
||||
error: unknown CPU: ''
|
||||
```
|
||||
|
||||
**Note:** Freestanding targets are not listed on `zig targets | jq .libc` (triple-targets)
|
||||
|
||||
#### CPU Features
|
||||
|
||||
Similar to [Targets available](#targets-available) command, add `-mcpu` or `-Dcpu=` (need `build.zig`).
|
||||
|
||||
- `+` add feature
|
||||
- `-` remove feature
|
||||
|
||||
**Note:** For show feature list add `+`/`-` without feature name
|
||||
|
||||
**e.g.:**
|
||||
```bash
|
||||
$> zig build-lib --show-builtin -target xtensa-freestanding-none -mcpu=esp32+
|
||||
|
||||
info: available CPU features for architecture 'xtensa':
|
||||
bool: Enable Xtensa Boolean extension
|
||||
clamps: Enable Xtensa CLAMPS option
|
||||
coprocessor: Enable Xtensa Coprocessor option
|
||||
dcache: Enable Xtensa Data Cache option
|
||||
debug: Enable Xtensa Debug option
|
||||
density: Enable Density instructions
|
||||
dfpaccel: Enable Xtensa Double Precision FP acceleration
|
||||
div32: Enable Xtensa Div32 option
|
||||
esp32s2ops: Support Xtensa esp32-s2 ISA extension
|
||||
esp32s3ops: Support Xtensa esp32-s3 ISA extension
|
||||
exception: Enable Xtensa Exception option
|
||||
extendedl32r: Enable Xtensa Extended L32R option
|
||||
forced_atomics: Assume that lock-free native-width atomics are available
|
||||
fp: Enable Xtensa Single FP instructions
|
||||
hifi3: Enable Xtensa HIFI3 instructions
|
||||
highpriinterrupts: Enable Xtensa HighPriInterrupts option
|
||||
highpriinterrupts_level3: Enable Xtensa HighPriInterrupts Level3
|
||||
highpriinterrupts_level4: Enable Xtensa HighPriInterrupts Level4
|
||||
highpriinterrupts_level5: Enable Xtensa HighPriInterrupts Level5
|
||||
highpriinterrupts_level6: Enable Xtensa HighPriInterrupts Level6
|
||||
highpriinterrupts_level7: Enable Xtensa HighPriInterrupts Level7
|
||||
interrupt: Enable Xtensa Interrupt option
|
||||
loop: Enable Xtensa Loop extension
|
||||
mac16: Enable Xtensa MAC16 instructions
|
||||
minmax: Enable Xtensa MINMAX option
|
||||
miscsr: Enable Xtensa Miscellaneous SR option
|
||||
mul16: Enable Xtensa Mul16 option
|
||||
mul32: Enable Xtensa Mul32 option
|
||||
mul32high: Enable Xtensa Mul32High option
|
||||
nsa: Enable Xtensa NSA option
|
||||
prid: Enable Xtensa Processor ID option
|
||||
regprotect: Enable Xtensa Region Protection option
|
||||
rvector: Enable Xtensa Relocatable Vector option
|
||||
s32c1i: Enable Xtensa S32C1I option
|
||||
sext: Enable Xtensa Sign Extend option
|
||||
threadptr: Enable Xtensa THREADPTR option
|
||||
timers1: Enable Xtensa Timers 1
|
||||
timers2: Enable Xtensa Timers 2
|
||||
timers3: Enable Xtensa Timers 3
|
||||
windowed: Enable Xtensa Windowed Register option
|
||||
|
||||
error: unknown CPU feature: ''
|
||||
```
|
||||
|
||||
|
||||
#### Target info (builtin)
|
||||
|
||||
**Note:** If like syntax-highlighting use `| bat -p -l zig` pipeline command or save this output as `builtin.zig` and open on your code editor.
|
||||
|
||||
```bash
|
||||
$> zig build-lib --show-builtin -target xtensa-freestanding-none -mcpu=esp32s3
|
||||
```
|
||||
```zig
|
||||
const std = @import("std");
|
||||
/// Zig version. When writing code that supports multiple versions of Zig, prefer
|
||||
/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
|
||||
pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
|
||||
pub const zig_version_string = "0.16.0-xtensa-dev.2287+eb3f16db5";
|
||||
pub const zig_backend = std.builtin.CompilerBackend.stage2_llvm;
|
||||
|
||||
pub const output_mode: std.builtin.OutputMode = .Lib;
|
||||
pub const link_mode: std.builtin.LinkMode = .static;
|
||||
pub const unwind_tables: std.builtin.UnwindTables = .async;
|
||||
pub const is_test = false;
|
||||
pub const single_threaded = false;
|
||||
pub const abi: std.Target.Abi = .none;
|
||||
pub const cpu: std.Target.Cpu = .{
|
||||
.arch = .xtensa,
|
||||
.model = &std.Target.xtensa.cpu.esp32s3,
|
||||
.features = std.Target.xtensa.featureSet(&.{
|
||||
.bool,
|
||||
.clamps,
|
||||
.coprocessor,
|
||||
.dcache,
|
||||
.debug,
|
||||
.density,
|
||||
.div32,
|
||||
.esp32s3ops,
|
||||
.exception,
|
||||
.fp,
|
||||
.highpriinterrupts,
|
||||
.highpriinterrupts_level7,
|
||||
.interrupt,
|
||||
.loop,
|
||||
.mac16,
|
||||
.minmax,
|
||||
.miscsr,
|
||||
.mul16,
|
||||
.mul32,
|
||||
.mul32high,
|
||||
.nsa,
|
||||
.prid,
|
||||
.regprotect,
|
||||
.rvector,
|
||||
.s32c1i,
|
||||
.sext,
|
||||
.threadptr,
|
||||
.timers3,
|
||||
.windowed,
|
||||
}),
|
||||
};
|
||||
pub const os: std.Target.Os = .{
|
||||
.tag = .freestanding,
|
||||
.version_range = .{ .none = {} },
|
||||
};
|
||||
pub const target: std.Target = .{
|
||||
.cpu = cpu,
|
||||
.os = os,
|
||||
.abi = abi,
|
||||
.ofmt = object_format,
|
||||
.dynamic_linker = .none,
|
||||
};
|
||||
pub const object_format: std.Target.ObjectFormat = .elf;
|
||||
pub const mode: std.builtin.OptimizeMode = .Debug;
|
||||
pub const link_libc = false;
|
||||
pub const link_libcpp = false;
|
||||
pub const have_error_return_tracing = true;
|
||||
pub const valgrind_support = false;
|
||||
pub const sanitize_thread = false;
|
||||
pub const fuzz = false;
|
||||
pub const position_independent_code = false;
|
||||
pub const position_independent_executable = false;
|
||||
pub const strip_debug_info = false;
|
||||
pub const code_model: std.builtin.CodeModel = .default;
|
||||
pub const omit_frame_pointer = false;
|
||||
```
|
||||
Reference in New Issue
Block a user