eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 283a4bcd1434d1e773857c4a50bf766fda1b8561
parent 235dd59bdc9aaeae4ce3d243a4af9592382a750f
Author: Daniel Barlow <dan@telent.net>
Date:   Mon, 19 Jan 2026 19:40:07 +0000

Add 'vendor/esp-hal-ota/' from commit '57adf08fef483420bf44389594dc3355e766e8ab'

git-subtree-dir: vendor/esp-hal-ota
git-subtree-mainline: 235dd59bdc9aaeae4ce3d243a4af9592382a750f
git-subtree-split: 57adf08fef483420bf44389594dc3355e766e8ab

Diffstat:
Avendor/esp-hal-ota/.gitignore | 1+
Avendor/esp-hal-ota/Cargo.lock | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/Cargo.toml | 41+++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/LICENSE | 21+++++++++++++++++++++
Avendor/esp-hal-ota/README.md | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/examples/.cargo/config.toml | 25+++++++++++++++++++++++++
Avendor/esp-hal-ota/examples/.env.example | 3+++
Avendor/esp-hal-ota/examples/.gitignore | 12++++++++++++
Avendor/esp-hal-ota/examples/Cargo.lock | 1758+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/examples/Cargo.toml | 45+++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/examples/build.rs | 10++++++++++
Avendor/esp-hal-ota/examples/esp-ota-test.py | 16++++++++++++++++
Avendor/esp-hal-ota/examples/partitions.csv | 8++++++++
Avendor/esp-hal-ota/examples/rust-toolchain.toml | 2++
Avendor/esp-hal-ota/examples/src/main.rs | 267+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/partition-reader/Cargo.lock | 7+++++++
Avendor/esp-hal-ota/partition-reader/Cargo.toml | 6++++++
Avendor/esp-hal-ota/partition-reader/part.bin | 0
Avendor/esp-hal-ota/partition-reader/src/main.rs | 24++++++++++++++++++++++++
Avendor/esp-hal-ota/partitions.csv.template | 6++++++
Avendor/esp-hal-ota/simple-ota-server/Cargo.lock | 25+++++++++++++++++++++++++
Avendor/esp-hal-ota/simple-ota-server/Cargo.toml | 9+++++++++
Avendor/esp-hal-ota/simple-ota-server/firmware.bin | 0
Avendor/esp-hal-ota/simple-ota-server/src/main.rs | 30++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/crc32.rs | 44++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/helpers.rs | 33+++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/lib.rs | 453+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/logging.rs | 35+++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_hal.rs | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32.rs | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32c2.rs | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32c3.rs | 22++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32c6.rs | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32h2.rs | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32s2.rs | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/esp32s3.rs | 22++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/mod.rs | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Avendor/esp-hal-ota/src/mmu_ll/not_selected.rs | 15+++++++++++++++
Avendor/esp-hal-ota/src/structs.rs | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 files changed, 3781 insertions(+), 0 deletions(-)

diff --git a/vendor/esp-hal-ota/.gitignore b/vendor/esp-hal-ota/.gitignore @@ -0,0 +1 @@ +target diff --git a/vendor/esp-hal-ota/Cargo.lock b/vendor/esp-hal-ota/Cargo.lock @@ -0,0 +1,215 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "esp-hal-ota" +version = "0.4.5" +dependencies = [ + "defmt", + "embedded-storage", + "esp32", + "esp32c2", + "esp32c3", + "esp32c6", + "esp32h2", + "esp32s2", + "esp32s3", + "log", +] + +[[package]] +name = "esp32" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b76170a463d18f888a1ad258031901036fd827a9ef126733053ba5f8739fb0c8" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32c2" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e62cf8932966b8d445b6f1832977b468178f0a84effb2e9fda89f60c24d45aa3" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32c3" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356af3771d0d6536c735bf71136594f4d1cbb506abf6e0c51a6639e9bf4e7988" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32c6" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5e511df672d79cd63365c92045135e01ba952b6bddd25b660baff5e1110f6b" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32h2" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4a50bbd1380931e095e0973b9b12f782a9c481f2edf1f7c42e7eb4ff736d6d" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32s2" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98574d4c577fbe888fe3e6df7fc80d25a05624d9998f7d7de1500ae21fcca78f" +dependencies = [ + "vcell", +] + +[[package]] +name = "esp32s3" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1810d8ee4845ef87542af981e38eb80ab531d0ef1061e1486014ab7af74c337a" +dependencies = [ + "vcell", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" diff --git a/vendor/esp-hal-ota/Cargo.toml b/vendor/esp-hal-ota/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "esp-hal-ota" +version = "0.4.5" +edition = "2024" +license = "MIT" +description = "OTA library for esp-hal" +repository = "https://github.com/filipton/esp-hal-ota" + +[lib] + +[dependencies] +embedded-storage = "0.3.1" +log = { version = "0.4.28", optional = true } +defmt = { version = "1.0.1", optional = true } + +esp32 = { version = "0.39.0", optional = true } + +esp32s2 = { version = "0.30.0", optional = true } +esp32s3 = { version = "0.34.0", optional = true } + +esp32c2 = { version = "0.28.0", optional = true } +esp32c3 = { version = "0.31.0", optional = true } +esp32c6 = { version = "0.22.0", optional = true } + +esp32h2 = { version = "0.18.0", optional = true } + +[features] +default = [] +log = ["dep:log"] +defmt = ["dep:defmt"] + +esp32 = ["dep:esp32"] + +esp32s2 = ["dep:esp32s2"] +esp32s3 = ["dep:esp32s3"] + +esp32c2 = ["dep:esp32c2"] +esp32c3 = ["dep:esp32c3"] +esp32c6 = ["dep:esp32c6"] + +esp32h2 = ["dep:esp32h2"] diff --git a/vendor/esp-hal-ota/LICENSE b/vendor/esp-hal-ota/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/esp-hal-ota/README.md b/vendor/esp-hal-ota/README.md @@ -0,0 +1,77 @@ +# esp-hal-ota +OTA for esp-hal (no-std). + +[![crates.io](https://img.shields.io/crates/v/esp-hal-ota.svg)](https://crates.io/crates/esp-hal-ota) +[![MIT license](https://img.shields.io/github/license/mashape/apistatus.svg)]() + +## Limitations +I cannot test if it works properly on esp32s2,esp32c2,esp32c6 and esp32h2. +But esp32s3, esp32c3 and esp32 are working perfectly fine. + +## Features +- Obviously OTA updates +- Dynamic partitions reading (so no macros, no reading from partitions.csv) - fully automatic +- Checking currently booted partition (using some pointer magic from ESP-IDF) +- CRC32 verification + +## Getting started +- Create `partitions.csv` file in project root (copy `partitions.csv.template` file) +- In your project edit `./.cargo/config.toml` file and append `--partition-table ./partitions.csv` to the `runner` attribute +- Optionally append `--erase-parts otadata` to `./cargo/config.toml` to fix some ota issues + +```toml +[target.xtensa-esp32s3-none-elf] +runner = "espflash flash --monitor --partition-table ./partitions.csv --erase-parts otadata" +``` + +## Example +To see real-world example look at `./examples` and `./simple-ota-server` dirs. + +```rust +let flash_size = 1234; // get it from OTA server +let target_crc = 65436743; // get it from OTA server + +let mut ota = Ota::new(FlashStorage::new()).unwrap(); +ota.ota_begin(flash_size, target_crc); + +let mut buf = [0; 4096]; +loop { + let n = read_next_chunk(&mut buf); + if n == 0 { + break; + } + + let res = ota.ota_write_chunk(&buf[..n]); + if res == Ok(true) { // end of flash + if ota.ota_flush(true, true).is_ok() { // true if you want to verify crc reading flash, and true if you want rollbacks + esp_hal::reset::software_reset(); + } + } + + let progress = (ota.get_ota_progress() * 100) as u8; + log::info!("progress: {}%", progress); +} +``` + +### Running example +- You can compile your .bin file using esp-flash +```bash +espflash save-image --chip esp32c3 ./target/riscv32imc-unknown-none-elf/debug/esp-hal-ota-example ../simple-ota-server/firmware.bin +``` + +This will generate .bin file from build file for chip. + +## Todo +- [x] Fully working library +- [x] Simple example +- [x] Better errors +- [x] Other esp32's (like esp32c3, esp32s2, etc..) +- [x] Rollbacks + +## Resources +- https://github.com/esp-rs/espflash (this led me to esp-idf-part) +- https://github.com/esp-rs/esp-idf-part +- https://github.com/espressif/esp-idf/blob/master/docs/en/api-reference/system/ota.rst (especially Python API) +- https://github.com/python/cpython/blob/main/Modules/binascii.c (internal_crc32) +- https://github.com/espressif/esp-idf/blob/master/components/app_update/esp_ota_ops.c#L552 (esp get current partition (paddr)) +- https://github.com/bjoernQ/esp32c3-ota-experiment (i've only seen this after first experiments, so haven't looked at it yet) diff --git a/vendor/esp-hal-ota/examples/.cargo/config.toml b/vendor/esp-hal-ota/examples/.cargo/config.toml @@ -0,0 +1,25 @@ +[alias] +esp32c3 = "run --no-default-features --features=esp32c3 --target=riscv32imc-unknown-none-elf" +esp32s3 = "run --no-default-features --features=esp32s3 --target=xtensa-esp32s3-none-elf" +esp32 = "run --no-default-features --features=esp32 --target=xtensa-esp32-none-elf" + +[target.'cfg(target_arch = "riscv32")'] +runner = "espflash flash --monitor --partition-table ./partitions.csv --erase-parts otadata" +rustflags = [ + "-C", "force-frame-pointers", +] + +[target.'cfg(target_arch = "xtensa")'] +runner = "espflash flash --monitor --partition-table ./partitions.csv --erase-parts otadata" +rustflags = [ + "-C", "link-arg=-nostartfiles", +] + +[build] +target = "xtensa-esp32s3-none-elf" #default esp32s3 + +[env] +ESP_LOG="INFO" + +[unstable] +build-std = ["core", "alloc"] diff --git a/vendor/esp-hal-ota/examples/.env.example b/vendor/esp-hal-ota/examples/.env.example @@ -0,0 +1,3 @@ +SSID= +PSK= +OTA_IP= diff --git a/vendor/esp-hal-ota/examples/.gitignore b/vendor/esp-hal-ota/examples/.gitignore @@ -0,0 +1,12 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb +.env +out*.bin diff --git a/vendor/esp-hal-ota/examples/Cargo.lock b/vendor/esp-hal-ota/examples/Cargo.lock @@ -0,0 +1,1758 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "allocator-api2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78200ac3468a57d333cd0ea5dd398e25111194dcacd49208afca95c629a6311d" + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitfield" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db1bcd90f88eabbf0cadbfb87a45bceeaebcd3b4bc9e43da379cd2ef0162590d" +dependencies = [ + "bitfield-macros", +] + +[[package]] +name = "bitfield-macros" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3787a07661997bfc05dd3431e379c0188573f78857080cf682e1393ab8e4d64c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bt-hci" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb938a3b4c5cc6c2409275bad789c0346a0495fa071a0acc5d72b9bd3175a2f7" +dependencies = [ + "btuuid", + "embassy-sync 0.7.2", + "embedded-io 0.6.1", + "embedded-io-async 0.6.1", + "futures-intrusive", + "heapless 0.8.0", +] + +[[package]] +name = "btuuid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0acfef8a77a02866e04f7e2ad3f4c7b32d575696c49c4bbad742b4aecb8e4a3" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.101", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "delegate" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b6483c2bbed26f97861cf57651d4f2b731964a28cd2257f934a4b452480d21" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "embassy-embedded-hal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" +dependencies = [ + "embassy-futures", + "embassy-hal-internal", + "embassy-sync 0.7.2", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" +dependencies = [ + "critical-section", + "document-features", + "embassy-executor-macros", + "embassy-executor-timer-queue", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "embassy-executor-timer-queue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-hal-internal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" +dependencies = [ + "num-traits", +] + +[[package]] +name = "embassy-net" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0558a231a47e7d4a06a28b5278c92e860f1200f24821d2f365a2f40fe3f3c7b2" +dependencies = [ + "document-features", + "embassy-net-driver", + "embassy-sync 0.7.2", + "embassy-time", + "embedded-io-async 0.6.1", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-sync" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async 0.6.1", + "futures-sink", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-sync" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async 0.6.1", + "futures-core", + "futures-sink", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-utils" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e2ee86063bd028a420a5fb5898c18c87a8898026da1d4c852af2c443d0a454" +dependencies = [ + "embassy-executor-timer-queue", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a" +dependencies = [ + "embedded-io-async 0.6.1", +] + +[[package]] +name = "embassy-usb-synopsys-otg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288751f8eaa44a5cf2613f13cee0ca8e06e6638cb96e897e6834702c79084b23" +dependencies = [ + "critical-section", + "embassy-sync 0.7.2", + "embassy-usb-driver", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-io-async" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564b9f813c544241430e147d8bc454815ef9ac998878d30cc3055449f7fd4c0" +dependencies = [ + "embedded-io 0.7.1", +] + +[[package]] +name = "embedded-nal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-nal-async" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" +dependencies = [ + "embedded-io-async 0.6.1", + "embedded-nal", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "enumset" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a6b7c3d347de0a9f7bfd2f853be43fe32fa6fac30c70f6d6d67a1e936b87ee" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da3ea9e1d1a3b1593e15781f930120e72aa7501610b2f82e5b6739c72e8eac5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "esp-alloc" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "641e43d6a60244429117ef2fa7a47182120c7561336ea01f6fb08d634f46bae1" +dependencies = [ + "allocator-api2", + "cfg-if", + "document-features", + "enumset", + "esp-config", + "esp-sync", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "esp-backtrace" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd8a541e17aa485d82df547f03c77b89f78cb110f59dea67cc90733d67e3678" +dependencies = [ + "cfg-if", + "document-features", + "esp-config", + "esp-metadata-generated", + "esp-println", + "heapless 0.9.1", + "riscv", + "semihosting", + "xtensa-lx", +] + +[[package]] +name = "esp-bootloader-esp-idf" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c319c4a24fb44ef4c5f9854ff3dc6010eb8f15a6613d024227aa2355e3f6a334" +dependencies = [ + "cfg-if", + "document-features", + "embedded-storage", + "esp-config", + "esp-rom-sys", + "jiff", + "log", + "strum", +] + +[[package]] +name = "esp-config" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "289fde78fff1ff500e81efbdf958b1dae1614eacc61cc5560b0a3e03a25f266e" +dependencies = [ + "document-features", + "esp-metadata-generated", + "serde", + "serde_yaml", + "somni-expr", +] + +[[package]] +name = "esp-hal" +version = "1.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75242d788e67fc7ce51308019c0ff5d5103f989721577bb566b02710ef1ba79" +dependencies = [ + "bitfield", + "bitflags 2.9.1", + "bytemuck", + "cfg-if", + "critical-section", + "delegate", + "digest", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-sync 0.7.2", + "embassy-usb-driver", + "embassy-usb-synopsys-otg", + "embedded-can", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-io 0.6.1", + "embedded-io 0.7.1", + "embedded-io-async 0.6.1", + "embedded-io-async 0.7.0", + "enumset", + "esp-config", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-riscv-rt", + "esp-rom-sys", + "esp-sync", + "esp-synopsys-usb-otg", + "esp32", + "esp32c2", + "esp32c3", + "esp32c6", + "esp32h2", + "esp32s2", + "esp32s3", + "fugit", + "instability", + "nb 1.1.0", + "paste", + "portable-atomic", + "rand_core 0.6.4", + "rand_core 0.9.3", + "riscv", + "sha1", + "sha2", + "strum", + "ufmt-write", + "xtensa-lx", + "xtensa-lx-rt", +] + +[[package]] +name = "esp-hal-ota" +version = "0.4.5" +dependencies = [ + "embedded-storage", + "esp32", + "esp32c3", + "esp32s3", + "log", +] + +[[package]] +name = "esp-hal-ota-example" +version = "0.1.0" +dependencies = [ + "dotenvy", + "embassy-executor", + "embassy-net", + "embassy-time", + "esp-alloc", + "esp-backtrace", + "esp-bootloader-esp-idf", + "esp-hal", + "esp-hal-ota", + "esp-println", + "esp-radio", + "esp-rtos", + "esp-storage", + "log", + "static_cell", +] + +[[package]] +name = "esp-hal-procmacros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd82a6506fb08d53a1086d165d92f085717aa9c59e67ac87a9e6f8acdcf6897" +dependencies = [ + "document-features", + "object", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.101", + "termcolor", +] + +[[package]] +name = "esp-metadata-generated" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18b1787dd3adea642fb529dd83fe558a08ace365bbaede4643a8959992900f4" + +[[package]] +name = "esp-phy" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62199c3e50eefcf53b8f3c690946582a124f7137b45bd1b14eb4b90a3fec2dd7" +dependencies = [ + "cfg-if", + "document-features", + "esp-config", + "esp-hal", + "esp-metadata-generated", + "esp-sync", + "esp-wifi-sys", +] + +[[package]] +name = "esp-println" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dcd18cbb132db6eb30d7c96bd831c3b6916894210f4528321f69fa66178b331" +dependencies = [ + "document-features", + "esp-metadata-generated", + "esp-sync", + "log", + "portable-atomic", +] + +[[package]] +name = "esp-radio" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83744f57d19a7190a538ad42025da7f53940c3aca71cbcd92275095d671e254" +dependencies = [ + "allocator-api2", + "bt-hci", + "cfg-if", + "document-features", + "embassy-net-driver", + "embedded-io 0.6.1", + "embedded-io 0.7.1", + "embedded-io-async 0.6.1", + "embedded-io-async 0.7.0", + "enumset", + "esp-alloc", + "esp-config", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-phy", + "esp-radio-rtos-driver", + "esp-sync", + "esp-wifi-sys", + "heapless 0.9.1", + "instability", + "num-derive", + "num-traits", + "portable-atomic", + "portable_atomic_enum", + "xtensa-lx-rt", +] + +[[package]] +name = "esp-radio-rtos-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab031e544f6bc086c2d7aba89276e6a47ce6bb5614ae3c88a1c12a4ab4f8f25c" + +[[package]] +name = "esp-riscv-rt" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502744a5b1e7268d27fd2a4e56ad45efe42ead517d6c517a6961540de949b0ee" +dependencies = [ + "document-features", + "riscv", + "riscv-rt", +] + +[[package]] +name = "esp-rom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01bafc39f59d56610b38ed0f63b16abeb8b357b8f546507d0d6c50c1a494f530" +dependencies = [ + "cfg-if", + "document-features", + "esp-metadata-generated", +] + +[[package]] +name = "esp-rtos" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7844233ccdf92eaf4134c08c56c1b4a874f7d59e6249c579e912ecc6c9312fda" +dependencies = [ + "allocator-api2", + "cfg-if", + "document-features", + "embassy-executor", + "embassy-sync 0.7.2", + "embassy-time-driver", + "embassy-time-queue-utils", + "esp-config", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-radio-rtos-driver", + "esp-sync", + "portable-atomic", +] + +[[package]] +name = "esp-storage" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac4c20d28188fc31ad34008ad3a94dd7d828e5fef0c83c265bdb7dac168d512" +dependencies = [ + "document-features", + "embedded-storage", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-rom-sys", + "esp-sync", +] + +[[package]] +name = "esp-sync" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b977b028ae5959f0b2daf6602a1d751723b2d329c7251daf869ad382c8ed1543" +dependencies = [ + "cfg-if", + "document-features", + "embassy-sync 0.6.2", + "embassy-sync 0.7.2", + "esp-metadata-generated", + "riscv", + "xtensa-lx", +] + +[[package]] +name = "esp-synopsys-usb-otg" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8938451cb19032f13365328ea66ab38c8d16deecdf322067442297110eb74468" +dependencies = [ + "critical-section", + "embedded-hal 0.2.7", + "ral-registers", + "usb-device", + "vcell", +] + +[[package]] +name = "esp-wifi-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b6544f6f0cb86169d1f93ba2101a8d50358a040c5043676ed86b793e09b12c" +dependencies = [ + "anyhow", +] + +[[package]] +name = "esp32" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b76170a463d18f888a1ad258031901036fd827a9ef126733053ba5f8739fb0c8" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c2" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e62cf8932966b8d445b6f1832977b468178f0a84effb2e9fda89f60c24d45aa3" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c3" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356af3771d0d6536c735bf71136594f4d1cbb506abf6e0c51a6639e9bf4e7988" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c6" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5e511df672d79cd63365c92045135e01ba952b6bddd25b660baff5e1110f6b" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32h2" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4a50bbd1380931e095e0973b9b12f782a9c481f2edf1f7c42e7eb4ff736d6d" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32s2" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98574d4c577fbe888fe3e6df7fc80d25a05624d9998f7d7de1500ae21fcca78f" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32s3" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1810d8ee4845ef87542af981e38eb80ab531d0ef1061e1486014ab7af74c337a" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fugit" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" +dependencies = [ + "gcd", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "instability" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a" +dependencies = [ + "darling", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "portable_atomic_enum" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d48f60c43e0120bb2bb48589a16d4bed2f4b911be41e299f2d0fc0e0e20885" +dependencies = [ + "portable-atomic", + "portable_atomic_enum_macros", +] + +[[package]] +name = "portable_atomic_enum_macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33fa6ec7f2047f572d49317cca19c87195de99c6e5b6ee492da701cfe02b053" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ral-registers" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46b71a9d9206e8b46714c74255adcaea8b11e0350c1d8456165073c3f75fc81a" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "riscv-rt" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d07b9f3a0eff773fc4df11f44ada4fa302e529bff4b7fe7e6a4b98a65ce9174" +dependencies = [ + "riscv", + "riscv-pac", + "riscv-rt-macros", + "riscv-target-parser", +] + +[[package]] +name = "riscv-rt-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c3138fdd8d128b2d81829842a3e0ce771b3712f7b6318ed1476b0695e7d330" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "riscv-target-parser" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1376b15f3ff160e9b1e8ea564ce427f2f6fcf77528cc0a8bf405cb476f9cea7" + +[[package]] +name = "rlsf" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "svgbobdoc", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semihosting" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e1c7d2b77d80283c750a39c52f1ab4d17234e8f30bca43550f5b2375f41d5f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "smoltcp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "heapless 0.8.0", + "managed", +] + +[[package]] +name = "somni-expr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed9b7648d5e8b2df6c5e49940c54bcdd2b4dd71eafc6e8f1c714eb4581b0f53" +dependencies = [ + "somni-parser", +] + +[[package]] +name = "somni-parser" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ee90f60ebcade244355ed4ff4077e364b251508c3462af386a9ee96c5a5492" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.101", +] + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "xtensa-lx" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e012d667b0aa6d2592ace8ef145a98bff3e76cca7a644f4181ecd7a916ed289b" +dependencies = [ + "critical-section", +] + +[[package]] +name = "xtensa-lx-rt" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8709f037fb123fe7ff146d2bce86f9dc0dfc53045c016bfd9d703317b6502845" +dependencies = [ + "document-features", + "xtensa-lx", + "xtensa-lx-rt-proc-macros", +] + +[[package]] +name = "xtensa-lx-rt-proc-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fb42cd29c42f8744c74276e9f5bee7b06685bbe5b88df891516d72cb320450" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] diff --git a/vendor/esp-hal-ota/examples/Cargo.toml b/vendor/esp-hal-ota/examples/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "esp-hal-ota-example" +version = "0.1.0" +authors = ["filipton <filipton12@gmail.com>"] +edition = "2024" +license = "MIT OR Apache-2.0" + +[dependencies] +esp-backtrace = { version = "0.18.0", features = [ "panic-handler", "println" ] } +esp-hal = { version = "1.0.0-rc.1", features = ["unstable"] } +esp-println = { version = "0.16.0", features = ["log-04"] } +log = { version = "0.4.28" } +esp-radio = { version = "0.16.0", features = [ "unstable", "wifi", "ble" ] } +esp-rtos = { version = "0.1.0", features = ["esp-radio", "embassy"] } +embassy-executor = { version = "0.9.1", package = "embassy-executor", features = ["arch-riscv32"] } +embassy-net = { version = "0.7.1", features = ["tcp", "udp", "dhcpv4", "medium-ethernet"] } +embassy-time = { version = "0.5.0" } +esp-storage = { version = "0.8.0", features = [] } +esp-hal-ota = { path = "../", features = ["log"] } +static_cell = { version = "2.1.1", features = ["nightly"] } +esp-alloc = "0.9.0" +esp-bootloader-esp-idf = { version = "0.3.0", features = ["log-04"] } + +[build-dependencies] +dotenvy = "0.15.7" + +[profile.dev] +# Rust debug is too slow. +# For debug builds always builds with some optimization +opt-level = "s" + +[profile.release] +codegen-units = 1 # LLVM can perform better optimizations using a single thread +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 2 +overflow-checks = false + +[features] +default = ["esp32s3"] +esp32s3 = ["esp-backtrace/esp32s3", "esp-hal/esp32s3", "esp-println/esp32s3", "esp-radio/esp32s3", "esp-rtos/esp32s3", "esp-storage/esp32s3", "esp-hal-ota/esp32s3", "esp-bootloader-esp-idf/esp32s3"] +esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3", "esp-println/esp32c3", "esp-radio/esp32c3", "esp-rtos/esp32c3", "esp-storage/esp32c3", "esp-hal-ota/esp32c3", "esp-bootloader-esp-idf/esp32c3"] +esp32 = ["esp-backtrace/esp32", "esp-hal/esp32", "esp-println/esp32", "esp-radio/esp32", "esp-rtos/esp32", "esp-storage/esp32", "esp-hal-ota/esp32", "esp-bootloader-esp-idf/esp32"] diff --git a/vendor/esp-hal-ota/examples/build.rs b/vendor/esp-hal-ota/examples/build.rs @@ -0,0 +1,10 @@ +fn main() { + println!("cargo:rerun-if-changed=*.env*"); + if let Ok(mut iter) = dotenvy::dotenv_iter() { + while let Some(Ok((key, value))) = iter.next() { + println!("cargo:rustc-env={key}={value}"); + } + } + + println!("cargo:rustc-link-arg-bins=-Tlinkall.x"); +} diff --git a/vendor/esp-hal-ota/examples/esp-ota-test.py b/vendor/esp-hal-ota/examples/esp-ota-test.py @@ -0,0 +1,16 @@ +import sys +import os + +idf_path = os.environ["IDF_PATH"] # get value of IDF_PATH from environment +otatool_dir = os.path.join(idf_path, "components", "app_update") # otatool.py lives in $IDF_PATH/components/app_update + +sys.path.append(otatool_dir) # this enables Python to find otatool module +from otatool import * # import all names inside otatool module + +target = OtatoolTarget("/dev/ttyACM0") +target.switch_ota_partition(0) +#print(target._get_otadata_info()) + +#target.erase_otadata() +#target.erase_ota_partition(1) +#target.switch_ota_partition(1) diff --git a/vendor/esp-hal-ota/examples/partitions.csv b/vendor/esp-hal-ota/examples/partitions.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, 0xd000, 0x2000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 0x100000, +ota_0, app, ota_0, 0x110000, 0x100000, +ota_1, app, ota_1, 0x210000, 0x100000, +#ota_2, app, ota_2, 0x310000, 0x10000, diff --git a/vendor/esp-hal-ota/examples/rust-toolchain.toml b/vendor/esp-hal-ota/examples/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/vendor/esp-hal-ota/examples/src/main.rs b/vendor/esp-hal-ota/examples/src/main.rs @@ -0,0 +1,267 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +extern crate alloc; +use core::str::FromStr; +use embassy_executor::Spawner; +use embassy_net::{Config, Runner, Stack, StackResources, tcp::TcpSocket}; +use embassy_time::{Duration, Timer}; +use esp_backtrace as _; +use esp_hal::timer::timg::TimerGroup; +use esp_hal_ota::Ota; +use esp_radio::{ + Controller, + wifi::{ClientConfig, ModeConfig, WifiController, WifiDevice, WifiEvent, WifiStaState}, +}; +use esp_storage::FlashStorage; + +const WIFI_SSID: &'static str = env!("SSID"); +const WIFI_PSK: &'static str = env!("PSK"); +const OTA_SERVER_IP: &'static str = env!("OTA_IP"); + +const RX_BUFFER_SIZE: usize = 16384; +const TX_BUFFER_SIZE: usize = 16384; +static mut TX_BUFF: [u8; TX_BUFFER_SIZE] = [0; TX_BUFFER_SIZE]; +static mut RX_BUFF: [u8; RX_BUFFER_SIZE] = [0; RX_BUFFER_SIZE]; + +macro_rules! mk_static { + ($t:ty,$val:expr) => {{ + static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); + #[deny(unused_attributes)] + let x = STATIC_CELL.uninit().write(($val)); + x + }}; +} + +esp_bootloader_esp_idf::esp_app_desc!(); + +#[esp_rtos::main] +async fn main(spawner: Spawner) { + #[cfg(not(feature = "esp32"))] + { + esp_alloc::heap_allocator!(size: 150 * 1024); + } + + #[cfg(feature = "esp32")] + { + static mut HEAP: core::mem::MaybeUninit<[u8; 30 * 1024]> = core::mem::MaybeUninit::uninit(); + + #[unsafe(link_section = ".dram2_uninit")] + static mut HEAP2: core::mem::MaybeUninit<[u8; 64 * 1024]> = + core::mem::MaybeUninit::uninit(); + + unsafe { + #[allow(static_mut_refs)] + esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new( + HEAP.as_mut_ptr() as *mut u8, + core::mem::size_of_val(&*core::ptr::addr_of!(HEAP)), + esp_alloc::MemoryCapability::Internal.into(), + )); + + #[allow(static_mut_refs)] + esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new( + HEAP2.as_mut_ptr() as *mut u8, + core::mem::size_of_val(&*core::ptr::addr_of!(HEAP2)), + esp_alloc::MemoryCapability::Internal.into(), + )); + } + } + + let peripherals = esp_hal::init(esp_hal::Config::default()); + //let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + esp_println::logger::init_logger_from_env(); + //log::set_max_level(log::LevelFilter::Info); // only for esp32s3?? + + let timg0 = TimerGroup::new(peripherals.TIMG0); + + #[cfg(any(feature = "esp32s3", feature = "esp32"))] + esp_rtos::start(timg0.timer0); + + #[cfg(feature = "esp32c3")] + let software_interrupt = + esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); + + #[cfg(feature = "esp32c3")] + esp_rtos::start(timg0.timer0, software_interrupt.software_interrupt0); + + let init = &*mk_static!(Controller<'static>, esp_radio::init().unwrap()); + + let wifi = peripherals.WIFI; + let (controller, interfaces) = esp_radio::wifi::new(&init, wifi, Default::default()).unwrap(); + + let config = Config::dhcpv4(Default::default()); + let seed = 69420; + + let (stack, runner) = embassy_net::new( + interfaces.sta, + config, + { + static STATIC_CELL: static_cell::StaticCell<StackResources<3>> = + static_cell::StaticCell::new(); + STATIC_CELL.uninit().write(StackResources::<3>::new()) + }, + seed, + ); + + spawner + .spawn(connection(controller, stack)) + .expect("connection spawn"); + spawner.spawn(net_task(runner)).expect("net task spawn"); + + // mark ota partition valid + { + let mut ota = Ota::new(FlashStorage::new(unsafe { + peripherals.FLASH.clone_unchecked() + })) + .expect("Cannot create ota"); + _ = ota.ota_mark_app_valid(); //do not unwrap here if using factory/test partition + } + + loop { + log::info!("Wait for wifi!"); + Timer::after(Duration::from_secs(1)).await; + + if let Some(config) = stack.config_v4() { + log::info!("Got IP: {}", config.address); + break; + } + } + + let mut socket = unsafe { + TcpSocket::new( + stack, + &mut *core::ptr::addr_of_mut!(RX_BUFF), + &mut *core::ptr::addr_of_mut!(TX_BUFF), + ) + }; + + let ip = embassy_net::IpEndpoint::from_str(OTA_SERVER_IP).expect("Wrong ip addr"); + socket.connect(ip).await.expect("Cannot connect!"); + let mut ota_buff = [0; 4096 * 2]; + socket + .read(&mut ota_buff[..4]) + .await + .expect("Cannot read firmware size!"); + let flash_size = u32::from_le_bytes(ota_buff[..4].try_into().unwrap()); + + socket + .read(&mut ota_buff[..4]) + .await + .expect("Cannot read target crc!"); + let target_crc = u32::from_le_bytes(ota_buff[..4].try_into().unwrap()); + + log::info!("flash_size: {flash_size}"); + log::info!("target_crc: {target_crc}"); + + let mut ota = Ota::new(FlashStorage::new(unsafe { + peripherals.FLASH.clone_unchecked() + })) + .expect("Cannot create ota"); + ota.ota_begin(flash_size, target_crc).unwrap(); + + let mut bytes_read: usize = 0; + loop { + let bytes_to_read = 8192.min(flash_size - bytes_read as u32); + let res = read_exact(&mut socket, &mut ota_buff[..bytes_to_read as usize]).await; + if let Ok(_) = res { + bytes_read += bytes_to_read as usize; + if bytes_to_read == 0 { + break; + } + + let res = ota.ota_write_chunk(&ota_buff[..bytes_to_read as usize]); + _ = socket.write(&[0]).await; + + match res { + Ok(true) => { + let res = ota.ota_flush(false, true); + if let Err(e) = res { + log::error!("Ota flush error: {e:?}"); + break; + } + + log::info!("Ota OK! Rebooting in 1s!"); + Timer::after_millis(1000).await; + esp_hal::system::software_reset(); + } + Err(e) => { + log::error!("Ota write error: {e:?}"); + break; + } + _ => {} + } + } + + log::info!("Progress: {}%", (ota.get_ota_progress() * 100.0) as u8); + } + + loop { + log::info!("bump"); + Timer::after_millis(15000).await; + } +} + +#[embassy_executor::task] +async fn connection(mut controller: WifiController<'static>, stack: Stack<'static>) { + log::info!("start connection task"); + log::info!("Device capabilities: {:?}", controller.capabilities()); + loop { + if esp_radio::wifi::sta_state() == WifiStaState::Connected { + // wait until we're no longer connected + controller.wait_for_event(WifiEvent::StaDisconnected).await; + Timer::after(Duration::from_millis(5000)).await + } + if !matches!(controller.is_started(), Ok(true)) { + let client_config = ModeConfig::Client( + ClientConfig::default() + .with_ssid(WIFI_SSID.try_into().expect("Wifi ssid parse")) + .with_password(WIFI_PSK.try_into().expect("Wifi psk parse")), + ); + controller.set_config(&client_config).unwrap(); + log::info!("Starting wifi"); + controller.start_async().await.unwrap(); + log::info!("Wifi started!"); + } + log::info!("About to connect..."); + + match controller.connect_async().await { + Ok(_) => { + log::info!("Wifi connected!"); + + loop { + if stack.is_link_up() { + break; + } + Timer::after(Duration::from_millis(500)).await; + } + } + Err(e) => { + log::info!("Failed to connect to wifi: {e:?}"); + Timer::after(Duration::from_millis(5000)).await + } + } + } +} + +#[embassy_executor::task] +async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) { + runner.run().await +} + +pub async fn read_exact( + socket: &mut TcpSocket<'_>, + mut buf: &mut [u8], +) -> Result<(), embassy_net::tcp::Error> { + while !buf.is_empty() { + match socket.read(buf).await { + Ok(0) => return Err(embassy_net::tcp::Error::ConnectionReset), + Ok(n) => { + buf = &mut buf[n..]; + } + Err(e) => return Err(e), + } + } + Ok(()) +} diff --git a/vendor/esp-hal-ota/partition-reader/Cargo.lock b/vendor/esp-hal-ota/partition-reader/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "partition-reader" +version = "0.1.0" diff --git a/vendor/esp-hal-ota/partition-reader/Cargo.toml b/vendor/esp-hal-ota/partition-reader/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "partition-reader" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/vendor/esp-hal-ota/partition-reader/part.bin b/vendor/esp-hal-ota/partition-reader/part.bin Binary files differ. diff --git a/vendor/esp-hal-ota/partition-reader/src/main.rs b/vendor/esp-hal-ota/partition-reader/src/main.rs @@ -0,0 +1,24 @@ +const PARTITION_BYTES: &[u8] = include_bytes!("../part.bin"); + +fn main() { + let chunks = PARTITION_BYTES.chunks(32); + for chunk in chunks { + if chunk == &[0xFF; 32] { + break; + } + + let magic = &chunk[0..2]; + if magic != &[0xAA, 0x50] { + continue; + } + + let p_type = &chunk[2]; + let p_subtype = &chunk[3]; + let p_offset = u32::from_le_bytes(chunk[4..8].try_into().unwrap()); + let p_size = u32::from_le_bytes(chunk[8..12].try_into().unwrap()); + let p_name = core::str::from_utf8(&chunk[12..28]).unwrap(); + let p_flags = u32::from_le_bytes(chunk[28..32].try_into().unwrap()); + + println!("{magic:?} {p_type} {p_subtype} {p_offset} {p_size} {p_name} {p_flags}"); + } +} diff --git a/vendor/esp-hal-ota/partitions.csv.template b/vendor/esp-hal-ota/partitions.csv.template @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, 0xd000, 0x2000, +phy_init, data, phy, 0xf000, 0x1000, +ota_0, app, ota_0, 0x10000, 0x100000, +ota_1, app, ota_1, 0x110000, 0x100000, diff --git a/vendor/esp-hal-ota/simple-ota-server/Cargo.lock b/vendor/esp-hal-ota/simple-ota-server/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "simple-ota-server" +version = "0.1.0" +dependencies = [ + "crc32fast", +] diff --git a/vendor/esp-hal-ota/simple-ota-server/Cargo.toml b/vendor/esp-hal-ota/simple-ota-server/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "simple-ota-server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +crc32fast = "1.4.2" diff --git a/vendor/esp-hal-ota/simple-ota-server/firmware.bin b/vendor/esp-hal-ota/simple-ota-server/firmware.bin Binary files differ. diff --git a/vendor/esp-hal-ota/simple-ota-server/src/main.rs b/vendor/esp-hal-ota/simple-ota-server/src/main.rs @@ -0,0 +1,30 @@ +use std::{ + io::{Read, Write}, + net::TcpListener, +}; + +fn main() { + let binary = std::fs::read("./firmware.bin").unwrap(); + let binary_crc = crc32fast::hash(&binary); + + println!("BINARY_SIZE: {}", binary.len()); + println!("BINARY CRC32: {}", binary_crc); + + let listener = TcpListener::bind("0.0.0.0:6969").unwrap(); + for stream in listener.incoming() { + println!("Connection"); + let mut stream = stream.unwrap(); + + _ = stream.write_all(&(binary.len() as u32).to_le_bytes()); + _ = stream.write_all(&binary_crc.to_le_bytes()); + + let chunks = binary.chunks(4096 * 2); + let mut buf = [0; 1]; + for chunk in chunks { + println!("Writing: {}", chunk.len()); + + _ = stream.write_all(chunk); + _ = stream.read_exact(&mut buf); + } + } +} diff --git a/vendor/esp-hal-ota/src/crc32.rs b/vendor/esp-hal-ota/src/crc32.rs @@ -0,0 +1,44 @@ +const CRC_32_TAB: [u32; 256] = [ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +]; + +pub fn calc_crc32(buf: &[u8], mut crc: u32) -> u32 { + crc = !crc; + for &elem in buf { + let crc_idx = (crc ^ elem as u32) & 0xFF; + crc = CRC_32_TAB[crc_idx as usize] ^ (crc >> 8); + } + + crc ^ 0xFFFFFFFF +} diff --git a/vendor/esp-hal-ota/src/helpers.rs b/vendor/esp-hal-ota/src/helpers.rs @@ -0,0 +1,33 @@ +#[inline(always)] +/// Helper funcion! +/// Change seq to partition number +pub const fn seq_to_part(seq: u32, partitions_count: usize) -> usize { + ((seq as usize).saturating_sub(1)) % partitions_count +} + +#[inline(always)] +/// Helper funcion! +/// If crc of seq is correct it returns seq, otherwise default value is returned +pub fn seq_or_default(seq: &[u8], crc: u32, default: u32) -> u32 { + let crc_calc = crate::crc32::calc_crc32(seq, 0xFFFFFFFF); + if crc == crc_calc { + return u32::from_le_bytes(seq.try_into().expect("Wrong size?")); + } + + default +} + +#[inline(always)] +/// Helper function! +/// Check if crc is correct for given seq +pub fn is_crc_seq_correct(seq: u32, crc: u32) -> bool { + let bytes = unsafe { + let mut buf = [0; 4]; //u32 + core::ptr::copy_nonoverlapping(&seq as *const u32 as *const u8, buf.as_mut_ptr(), 4); + + buf + }; + + let crc_calc = crate::crc32::calc_crc32(&bytes, 0xFFFFFFFF); + crc == crc_calc +} diff --git a/vendor/esp-hal-ota/src/lib.rs b/vendor/esp-hal-ota/src/lib.rs @@ -0,0 +1,453 @@ +#![no_std] +#![cfg_attr(any(feature = "esp32", feature = "esp32s2"), feature(concat_idents))] +#![cfg_attr(feature = "esp32", feature(asm_experimental_arch))] +#![doc = include_str!("../README.md")] + +#[macro_use] +mod logging; + +use embedded_storage::{ReadStorage, Storage}; +pub use structs::*; + +pub mod crc32; +pub mod helpers; +pub mod mmu_hal; +pub mod mmu_ll; +pub mod structs; + +const PART_OFFSET: u32 = 0x8000; +const PART_SIZE: u32 = 0xc00; +const FIRST_OTA_PART_SUBTYPE: u8 = 0x10; +const OTA_VERIFY_READ_SIZE: usize = 256; + +pub struct Ota<S> +where + S: ReadStorage + Storage, +{ + flash: S, + + progress: Option<FlashProgress>, + pinfo: PartitionInfo, +} + +pub struct ProgressDetails { + pub remaining: u32, + pub last_crc: u32, +} + +#[derive(Debug)] +pub struct OtaConfiguratuion { + partition_table_offset: u32, +} +impl OtaConfiguratuion { + /// Create default configuration of the [`Ota`] process. + /// + /// Notably this uses the default partition table offset of `0x8000` + pub const fn new() -> Self { + Self { + partition_table_offset: PART_OFFSET, + } + } + + /// Set custom partition table offset + pub const fn with_partition_table_offset(self, partition_table_offset: u32) -> Self { + Self { + partition_table_offset, + ..self + } + } +} +impl Default for OtaConfiguratuion { + fn default() -> Self { + Self::new() + } +} + +impl<S> Ota<S> +where + S: ReadStorage + Storage, +{ + pub fn new(flash: S) -> Result<Self> { + Self::with_configuration(flash, OtaConfiguratuion::new()) + } + + pub fn with_configuration(mut flash: S, config: OtaConfiguratuion) -> Result<Self> { + let pinfo = Self::read_partitions(&mut flash, config.partition_table_offset)?; + if pinfo.ota_partitions_count < 2 { + error!("Not enough OTA partitions! (>= 2)"); + + return Err(OtaError::NotEnoughPartitions); + } + + Ok(Ota { + flash, + progress: None, + pinfo, + }) + } + + fn get_partitions(&self) -> &[(u32, u32)] { + &self.pinfo.ota_partitions[..self.pinfo.ota_partitions_count] + } + + /// To begin ota update (need to provide flash size) + pub fn ota_begin(&mut self, size: u32, target_crc: u32) -> Result<()> { + let next_part = self.get_next_ota_partition().unwrap_or(0); + + let ota_offset = self.get_partitions()[next_part].0; + self.progress = Some(FlashProgress { + last_crc: 0, + flash_size: size, + remaining: size, + flash_offset: ota_offset, + target_partition: next_part, + target_crc, + }); + + Ok(()) + } + + /// Resumes an OTA update after progress has been lost + pub fn ota_resume( + &mut self, + flash_size: u32, + remaining: u32, + target_crc: u32, + last_crc: u32, + verify_crc: bool, + ) -> Result<()> { + let next_part = self.get_next_ota_partition().unwrap_or(0); + let ota_offset = self.get_partitions()[next_part].0; + + if verify_crc { + let mut calc_crc = 0; + let mut bytes = [0; OTA_VERIFY_READ_SIZE]; + let mut written = flash_size - remaining; + let mut partition_offset = ota_offset; + + loop { + let n = written.min(OTA_VERIFY_READ_SIZE as u32); + if n == 0 { + break; + } + + _ = self.flash.read(partition_offset, &mut bytes[..n as usize]); + partition_offset += n; + written -= n; + + calc_crc = crc32::calc_crc32(&bytes[..n as usize], calc_crc); + } + + if calc_crc != last_crc { + return Err(OtaError::WrongCRC); + } + } + + self.progress = Some(FlashProgress { + last_crc, + flash_size, + remaining, + flash_offset: ota_offset + (flash_size - remaining), + target_partition: next_part, + target_crc, + }); + + Ok(()) + } + + /// Returns progress details to save for resumption later + pub fn get_progress_details(&self) -> Option<ProgressDetails> { + if self.progress.is_none() { + warn!("[OTA] Cannot get progress details!"); + + return None; + } + + let progress = self.progress.as_ref().unwrap(); + Some(ProgressDetails { + remaining: progress.remaining, + last_crc: progress.last_crc, + }) + } + + /// Returns ota progress in f32 (0..1) + pub fn get_ota_progress(&self) -> f32 { + if self.progress.is_none() { + warn!("[OTA] Cannot get ota progress! Seems like update wasn't started yet."); + + return 0.0; + } + + let progress = self.progress.as_ref().unwrap(); + (progress.flash_size - progress.remaining) as f32 / progress.flash_size as f32 + } + + /// Writes next firmware chunk + pub fn ota_write_chunk(&mut self, chunk: &[u8]) -> Result<bool> { + let progress = self.progress.as_mut().ok_or(OtaError::OtaNotStarted)?; + + if progress.remaining == 0 { + return Ok(true); + } + + let write_size = chunk.len() as u32; + let write_size = write_size.min(progress.remaining) as usize; + + self.flash + .write(progress.flash_offset, &chunk[..write_size]) + .map_err(|_| OtaError::FlashRWError)?; + + debug!( + "[OTA] Wrote {} bytes to ota partition at 0x{:x}", + write_size, progress.flash_offset + ); + + progress.last_crc = crc32::calc_crc32(&chunk[..write_size], progress.last_crc); + + progress.flash_offset += write_size as u32; + progress.remaining -= write_size as u32; + Ok(progress.remaining == 0) + } + + /// verify - should it read flash and check crc + /// rollback - if rollbacks enable (will set ota_state to ESP_OTA_IMG_NEW) + pub fn ota_flush(&mut self, verify: bool, rollback: bool) -> Result<()> { + if verify && !self.ota_verify()? { + error!("[OTA] Verify failed! Not flushing..."); + + return Err(OtaError::OtaVerifyError); + } + + let progress = self.progress.clone().ok_or(OtaError::OtaNotStarted)?; + + if progress.target_crc != progress.last_crc { + warn!("[OTA] Calculated crc: {}", progress.last_crc); + warn!("[OTA] Target crc: {}", progress.target_crc); + error!("[OTA] Crc check failed! Cant finish ota update..."); + + return Err(OtaError::WrongCRC); + } + + let img_state = match rollback { + true => OtaImgState::EspOtaImgNew, + false => OtaImgState::EspOtaImgUndefined, + }; + + self.set_target_ota_boot_partition(progress.target_partition, img_state); + Ok(()) + } + + /// It reads written flash and checks crc + pub fn ota_verify(&mut self) -> Result<bool> { + let progress = self.progress.clone().ok_or(OtaError::OtaNotStarted)?; + + let mut calc_crc = 0; + let mut bytes = [0; OTA_VERIFY_READ_SIZE]; + + let mut partition_offset = self.pinfo.ota_partitions[progress.target_partition].0; + let mut remaining = progress.flash_size; + + loop { + let n = remaining.min(OTA_VERIFY_READ_SIZE as u32); + if n == 0 { + break; + } + + _ = self.flash.read(partition_offset, &mut bytes[..n as usize]); + partition_offset += n; + remaining -= n; + + calc_crc = crc32::calc_crc32(&bytes[..n as usize], calc_crc); + } + + Ok(calc_crc == progress.target_crc) + } + + /// Sets ota boot target partition + pub fn set_target_ota_boot_partition(&mut self, target: usize, state: OtaImgState) { + let (slot1, slot2) = self.get_ota_boot_entries(); + let (seq1, seq2) = (slot1.seq, slot2.seq); + + let mut target_seq = seq1.max(seq2); + while helpers::seq_to_part(target_seq, self.pinfo.ota_partitions_count) != target + || target_seq == 0 + { + target_seq += 1; + } + + let flash = &mut self.flash; + let target_crc = crc32::calc_crc32(&target_seq.to_le_bytes(), 0xFFFFFFFF); + if seq1 > seq2 { + let offset = self.pinfo.otadata_offset + (self.pinfo.otadata_size >> 1); + + _ = flash.write(offset, &target_seq.to_le_bytes()); + _ = flash.write(offset + 32 - 4 - 4, &(state as u32).to_le_bytes()); + _ = flash.write(offset + 32 - 4, &target_crc.to_le_bytes()); + } else { + _ = flash.write(self.pinfo.otadata_offset, &target_seq.to_le_bytes()); + _ = flash.write( + self.pinfo.otadata_offset + 32 - 4 - 4, + &(state as u32).to_le_bytes(), + ); + _ = flash.write( + self.pinfo.otadata_offset + 32 - 4, + &target_crc.to_le_bytes(), + ); + } + } + + pub fn set_ota_state(&mut self, slot: u8, state: OtaImgState) -> Result<()> { + let offset = match slot { + 1 => self.pinfo.otadata_offset, + 2 => self.pinfo.otadata_offset + (self.pinfo.otadata_size >> 1), + _ => { + error!("Use slot1 or slot2!"); + return Err(OtaError::CannotFindCurrentBootPartition); + } + }; + + _ = self + .flash + .write(offset + 32 - 4 - 4, &(state as u32).to_le_bytes()); + + Ok(()) + } + + /// Returns current OTA boot sequences + /// + /// NOTE: if crc doesn't match, it returns 0 for that seq + /// NOTE: [Entry struct (link to .h file)](https://github.com/espressif/esp-idf/blob/master/components/bootloader_support/include/esp_flash_partitions.h#L66) + pub fn get_ota_boot_entries(&mut self) -> (EspOtaSelectEntry, EspOtaSelectEntry) { + let mut bytes = [0; 32]; + _ = self.flash.read(self.pinfo.otadata_offset, &mut bytes); + let mut slot1: EspOtaSelectEntry = + unsafe { core::ptr::read(bytes.as_ptr() as *const EspOtaSelectEntry) }; + slot1.check_crc(); + + _ = self.flash.read( + self.pinfo.otadata_offset + (self.pinfo.otadata_size >> 1), + &mut bytes, + ); + let mut slot2: EspOtaSelectEntry = + unsafe { core::ptr::read(bytes.as_ptr() as *const EspOtaSelectEntry) }; + slot2.check_crc(); + + (slot1, slot2) + } + + /// Returns currently booted partition index + pub fn get_currently_booted_partition(&self) -> Option<usize> { + mmu_hal::esp_get_current_running_partition(self.get_partitions()) + } + + /// BUG: this wont work if user has ota partitions not starting from ota0 + /// or if user skips some ota partitions: ota0, ota2, ota3... + pub fn get_next_ota_partition(&self) -> Option<usize> { + let curr_part = mmu_hal::esp_get_current_running_partition(self.get_partitions()); + curr_part.map(|next_part| (next_part + 1) % self.pinfo.ota_partitions_count) + } + + fn get_current_slot(&mut self) -> Result<(u8, EspOtaSelectEntry)> { + let (slot1, slot2) = self.get_ota_boot_entries(); + let current_partition = self + .get_currently_booted_partition() + .ok_or(OtaError::CannotFindCurrentBootPartition)?; + + let slot1_part = helpers::seq_to_part(slot1.seq, self.pinfo.ota_partitions_count); + let slot2_part = helpers::seq_to_part(slot2.seq, self.pinfo.ota_partitions_count); + if current_partition == slot1_part { + return Ok((1, slot1)); + } else if current_partition == slot2_part { + return Ok((2, slot2)); + } + + Err(OtaError::CannotFindCurrentBootPartition) + } + + pub fn get_ota_image_state(&mut self) -> Result<OtaImgState> { + let (slot1, slot2) = self.get_ota_boot_entries(); + let current_partition = self + .get_currently_booted_partition() + .ok_or(OtaError::CannotFindCurrentBootPartition)?; + + let slot1_part = helpers::seq_to_part(slot1.seq, self.pinfo.ota_partitions_count); + let slot2_part = helpers::seq_to_part(slot2.seq, self.pinfo.ota_partitions_count); + if current_partition == slot1_part { + return Ok(slot1.ota_state); + } else if current_partition == slot2_part { + return Ok(slot2.ota_state); + } + + Err(OtaError::CannotFindCurrentBootPartition) + } + + pub fn ota_mark_app_valid(&mut self) -> Result<()> { + let (current_slot_nmb, current_slot) = self.get_current_slot()?; + if current_slot.ota_state != OtaImgState::EspOtaImgValid { + self.set_ota_state(current_slot_nmb, OtaImgState::EspOtaImgValid)?; + + info!("Marked current slot as valid!"); + } + + Ok(()) + } + + pub fn ota_mark_app_invalid_rollback(&mut self) -> Result<()> { + let (current_slot_nmb, current_slot) = self.get_current_slot()?; + if current_slot.ota_state != OtaImgState::EspOtaImgValid { + self.set_ota_state(current_slot_nmb, OtaImgState::EspOtaImgInvalid)?; + + info!("Marked current slot as invalid!"); + } + + Ok(()) + } + + fn read_partitions(flash: &mut S, partition_table_offset: u32) -> Result<PartitionInfo> { + let mut tmp_pinfo = PartitionInfo { + ota_partitions: [(0, 0); 16], + ota_partitions_count: 0, + otadata_size: 0, + otadata_offset: 0, + }; + + let mut bytes = [0xFF; 32]; + let mut last_ota_part: i8 = -1; + for read_offset in (0..PART_SIZE).step_by(32) { + _ = flash.read(partition_table_offset + read_offset, &mut bytes); + if bytes == [0xFF; 32] { + break; + } + + let magic = &bytes[0..2]; + if magic != [0xAA, 0x50] { + continue; + } + + let p_type = &bytes[2]; + let p_subtype = &bytes[3]; + let p_offset = u32::from_le_bytes(bytes[4..8].try_into().unwrap()); + let p_size = u32::from_le_bytes(bytes[8..12].try_into().unwrap()); + //let p_name = core::str::from_utf8(&bytes[12..28]).unwrap(); + //let p_flags = u32::from_le_bytes(bytes[28..32].try_into().unwrap()); + //log::info!("{magic:?} {p_type} {p_subtype} {p_offset} {p_size} {p_name} {p_flags}"); + + if *p_type == 0 && *p_subtype >= FIRST_OTA_PART_SUBTYPE { + let ota_part_idx = *p_subtype - FIRST_OTA_PART_SUBTYPE; + if ota_part_idx as i8 - last_ota_part != 1 { + return Err(OtaError::WrongOTAPArtitionOrder); + } + + last_ota_part = ota_part_idx as i8; + tmp_pinfo.ota_partitions[tmp_pinfo.ota_partitions_count] = (p_offset, p_size); + tmp_pinfo.ota_partitions_count += 1; + } else if *p_type == 1 && *p_subtype == 0 { + //otadata + tmp_pinfo.otadata_offset = p_offset; + tmp_pinfo.otadata_size = p_size; + } + } + + Ok(tmp_pinfo) + } +} diff --git a/vendor/esp-hal-ota/src/logging.rs b/vendor/esp-hal-ota/src/logging.rs @@ -0,0 +1,35 @@ +macro_rules! debug { + ($($arg:tt)*) => { + #[cfg(feature = "defmt")] + defmt::debug!($($arg)*); + #[cfg(feature = "log")] + log::debug!($($arg)*); + }; +} + +macro_rules! info { + ($($arg:tt)*) => { + #[cfg(feature = "defmt")] + defmt::info!($($arg)*); + #[cfg(feature = "log")] + log::info!($($arg)*); + }; +} + +macro_rules! warn { + ($($arg:tt)*) => { + #[cfg(feature = "defmt")] + defmt::warn!($($arg)*); + #[cfg(feature = "log")] + log::warn!($($arg)*); + }; +} + +macro_rules! error { + ($($arg:tt)*) => { + #[cfg(feature = "defmt")] + defmt::error!($($arg)*); + #[cfg(feature = "log")] + log::error!($($arg)*); + }; +} diff --git a/vendor/esp-hal-ota/src/mmu_hal.rs b/vendor/esp-hal-ota/src/mmu_hal.rs @@ -0,0 +1,50 @@ +pub const MMU_PAGE_8KB: u32 = 0x2000; +pub const MMU_PAGE_16KB: u32 = 0x4000; +pub const MMU_PAGE_32KB: u32 = 0x8000; +pub const MMU_PAGE_64KB: u32 = 0x10000; + +fn mmu_hal_pages_to_bytes(mmu_id: u32, page_num: u32) -> u32 { + let mmu_page_size = crate::mmu_ll::mmu_ll_get_page_size(mmu_id); + let shift_code = match mmu_page_size { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + _ => panic!("WRONG MMU_PAGE_SIZE! 0x{:X?}", mmu_page_size), + }; + + page_num << shift_code +} + +pub fn esp_get_current_running_partition(partitions: &[(u32, u32)]) -> Option<usize> { + // NOTE: + // mmu_id is always 0 because s_vaddr_to_paddr is using 0 for all targets + // except esp32p4 (per SOC_MMU_PER_EXT_MEM_TARGET define) + // + // https://github.com/espressif/esp-idf/blob/b5ac4fbdf9e9fb320bb0a98ee4fbaa18f8566f37/components/esp_mm/esp_mmu_map.c#L754 + let mmu_id = 0; + + let ptr = esp_get_current_running_partition as *const () as *const u32; + let entry_id = crate::mmu_ll::mmu_ll_get_entry_id(mmu_id, ptr as u32); + + if !crate::mmu_ll::mmu_ll_check_entry_valid(mmu_id, entry_id) { + error!("mmu_ll_check_entry_valid failed!"); + + return None; + } + + // page_num is always 1 + // https://github.com/espressif/esp-idf/blob/master/components/hal/mmu_hal.c#L129 + let page_size_in_bytes = mmu_hal_pages_to_bytes(mmu_id, 1); + let offset = (ptr as u32) % page_size_in_bytes; + + let paddr_base = crate::mmu_ll::mmu_ll_entry_id_to_paddr_base(mmu_id, entry_id); + let paddr = paddr_base | offset; + + for (i, part) in partitions.iter().enumerate() { + if paddr >= part.0 && paddr < part.0 + part.1 { + return Some(i); + } + } + + None +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32.rs @@ -0,0 +1,101 @@ +const SOC_MMU_VADDR_MASK: u32 = 0x3FFFFF; +const SOC_MMU_INVALID: u32 = 1 << 8; +const MMU_LL_PSRAM_ENTRY_START_ID: u32 = 1152; +const SOC_IRAM0_CACHE_ADDRESS_LOW: u32 = 0x400D0000; +const SOC_IRAM0_CACHE_ADDRESS_HIGH: u32 = 0x40400000; +const SOC_IRAM1_CACHE_ADDRESS_LOW: u32 = 0x40400000; +const SOC_IRAM1_CACHE_ADDRESS_HIGH: u32 = 0x40800000; +const SOC_IROM0_CACHE_ADDRESS_LOW: u32 = 0x40800000; +const SOC_IROM0_CACHE_ADDRESS_HIGH: u32 = 0x40C00000; +const SOC_DRAM1_CACHE_ADDRESS_LOW: u32 = 0x3F800000; +const SOC_DRAM1_CACHE_ADDRESS_HIGH: u32 = 0x3FC00000; +const SOC_DROM0_CACHE_ADDRESS_LOW: u32 = 0x3F400000; +const SOC_DROM0_CACHE_ADDRESS_HIGH: u32 = 0x3F800000; +const DPORT_PRO_FLASH_MMU_TABLE: u32 = 0x3FF10000; + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + crate::mmu_hal::MMU_PAGE_64KB +} + +pub fn mmu_ll_get_entry_id(_mmu_id: u32, vaddr: u32) -> u32 { + let mut offset = 0; + let mut shift_code = 0; + let mut vaddr_mask = 0; + + if soc_address_in_bus!(SOC_DROM0_CACHE, vaddr) { + offset = 0; + shift_code = 16; + vaddr_mask = SOC_MMU_VADDR_MASK; + } else if soc_address_in_bus!(SOC_IRAM0_CACHE, vaddr) { + offset = 64; + shift_code = 16; + vaddr_mask = SOC_MMU_VADDR_MASK; + } else if soc_address_in_bus!(SOC_IRAM1_CACHE, vaddr) { + offset = 128; + shift_code = 16; + vaddr_mask = SOC_MMU_VADDR_MASK; + } else if soc_address_in_bus!(SOC_IROM0_CACHE, vaddr) { + offset = 192; + shift_code = 16; + vaddr_mask = SOC_MMU_VADDR_MASK; + } else if soc_address_in_bus!(SOC_DRAM1_CACHE, vaddr) { + offset = MMU_LL_PSRAM_ENTRY_START_ID; + shift_code = 15; + vaddr_mask = SOC_MMU_VADDR_MASK >> 1; + } else { + error!("mmu_ll_get_entry_id failed!"); + } + + offset + ((vaddr & vaddr_mask) >> shift_code) +} + +pub fn mmu_ll_entry_id_to_paddr_base(_mmu_id: u32, entry_id: u32) -> u32 { + let level = unsafe { dport_interrupt_disable() }; + let mmu_val = unsafe { *(DPORT_PRO_FLASH_MMU_TABLE as *const u32).offset(entry_id as isize) }; + unsafe { dport_interrupt_restore(level) }; + + if entry_id >= MMU_LL_PSRAM_ENTRY_START_ID { + mmu_val << 15 + } else { + mmu_val << 16 + } +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let level = unsafe { dport_interrupt_disable() }; + let mmu_val = unsafe { *(DPORT_PRO_FLASH_MMU_TABLE as *const u32).offset(entry_id as isize) }; + unsafe { dport_interrupt_restore(level) }; + + (mmu_val & SOC_MMU_INVALID) == 0 +} + +// NOTE:Idk if required! +// Only used when using second core etc. + +const SOC_DPORT_WORKAROUND_DIS_INTERRUPT_LVL: u32 = 5; +#[inline(always)] +unsafe fn dport_interrupt_disable() -> u32 { + let level: u32; + + unsafe { + core::arch::asm!( + "rsil {0}, {1}", + out(reg) level, + const SOC_DPORT_WORKAROUND_DIS_INTERRUPT_LVL, + options(nomem, nostack) + ); + } + + level +} + +#[inline(always)] +unsafe fn dport_interrupt_restore(level: u32) { + unsafe { + core::arch::asm!( + "wsr.ps {0}; rsync", + in(reg) level, + options(nomem, nostack) + ); + } +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32c2.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32c2.rs @@ -0,0 +1,55 @@ +use crate::mmu_hal::{MMU_PAGE_16KB, MMU_PAGE_32KB, MMU_PAGE_64KB}; + +const DR_REG_MMU_TABLE: u32 = 0x600c5000; +const SOC_MMU_VALID_VAL_MASK: u32 = 0x3f; +const SOC_MMU_INVALID: u32 = 1 << 6; + +fn soc_mmu_vaddr_mask(mmu_id: u32) -> u32 { + mmu_ll_get_page_size(mmu_id) * 64 - 1 +} + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + let extmem = unsafe { &*esp32c2::EXTMEM::ptr() }; + let cache_mmu_page_size = extmem.cache_conf_misc().read().cache_mmu_page_size().bits(); + match cache_mmu_page_size { + 0 => MMU_PAGE_16KB, + 1 => MMU_PAGE_32KB, + _ => MMU_PAGE_64KB, + } +} + +pub fn mmu_ll_get_entry_id(mmu_id: u32, vaddr: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + _ => { + error!("mmu_ll_get_entry_id failed!"); + + 0 + } + }; + + (vaddr & soc_mmu_vaddr_mask(mmu_id)) >> shift_code +} + +pub fn mmu_ll_entry_id_to_paddr_base(mmu_id: u32, entry_id: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + _ => { + error!("mmu_ll_entry_id_to_paddr_base failed!"); + + 0 + } + }; + + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_VALID_VAL_MASK) << shift_code } +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_INVALID) == 0 } +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32c3.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32c3.rs @@ -0,0 +1,22 @@ +const SOC_MMU_VADDR_MASK: u32 = 0x7FFFFF; +const DR_REG_MMU_TABLE: u32 = 0x600c5000; +const SOC_MMU_VALID_VAL_MASK: u32 = 0xff; +const SOC_MMU_INVALID: u32 = 1 << 8; + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + crate::mmu_hal::MMU_PAGE_64KB +} + +pub fn mmu_ll_get_entry_id(_mmu_id: u32, vaddr: u32) -> u32 { + (vaddr & SOC_MMU_VADDR_MASK) >> 16 +} + +pub fn mmu_ll_entry_id_to_paddr_base(_mmu_id: u32, entry_id: u32) -> u32 { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_VALID_VAL_MASK) << 16 } +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_INVALID) == 0 } +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32c6.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32c6.rs @@ -0,0 +1,79 @@ +use crate::mmu_hal::{MMU_PAGE_8KB, MMU_PAGE_16KB, MMU_PAGE_32KB, MMU_PAGE_64KB}; + +const SOC_MMU_ENTRY_NUM: u32 = 256; +const SOC_MMU_VALID_VAL_MASK: u32 = 0x1ff; +const SOC_MMU_VALID: u32 = 1 << 9; + +fn soc_mmu_vaddr_mask(mmu_id: u32) -> u32 { + mmu_ll_get_page_size(mmu_id) * SOC_MMU_ENTRY_NUM - 1 +} + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + let spi_mem = unsafe { &*esp32c6::SPI0::ptr() }; + let page_size_code = spi_mem.mmu_power_ctrl().read().spi_mmu_page_size().bits(); + + match page_size_code { + 0 => MMU_PAGE_64KB, + 1 => MMU_PAGE_32KB, + 2 => MMU_PAGE_16KB, + _ => MMU_PAGE_8KB, + } +} + +pub fn mmu_ll_get_entry_id(mmu_id: u32, vaddr: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + MMU_PAGE_8KB => 13, + _ => { + error!("mmu_ll_get_entry_id failed!"); + + 0 + } + }; + + (vaddr & soc_mmu_vaddr_mask(mmu_id)) >> shift_code +} + +pub fn mmu_ll_entry_id_to_paddr_base(mmu_id: u32, entry_id: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + MMU_PAGE_8KB => 13, + _ => { + error!("mmu_ll_entry_id_to_paddr_base failed!"); + + 0 + } + }; + + let spi_mem = unsafe { &*esp32c6::SPI0::ptr() }; + spi_mem + .mmu_item_index() + .write(|w| unsafe { w.spi_mmu_item_index().bits(entry_id) }); + + let mmu_item_content = spi_mem + .mmu_item_content() + .read() + .spi_mmu_item_content() + .bits(); + + (mmu_item_content & SOC_MMU_VALID_VAL_MASK) << shift_code +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let spi_mem = unsafe { &*esp32c6::SPI0::ptr() }; + spi_mem + .mmu_item_index() + .write(|w| unsafe { w.spi_mmu_item_index().bits(entry_id) }); + + let mmu_item_content = spi_mem + .mmu_item_content() + .read() + .spi_mmu_item_content() + .bits(); + + (mmu_item_content & SOC_MMU_VALID) != 0 +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32h2.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32h2.rs @@ -0,0 +1,79 @@ +use crate::mmu_hal::{MMU_PAGE_8KB, MMU_PAGE_16KB, MMU_PAGE_32KB, MMU_PAGE_64KB}; + +const SOC_MMU_ENTRY_NUM: u32 = 256; +const SOC_MMU_VALID_VAL_MASK: u32 = 0x1ff; +const SOC_MMU_VALID: u32 = 1 << 9; + +fn soc_mmu_vaddr_mask(mmu_id: u32) -> u32 { + mmu_ll_get_page_size(mmu_id) * SOC_MMU_ENTRY_NUM - 1 +} + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + let spi_mem = unsafe { &*esp32h2::SPI0::ptr() }; + let page_size_code = spi_mem.mmu_power_ctrl().read().spi_mmu_page_size().bits(); + + match page_size_code { + 0 => MMU_PAGE_64KB, + 1 => MMU_PAGE_32KB, + 2 => MMU_PAGE_16KB, + _ => MMU_PAGE_8KB, + } +} + +pub fn mmu_ll_get_entry_id(mmu_id: u32, vaddr: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + MMU_PAGE_8KB => 13, + _ => { + error!("mmu_ll_get_entry_id failed!"); + + 0 + } + }; + + (vaddr & soc_mmu_vaddr_mask(mmu_id)) >> shift_code +} + +pub fn mmu_ll_entry_id_to_paddr_base(mmu_id: u32, entry_id: u32) -> u32 { + let shift_code = match mmu_ll_get_page_size(mmu_id) { + MMU_PAGE_64KB => 16, + MMU_PAGE_32KB => 15, + MMU_PAGE_16KB => 14, + MMU_PAGE_8KB => 13, + _ => { + error!("mmu_ll_entry_id_to_paddr_base failed!"); + + 0 + } + }; + + let spi_mem = unsafe { &*esp32h2::SPI0::ptr() }; + spi_mem + .mmu_item_index() + .write(|w| unsafe { w.spi_mmu_item_index().bits(entry_id) }); + + let mmu_item_content = spi_mem + .mmu_item_content() + .read() + .spi_mmu_item_content() + .bits(); + + (mmu_item_content & SOC_MMU_VALID_VAL_MASK) << shift_code +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let spi_mem = unsafe { &*esp32h2::SPI0::ptr() }; + spi_mem + .mmu_item_index() + .write(|w| unsafe { w.spi_mmu_item_index().bits(entry_id) }); + + let mmu_item_content = spi_mem + .mmu_item_content() + .read() + .spi_mmu_item_content() + .bits(); + + (mmu_item_content & SOC_MMU_VALID) != 0 +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32s2.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32s2.rs @@ -0,0 +1,58 @@ +const SOC_MMU_VADDR_MASK: u32 = 0x3FFFFF; +const DR_REG_MMU_TABLE: u32 = 0x61801000; +const SOC_MMU_VALID_VAL_MASK: u32 = 0x3fff; +const SOC_MMU_INVALID: u32 = 1 << 14; +const SOC_IRAM0_CACHE_ADDRESS_LOW: u32 = 0x40080000; +const SOC_IRAM0_CACHE_ADDRESS_HIGH: u32 = 0x40400000; +const SOC_IRAM1_ADDRESS_LOW: u32 = 0x40400000; +const SOC_IRAM1_ADDRESS_HIGH: u32 = 0x40800000; +const SOC_DROM0_ADDRESS_LOW: u32 = 0x3f000000; +const SOC_DROM0_ADDRESS_HIGH: u32 = 0x3f400000; +const SOC_DRAM0_CACHE_ADDRESS_LOW: u32 = 0x3fc00000; +const SOC_DRAM0_CACHE_ADDRESS_HIGH: u32 = 0x3ff80000; +const SOC_DRAM1_ADDRESS_LOW: u32 = 0x3f800000; +const SOC_DRAM1_ADDRESS_HIGH: u32 = 0x3fc00000; +const SOC_DPORT_CACHE_ADDRESS_LOW: u32 = 0x3f500000; +const SOC_DPORT_CACHE_ADDRESS_HIGH: u32 = 0x3f800000; +const PRO_CACHE_IBUS0_MMU_START: u32 = 0; +const PRO_CACHE_IBUS1_MMU_START: u32 = 0x100; +const PRO_CACHE_IBUS2_MMU_START: u32 = 0x200; +const PRO_CACHE_DBUS0_MMU_START: u32 = 0x300; +const PRO_CACHE_DBUS1_MMU_START: u32 = 0x400; +const PRO_CACHE_DBUS2_MMU_START: u32 = 0x500; + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + crate::mmu_hal::MMU_PAGE_64KB +} + +pub fn mmu_ll_get_entry_id(_mmu_id: u32, vaddr: u32) -> u32 { + let offset = if soc_address_in_bus!(SOC_DROM0, vaddr) { + PRO_CACHE_IBUS2_MMU_START / 4 + } else if soc_address_in_bus!(SOC_IRAM0_CACHE, vaddr) { + PRO_CACHE_IBUS0_MMU_START / 4 + } else if soc_address_in_bus!(SOC_IRAM1, vaddr) { + PRO_CACHE_IBUS1_MMU_START / 4 + } else if soc_address_in_bus!(SOC_DPORT_CACHE, vaddr) { + PRO_CACHE_DBUS2_MMU_START / 4 + } else if soc_address_in_bus!(SOC_DRAM1, vaddr) { + PRO_CACHE_DBUS1_MMU_START / 4 + } else if soc_address_in_bus!(SOC_DRAM0_CACHE, vaddr) { + PRO_CACHE_DBUS0_MMU_START / 4 + } else { + error!("mmu_ll_get_entry_id failed!"); + + 0 + }; + + offset + ((vaddr & SOC_MMU_VADDR_MASK) >> 16) +} + +pub fn mmu_ll_entry_id_to_paddr_base(_mmu_id: u32, entry_id: u32) -> u32 { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_VALID_VAL_MASK) << 16 } +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_INVALID) == 0 } +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/esp32s3.rs b/vendor/esp-hal-ota/src/mmu_ll/esp32s3.rs @@ -0,0 +1,22 @@ +const SOC_MMU_VADDR_MASK: u32 = 0x1FFFFFF; +const DR_REG_MMU_TABLE: u32 = 0x600C5000; +const SOC_MMU_VALID_VAL_MASK: u32 = 0x3fff; +const SOC_MMU_INVALID: u32 = 1 << 14; + +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + crate::mmu_hal::MMU_PAGE_64KB +} + +pub fn mmu_ll_get_entry_id(_mmu_id: u32, vaddr: u32) -> u32 { + (vaddr & SOC_MMU_VADDR_MASK) >> 16 +} + +pub fn mmu_ll_entry_id_to_paddr_base(_mmu_id: u32, entry_id: u32) -> u32 { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_VALID_VAL_MASK) << 16 } +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, entry_id: u32) -> bool { + let ptr = (DR_REG_MMU_TABLE + entry_id * 4) as *const u32; + unsafe { ((*ptr) & SOC_MMU_INVALID) == 0 } +} diff --git a/vendor/esp-hal-ota/src/mmu_ll/mod.rs b/vendor/esp-hal-ota/src/mmu_ll/mod.rs @@ -0,0 +1,64 @@ +#[cfg(any(feature = "esp32", feature = "esp32s2"))] +macro_rules! soc_address_in_bus { + ($bus_name:ident, $vaddr:ident) => {{ + (concat_idents!($bus_name, _ADDRESS_LOW)..concat_idents!($bus_name, _ADDRESS_HIGH)) + .contains(&$vaddr) + }}; +} + +#[cfg(feature = "esp32")] +mod esp32; +#[cfg(feature = "esp32")] +pub use esp32::*; + +#[cfg(feature = "esp32s2")] +mod esp32s2; +#[cfg(feature = "esp32s2")] +pub use esp32s2::*; + +#[cfg(feature = "esp32s3")] +mod esp32s3; +#[cfg(feature = "esp32s3")] +pub use esp32s3::*; + +#[cfg(feature = "esp32c2")] +mod esp32c2; +#[cfg(feature = "esp32c2")] +pub use esp32c2::*; + +#[cfg(feature = "esp32c3")] +mod esp32c3; +#[cfg(feature = "esp32c3")] +pub use esp32c3::*; + +#[cfg(feature = "esp32c6")] +mod esp32c6; +#[cfg(feature = "esp32c6")] +pub use esp32c6::*; + +#[cfg(feature = "esp32h2")] +mod esp32h2; +#[cfg(feature = "esp32h2")] +pub use esp32h2::*; + +#[cfg(not(any( + feature = "esp32", + feature = "esp32s2", + feature = "esp32s3", + feature = "esp32c2", + feature = "esp32c3", + feature = "esp32c6", + feature = "esp32h2" +)))] +mod not_selected; + +#[cfg(not(any( + feature = "esp32", + feature = "esp32s2", + feature = "esp32s3", + feature = "esp32c2", + feature = "esp32c3", + feature = "esp32c6", + feature = "esp32h2" +)))] +pub use not_selected::*; diff --git a/vendor/esp-hal-ota/src/mmu_ll/not_selected.rs b/vendor/esp-hal-ota/src/mmu_ll/not_selected.rs @@ -0,0 +1,15 @@ +pub fn mmu_ll_get_page_size(_mmu_id: u32) -> u32 { + 0 +} + +pub fn mmu_ll_get_entry_id(_mmu_id: u32, _vaddr: u32) -> u32 { + 0 +} + +pub fn mmu_ll_entry_id_to_paddr_base(_mmu_id: u32, _entry_id: u32) -> u32 { + 0 +} + +pub fn mmu_ll_check_entry_valid(_mmu_id: u32, _entry_id: u32) -> bool { + false +} diff --git a/vendor/esp-hal-ota/src/structs.rs b/vendor/esp-hal-ota/src/structs.rs @@ -0,0 +1,63 @@ +pub(crate) type Result<T> = core::result::Result<T, OtaError>; + +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum OtaError { + NotEnoughPartitions, + OtaNotStarted, + FlashRWError, + WrongCRC, + WrongOTAPArtitionOrder, + OtaVerifyError, + CannotFindCurrentBootPartition, +} + +#[derive(Clone)] +pub struct FlashProgress { + pub last_crc: u32, + pub flash_offset: u32, + pub flash_size: u32, + pub remaining: u32, + + pub target_partition: usize, + pub target_crc: u32, +} + +#[derive(Debug)] +pub struct PartitionInfo { + pub ota_partitions: [(u32, u32); 16], + pub ota_partitions_count: usize, + + pub otadata_offset: u32, + pub otadata_size: u32, +} + +#[repr(u32)] +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum OtaImgState { + EspOtaImgNew = 0x0, + EspOtaImgPendingVerify = 0x1, + EspOtaImgValid = 0x2, + EspOtaImgInvalid = 0x3, + EspOtaImgAborted = 0x4, + EspOtaImgUndefined = 0xFFFFFFFF, +} + +#[repr(C)] +#[derive(Debug)] +pub struct EspOtaSelectEntry { + pub seq: u32, + pub seq_label: [u8; 20], + pub ota_state: OtaImgState, + pub crc: u32, +} + +impl EspOtaSelectEntry { + /// Check if crc(of seq) is correct, if not - its setting seq to 0 + pub fn check_crc(&mut self) { + if !crate::helpers::is_crc_seq_correct(self.seq, self.crc) { + self.seq = 0; // set seq to 0 if crc not correct! + } + } +}