diff --git a/firmware/.cargo/config.toml b/firmware/.cargo/config.toml index f632639..2ba1943 100644 --- a/firmware/.cargo/config.toml +++ b/firmware/.cargo/config.toml @@ -4,13 +4,24 @@ target = "xtensa-esp32-espidf" [target.xtensa-esp32-espidf] linker = "ldproxy" runner = "espflash flash --monitor" -rustflags = [ "--cfg", "espidf_time64"] +# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3 +# See also https://github.com/ivmarkov/embuild/issues/16 +rustflags = ["--cfg", "espidf_time64"] [unstable] build-std = ["std", "panic_abort"] [env] -MCU="esp32" -# Note: this variable is not used by the pio builder (`cargo build --features pio`) -ESP_IDF_VERSION = "v5.2.3" +# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF (v5.3.2) +ESP_IDF_VERSION = { value = "tag:v5.3.2" } +# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files +# that you might put in the root of the project +# The easiest way to generate a full "sdkconfig[.release|debug]" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]" +# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder) +#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.release", relative = true } +#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.debug", relative = true } +ESP_IDF_SDKCONFIG_DEFAULTS = { value = "./sdkconfig.defaults", relative = true } +# ESP-IDF will be installed in ~/.espressif so it can be reused across the different examples. +# See also https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir +ESP_IDF_TOOLS_INSTALL_DIR = { value = "fromenv" } diff --git a/firmware/.gitignore b/firmware/.gitignore index 73a638b..8835ff2 100644 --- a/firmware/.gitignore +++ b/firmware/.gitignore @@ -1,4 +1,21 @@ -/.vscode -/.embuild -/target -/Cargo.lock +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ +.vscode/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# esp-idf +.embuild/ \ No newline at end of file diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 01fdb1f..ae1a88a 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.29" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "shlex", ] @@ -621,9 +621,11 @@ dependencies = [ name = "firmware" version = "0.1.0" dependencies = [ + "anyhow", "embuild", "esp-idf-svc", "log", + "toml-cfg", ] [[package]] @@ -1208,6 +1210,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1339,11 +1350,40 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml-cfg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c587298ddd135c156e92e8c3eae69614d6eecea8e2d8a09daab011e5e6a21d" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "serde", + "syn 2.0.104", + "toml", +] + [[package]] name = "toml_datetime" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -1352,10 +1392,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", + "serde", + "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "uncased" version = "0.9.10" diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 9724ed8..48ade66 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -1,47 +1,26 @@ [package] name = "firmware" version = "0.1.0" -authors = ["Clara Dautermann "] -edition = "2021" +edition = "2024" resolver = "2" -rust-version = "1.77" [[bin]] name = "firmware" -harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors +harness = false # We can't use the default rust libtest harness for a crosscompile target [profile.release] opt-level = "s" [profile.dev] -debug = true # Symbols are nice and they don't increase the size on Flash +debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" -[features] -default = [] - -experimental = ["esp-idf-svc/experimental"] - [dependencies] -log = "0.4" -esp-idf-svc = "0.51" - -# --- Optional Embassy Integration --- -# esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } - -# If you enable embassy-time-driver, you MUST also add one of: - -# a) Standalone Embassy libs ( embassy-time, embassy-sync etc) with a foreign async runtime: -# embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } # NOTE: any generic-queue variant will work - -# b) With embassy-executor: -# embassy-executor = { version = "0.7", features = ["executor-thread", "arch-std"] } - -# NOTE: if you use embassy-time with embassy-executor you don't need the generic-queue-8 feature - -# --- Temporary workaround for embassy-executor < 0.8 --- -# esp-idf-svc = { version = "0.51", features = ["embassy-time-driver", "embassy-sync"] } -# critical-section = { version = "1.1", features = ["std"], default-features = false } +anyhow = "1.0.98" +esp-idf-svc = "0.51.0" +log = "=0.4.27" +toml-cfg = "=0.2.0" [build-dependencies] -embuild = "0.33" +embuild = "=0.33.0" +toml-cfg = "=0.2.0" \ No newline at end of file diff --git a/firmware/build.rs b/firmware/build.rs index 112ec3f..a76b496 100644 --- a/firmware/build.rs +++ b/firmware/build.rs @@ -1,3 +1,52 @@ fn main() { - embuild::espidf::sysenv::output(); + linker_be_nice(); + // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link) + println!("cargo:rustc-link-arg=-Tlinkall.x"); +} + +fn linker_be_nice() { + let args: Vec = std::env::args().collect(); + if args.len() > 1 { + let kind = &args[1]; + let what = &args[2]; + + match kind.as_str() { + "undefined-symbol" => match what.as_str() { + "_defmt_timestamp" => { + eprintln!(); + eprintln!("💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`"); + eprintln!(); + } + "_stack_start" => { + eprintln!(); + eprintln!("💡 Is the linker script `linkall.x` missing?"); + eprintln!(); + } + "esp_wifi_preempt_enable" + | "esp_wifi_preempt_yield_task" + | "esp_wifi_preempt_task_create" => { + eprintln!(); + eprintln!("💡 `esp-wifi` has no scheduler enabled. Make sure you have the `builtin-scheduler` feature enabled, or that you provide an external scheduler."); + eprintln!(); + } + "embedded_test_linker_file_not_added_to_rustflags" => { + eprintln!(); + eprintln!("💡 `embedded-test` not found - make sure `embedded-test.x` is added as a linker script for tests"); + eprintln!(); + } + _ => (), + }, + // we don't have anything helpful for "missing-lib" yet + _ => { + std::process::exit(1); + } + } + + std::process::exit(0); + } + + println!( + "cargo:rustc-link-arg=-Wl,--error-handling-script={}", + std::env::current_exe().unwrap().display() + ); } diff --git a/firmware/rust-toolchain.toml b/firmware/rust-toolchain.toml index a2f5ab5..8270120 100644 --- a/firmware/rust-toolchain.toml +++ b/firmware/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] -channel = "esp" +channel = "esp" #nightly-2025-01-01 +components = ["rust-src"] diff --git a/firmware/sdkconfig.defaults b/firmware/sdkconfig.defaults deleted file mode 100644 index c25b89d..0000000 --- a/firmware/sdkconfig.defaults +++ /dev/null @@ -1,10 +0,0 @@ -# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 - -# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). -# This allows to use 1 ms granularity for thread sleeps (10 ms by default). -#CONFIG_FREERTOS_HZ=1000 - -# Workaround for https://github.com/espressif/esp-idf/issues/7631 -#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n -#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 9f40bc6..5a00db8 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -1,10 +1,14 @@ -fn main() { - // It is necessary to call this function once. Otherwise some patches to the runtime - // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 - esp_idf_svc::sys::link_patches(); +use anyhow::{bail, Result}; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use esp_idf_svc::hal::prelude::Peripherals; +use log::info; - // Bind the log crate to the ESP Logging facilities +fn main() -> Result<()> { + esp_idf_svc::sys::link_patches(); esp_idf_svc::log::EspLogger::initialize_default(); - log::info!("Hello, world!"); + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + + info!("Hello, world!"); } diff --git a/flake.nix b/flake.nix index 47e2647..6e6ac13 100644 --- a/flake.nix +++ b/flake.nix @@ -13,28 +13,13 @@ # Optionally pin to a specific commit of `nixpkgs-esp-dev`. rev = "f37890edc9b327fcbc6d48c4cf174e65e4c0d148"; }; - - forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: - let - pkgs = import nixpkgs { inherit system; overlays = [ (import "${nixpkgs-esp-dev}/overlay.nix") ]; }; - - libxml2Shared = pkgs.libxml2.overrideAttrs (old: { - configureFlags = (old.configureFlags or [ ]) ++ [ "--enable-shared" ]; - - # cursed patch necessary to fix linking errors - postInstall = '' - ln -sf libxml2.so $out/lib/libxml2.so.2 - ${old.postInstall or ""} - ''; - }); - in - f { inherit pkgs libxml2Shared; } - ); - + forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f { + pkgs = import nixpkgs { inherit system; overlays = [ (import "${nixpkgs-esp-dev}/overlay.nix") ]; }; + }); in { devShells = forEachSupportedSystem - ({ pkgs, libxml2Shared }: { + ({ pkgs }: { default = pkgs.mkShell { packages = with pkgs; [ @@ -42,23 +27,7 @@ espflash cargo-espflash espup - - llvmPackages_16.libclang # Explicitly add libclang - llvmPackages_16.clang # Include clang/headers - pkg-config # Often needed for bindgen to find clang - glibc.dev # Needed for C headers - libxml2Shared.out - ldproxy ]; - - env = { - # Set LD_LIBRARY_PATH so libstdc++.so.6 zlib and libxml2 can be found - LD_LIBRARY_PATH = with pkgs; pkgs.lib.makeLibraryPath [ - gcc.cc.lib - zlib - libxml2Shared.out - ]; - }; }; }); };