esp-idf-sys

repository·master·Indexed 18 days ago

https://github.com/esp-rs/esp-idf-sys

Low-level, raw Rust bindings for the ESP-IDF (Espressif IoT Development Framework) SDK. It enables Rust development on Espressif ESP32 series microcontrollers using the ESP-IDF standard library environment, featuring a cargo-driven automated build process that configures the C toolchain and SDK.

Tokens
5.6K
Snippets
13
Records
26
Agent score
64%

What's inside esp-idf-sys

  1. Overview of esp-idf-sys

    master

    esp-idf-sys provides raw Rust bindings for the ESP IDF SDK.

    Key Features

    • Automated Build: The build is cargo driven and automatically downloads and configures the ESP IDF SDK and the necessary C toolchain by default.
    • Build Systems: Supports the native ESP IDF build system and PlatformIO.
    • Mixed Projects: Can be used in mixed Rust/C projects.

    Important Note on Build Progress

    Because the build script downloads and builds the ESP IDF SDK, the initial build can take a significant amount of time. To see the progress and detailed build information, run cargo with the -vv (very verbose) flag:

    cargo build -vv

    These raw bindings are low-level. For safer, idiomatic Rust usage, consider:

  2. Use conditional compilation flags in esp-idf-sys

    master

    The esp-idf-sys build script provides several Rust cfg flags that allow you to conditionally compile code based on the ESP-IDF configuration and hardware.

    Available cfg flags:

    • esp_idf_comp_{component}_enabled: Enabled for each component (e.g., esp_idf_comp_espressif__mdns_enabled).
    • esp_idf_version="{major}.{minor}"
    • esp_idf_version_full="{major}.{minor}.{patch}"
    • esp_idf_version_major="{major}"
    • esp_idf_version_minor="{minor}"
    • esp_idf_version_patch="{patch}"
    • esp_idf_{sdkconfig_option}: For any sdkconfig option set to y. The option name is lowercased and prefixed with esp_idf_ (e.g., if CONFIG_ESP_WIFI_ENABLED is set, the flag is esp_idf_wifi_enabled).
    • {mcu}: The MCU for which the ESP-IDF is compiled.

    Note for upstream crate authors: If your crate needs access to these cfg flags, you must depend on esp-idf-sys and call embuild::espidf::sysenv::output(); in your build.rs.

  3. Configure ESP-IDF build settings

    master

    You can configure how the ESP-IDF framework is compiled using two methods:

    1. Environment Variables: Denoted by $VARIABLE. These can be passed via the command line or defined in the [env] section of a .cargo/config.toml file.
    2. Cargo.toml Metadata: Using the [package.metadata.esp-idf-sys] section.

    Important Rules:

    • Precedence: Environment variables always take precedence over Cargo.toml metadata.
    • Scope: Configuration must be placed in the root crate's Cargo.toml (the package in the workspace directory). If using a virtual workspace, specify the root crate name using the ESP_IDF_SYS_ROOT_CRATE environment variable.
    • Workspace Directory: Relative paths are resolved relative to the workspace directory (the directory containing Cargo.lock). If you have moved your target directory using CARGO_TARGET_DIR, you must explicitly set CARGO_WORKSPACE_DIR in .cargo/config.toml to ensure embuild can locate the crate root and your sdkconfig.defaults.
    [env]
    CARGO_WORKSPACE_DIR = { value = "", relative = true }
  4. Modify ESP-IDF configuration using cargo-pio

    master

    If you are using the pio builder, you can interactively modify the ESP-IDF sdkconfig file (e.g., to enable Bluetooth) using the cargo-pio subcommand.

    1. Install cargo-pio:
      cargo install cargo-pio --git https://github.com/ivmarkov/cargo-pio
    2. Open interactive menuconfig: Run the following command in the root of your binary crate project:
      cargo pio espidf menuconfig
    3. Apply changes: Follow your project's specific instructions (such as those in the 'Bluetooth Support' section) to ensure the generated/updated sdkconfig file is used by the build.
    # Install cargo-pio
    cargo install cargo-pio --git https://github.com/ivmarkov/cargo-pio
    
    # Open interactive menuconfig
    cargo pio espidf menuconfig
  5. Set up a new ESP-IDF Rust project

    master

    The recommended way to start a new "Hello, world!" binary crate with ESP-IDF is to use the esp-idf-template project. This template automates the arrangement and building of the project, so you do not need to manually clone the ESP IDF repository or configure the environment yourself.

    Before starting, ensure you have met the Build Prerequisites defined in the esp-idf-template crate.

  6. Select an ESP-IDF build feature

    master

    You can choose how the ESP-IDF framework and its build tools are installed and managed by selecting one of the following crate features:

    • native (Default): Uses the framework's own tooling and the embuild crate to download and build the ESP-IDF framework. This is the most flexible option.
    • pio: Uses PlatformIO via embuild to manage tools and the framework.
      • Warning: The pio builder is less flexible and currently only supports ESP-IDF version V4.3.2.
    • binstart: Used when your root crate is a binary crate defining a main function. It defines the ESP-IDF entry point.
    • libstart: Used when your root crate is a library crate. The root crate must provide a #[no_mangle] fn main() {} function to serve as the ESP-IDF entry point.
  7. Add extra ESP-IDF components via Cargo.toml

    master

    You can instruct esp-idf-sys to compile additional ESP-IDF components and generate Rust bindings for them by adding them to the package.metadata.esp-idf-sys.extra_components array in your Cargo.toml. This works for the root crate and all direct dependencies.

    Each entry in the array can specify:

    • component_dirs: A list of paths (absolute or relative to the Cargo.toml) to component directories.
    • remote_component: Configuration for components managed by the ESP-IDF component manager.
    • bindings_header: The path to a C header file used to generate bindings. If this is the only field provided, you are extending the existing bindings from src/include/esp-idf/bindings.h.
    • bindings_module: The name of the Rust module where the generated bindings will reside. If omitted, bindings are added to the crate root. If provided, a separate bindgen instance is used.
    [[package.metadata.esp-idf-sys.extra_components]]
    component_dirs = ["dir1", "dir2"]
    bindings_header = "bindings.h"
    bindings_module = "name"
  8. Access raw ESP-IDF bindings and errors

    master
    The esp-idf-sys crate provides direct access to the underlying ESP-IDF C SDK through the bindings module and provides error handling types via the error module. Most low-level C functions and types are re-exported at the crate root.
  9. Add remote ESP-IDF components via the Component Manager

    master

    To include components from the ESP-IDF component registry, use the remote_component field within extra_components. This maps to an idf_component.yml dependency entry. The component manager will download these to the managed_components directory in the esp-idf-sys build output.

    Available fields for remote_component:

    • name: The name of the component (e.g., espressif/mdns). Slashes are replaced by double underscores in Rust cfg flags (e.g., espressif__mdns).
    • version: The component version.
    • git: A git URL for the component.
    • path: A path to the component (not recommended for local components; use component_dirs instead).
    • service_url: A URL to a custom component registry.

    Example: Adding the espressif/mdns component

    [[package.metadata.esp-idf-sys.extra_components]]
    remote_component = { name = "espressif/mdns", version = "1.2" }
  10. Configure Rust compilation flags for ESP-IDF

    master

    Certain rustc flags are required to ensure compatibility with the ESP-IDF environment and to enable standard library support.

    • --cfg espidf_time64: Configures the libc crate to use 64-bit time_t.
      • Required for ESP-IDF 5.0 and above.
      • Must be unset for ESP-IDF versions below 5.0.
    • -Zbuild-std=std,panic_abort: Required to enable std support, as Rust does not provide pre-compiled std libraries for ESP32 targets.
  11. Limitations and Partition Table usage

    master

    Filesystem Requirement

    ESP IDF cannot be compiled on filesystems that do not support symbolic links (for example, FAT filesystems).

    Custom Partition Tables

    If your project uses a custom partitions.csv:

    1. Do NOT define CONFIG_PARTITION_TABLE_CUSTOM=y or CONFIG_PARTITION_TABLE_[CUSTOM_]FILENAME in your sdkconfig.defaults. The build system handles this automatically and will ignore these manual definitions.
    2. Flashing: When flashing the device, explicitly provide the partition table using the --partition-table flag with espflash:
    espflash flash [...] --partition-table partitions.csv