Compare commits

...

963 Commits

Author SHA1 Message Date
ris
a7612ada45 LED data gets transmitted using signal but not stable yet
Some checks failed
CI - nightly / esp-hal | nightly (${{ matrix.device.soc }}) (map[soc:esp32c2 target:riscv32imc-unknown-none-elf]) (push) Has been cancelled
CI - nightly / esp-hal | nightly (${{ matrix.device.soc }}) (map[soc:esp32c3 target:riscv32imc-unknown-none-elf]) (push) Has been cancelled
CI - nightly / esp-hal | nightly (${{ matrix.device.soc }}) (map[soc:esp32c6 target:riscv32imac-unknown-none-elf]) (push) Has been cancelled
CI - nightly / esp-hal | nightly (${{ matrix.device.soc }}) (map[soc:esp32h2 target:riscv32imac-unknown-none-elf]) (push) Has been cancelled
2025-01-09 19:43:59 -05:00
ris
d581195df7 LEDs write correctly and mulitcore now 2025-01-09 15:34:38 -05:00
Dániel Buga
040c0fd353
Mark Flex methods as unstable (#2917) 2025-01-09 16:13:12 +00:00
Dániel Buga
021676e871
Remove more enum prefixes (#2922) 2025-01-09 15:33:58 +00:00
Dániel Buga
848029b152
Test all feature sets (#2901)
* Mark interconnect as unstable

* Explicitly set unstable feature in HIL tests

* WIP append feature set name to artifact

* Add name to feature sets, build all combinations

* Fix tests

* Provide a looping executor for stable async tests

* Fix usb serial jtag

* Hide interconnect types
2025-01-09 13:58:14 +00:00
Dániel Buga
2b80e4d123
Return error instead of panic (#2916) 2025-01-09 13:47:54 +00:00
Dániel Buga
0ef00206d5
Remove all instance type params (#2907) 2025-01-09 11:27:48 +00:00
Dániel Buga
409641dd7e
Document that UART TX should be set up first (#2914) 2025-01-09 10:29:46 +00:00
Dániel Buga
9f553b1b0e
Mark ClockSources as #[non_exhaustive] (#2912) 2025-01-08 19:07:25 +00:00
Juraj Sadel
8a7f8361a6
UART: Move RX/TX pin assignment from constructor to builder functions (#2904)
* Add with_rx() and with_tx() methods to UART drivers

* changelog

* migration guide

* forgotten tests

* fmt

* fix H2 example

* Use the same calling order of calling TX and RX as before
2025-01-08 16:35:22 +00:00
Jesse Braham
7d0b39dbd2
Fix naming violations for SPI Address and Command enums (#2906)
* Fix naming violations for SPI `Address` and `Command` enums

* Update migration guide

* Update `CHANGELOG.md`
2025-01-08 14:39:54 +00:00
Dániel Buga
246e7f1c8b
Disable failing tests (#2910) 2025-01-08 14:38:10 +00:00
Björn Quentin
6b4312fb90
Use own implementation instead of ROM functions, re-add memchr (#2896)
* Use own implementation instead of ROM functions, re-add memchr ROM function

* CHANGELOG.md

* Improve

* Cast
2025-01-08 07:12:04 +00:00
Davo
5a64d9ba8f
feat: add support for internal temperature sensor (tsens) for esp32c6 and esp32c3 (#2875)
* feat: add basic support for temperature sensor (tsens) for esp32c6

* feat: add basic support for temperature sensor (tsens) for esp32c3

* feat: add configurable clock source for temperature sensor

* feat: add Temperature struct to avoid enforcing usage of floats

- Also add misc derives to multiple structs
- Add power_up / power_down methods to TemperatureSensor
- Enable ApbSarAdc via PeripheralGuard

* fix: move tsens module to unstable module list
2025-01-07 16:40:12 +00:00
Juraj Sadel
f1276f7d1b
Remove unnecessary prefixes/suffixes from Error and TxEvent enums (#2898)
* Remove unnecessary prefixes/suffixes from Error and TxEvent enums

* Remove #[allow(clippy::enum_variant_names ...)

* Use object+verb naming in Error enum variant

* Migration guide entry

* Remove ZeroLengthBufferPassed variant

* docs
2025-01-07 16:08:10 +00:00
Jesse Braham
bb406cec6b
Fix naming violations for spi::Mode enum variants (#2902)
* Fix naming violations for `spi::Mode`

* Update migration guide

* Update `CHANGELOG.md`
2025-01-07 15:55:19 +00:00
Björn Quentin
66d2effee2
Stabilize CpuClock, make non-exhaustive, rename variants (#2899)
* Stabilize CpuClock, make non-exhaustive, rename variants

* CHANGELOG.md

* Fix
2025-01-07 14:43:41 +00:00
Dominic Fischer
b3401bff59
Refactor SPI MISO setup (#2557)
* Refactor SPI MISO setup

* update HIL

* docs

* missed a spot

* fix changelog

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
Co-authored-by: Scott Mabin <scott@mabez.dev>
2025-01-07 11:31:26 +00:00
Jesse Braham
2a4e58a230
UART: Remove blocking version of read_bytes and rename drain_fifo to read_bytes instead (#2895)
* Remove `read_bytes` function, rename `drain_fifo` to `read_bytes`

* Update migration guide

* Update `CHANGELOG.md`

* Use `crate::interrupt::free` in `read_byte`

* Fix HIL test

* Only use `crate::interrupt:free` for ESP32
2025-01-07 10:02:29 +00:00
Juraj Sadel
5cd0d6f6bf
Alter stability note in README and briefly explain unstable feature (#2894)
* Alter stability note in README and briefly explain unstable feature

* Review comments
2025-01-07 09:03:30 +00:00
Jesse Braham
39da5337ac
Fix naming violations and clean up some doc comments in UART driver (#2893)
* Resolve naming violation for `Parity` enum

* Remove unnecessary/redundant information from doc comments

* Resolve naming violations for `DataBits` and `StopBits` enums

* Update migration guide

* Update `CHANGELOG.md`
2025-01-06 12:11:06 +00:00
Dominic Fischer
7319458dd2
Properly reset descriptors in DmaRxStreamBuf::prepare (#2890)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2025-01-06 09:16:44 +00:00
Jesse Braham
05b5bac027
Add package metadata to esp-storage to make documentation build (#2891) 2025-01-06 08:03:53 +00:00
Dominic Fischer
6494354a91
Fix small typo in migration guide (#2888)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2025-01-06 07:14:47 +00:00
Dániel Buga
713cd491b6
GPIO: Refactor AnyPin to contain a u8 (#2854)
* Remove panicking match from Flex::set_level

* Rework AnyPin to contain a u8

* SPI

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2025-01-03 14:46:39 +00:00
Dániel Buga
337b3cc6b7
Use _CONFIG_ to separate config prefix and key (#2848)
* Use two underscores to separate prefix

* Change separator to _CONFIG_

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2025-01-03 14:36:30 +00:00
Björn Quentin
dc2b968491
qa-test (#2871)
* Run multiple examples/tests

* Adapt some qa-tests
2025-01-03 14:31:19 +00:00
Dániel Buga
19eb7728bb
Allow clippy to break API, ignore a few initialism errors (#2840) 2025-01-03 14:13:07 +00:00
Björn Quentin
551386216e
Mention performance considerations (#2881) 2025-01-03 12:34:52 +00:00
Dániel Buga
1f929af377
Remove redundant config setters (#2847)
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2025-01-02 09:55:37 +00:00
Sergio Gasquez Arcos
06a15807e3
Fix C-METADATA violations (#2874)
* fix: C-METADATA violations of esp-hal

* feat: Normalize keyword and categories for most of the pacakges
2025-01-02 09:44:27 +00:00
Anthony Grondin
0f384992cf
Update smoltcp to 0.12.0 and embassy-net to 0.5.0 (#2849)
* chore: Update smoltcp to `0.12.0` and embassy-net to `0.5.0`

* Add CHANGELOG entry

* Remove `wifi_dhcp_smoltcp_nal.rs` example

`smoltcp-nal`, a core dependency on which this example depends on doesn't receive the desired amount of maintainability needed to keep up to date with new dependencies releases.
2025-01-02 09:41:31 +00:00
Björn Quentin
36095e447e
Hide Info,State,Instance (#2856)
* Hide Info,State,Instance

* Fix lp_gpio macro

* Fix visibility
2024-12-23 13:57:31 +00:00
Dániel Buga
c2de8a1859
Mark SPI slave as unstable (#2853) 2024-12-20 15:23:29 +00:00
Juraj Sadel
b9ebeb1809
Solve unstable inconsistencies in SPI master driver (#2852)
* Solve unstable unconsistencies in SPI master driver

* Mark Command, Address, and DataMode unstable as well
2024-12-20 14:49:59 +00:00
Kirill Mikhailov
8b16365c2d
Make ConfigError enum follow naming convention (#2855)
* Make `ConfigError` follow naming convention

* changelog entry

* !(changelog entry)
2024-12-20 14:36:54 +00:00
Kirill Mikhailov
62c72947dd
Multiple API fixes in UART driver (#2851)
* Close a number of issues

doctest update

fmt

* changelog entry

* dumb

* addressing reviews

* Add an entry to migration guide
2024-12-20 14:01:11 +00:00
Kirill Mikhailov
286219707c
I2C: Prefer compile-time checks over runtime checks where possible, prefer a fallible API over panics. (#2831)
* I2C module improvements (raw)

* fmt

* dumb

dumb2

dumb 3

dumb 4

dumb 5

* re-use `ExceedingFifo` instead of new `ExceedingTransactionSize` error

* changelog entry

* address reviews

* rebase

* dumb 6

* rebase

...
2024-12-20 13:18:28 +00:00
Dániel Buga
d66e153686
Remove Pin::gpio_bank (#2850) 2024-12-20 12:33:10 +00:00
Dániel Buga
7f8af8a651
Remove prelude (#2845)
* Remove prelude

* Changelog
2024-12-20 10:24:57 +00:00
C2D
2e6a95ac99
Add SpiDmaBus::split for moving between manual & automatic DMA buffers (#2824)
* Allow swapping dma buffers

* Deconstruct makes more sense

* Format

* Changelog

* Race-conditioned

* Change SpiDmaBus::deconstruct name to SpiDmaBus::split

* Add flush & bracket references

* Fix mutability

* Fix name of generic param

---------

Co-authored-by: ferris <ferris@devdroplets.com>
Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-12-20 09:23:33 +00:00
Björn Quentin
5c30c925ca
Make more SPI interrupts available (#2833)
* Make more SPI interrupts available

* CHANGELOG.md

* SPI interrupts for ESP32/ESP32-S2

* Fix

* Don't offer error interrupts

* Change doc wording

* Renaming

* Rebase fun

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-12-20 07:54:58 +00:00
Scott Mabin
f83ab23f04
Avoid abbreviations in API (#2844)
* Avoid abbreviations in API

* changelog/migration
2024-12-19 14:39:40 +00:00
C2D
f1c372f250
Fix SpiDmaBus write impl (#2843)
* Fix SpiDmaBus write impl

* Add hil test for SpiDmaBus::{read,write}

---------

Co-authored-by: ferris <ferris@devdroplets.com>
2024-12-19 13:57:21 +00:00
Dániel Buga
151e66c3b3
Implement missing traits on GPIO types (#2842) 2024-12-19 11:31:54 +00:00
Dániel Buga
a3b3547212
Implement some missing traits (#2823) 2024-12-19 10:58:49 +00:00
Jesse Braham
1fff464b66
Derive common traits for various types in uart and i2c drivers (#2825)
* Derive `Eq` for `uart::ConfigError`

* Derive common traits in `i2c::master` module for various types

* Update `CHANGELOG.md`

* Implement `Display` and `Error` traits for I2C/UART error types

* Remove `PartialEq` and `Eq` derives from I2C driver
2024-12-19 10:10:30 +00:00
Jesse Braham
036d08e09f
Annotate builder functions with #[must_use] (#2841) 2024-12-19 10:10:23 +00:00
Dániel Buga
cde6169d6d
Walk back on PartialEq/Eq (#2834) 2024-12-19 09:00:35 +00:00
Sergio Gasquez Arcos
d4386adfc7
Rename Spi enums (#2828)
* feat: Rename Spi enums

* docs: Update changelog

* feat: Rename crate::Mode to crate::DriverMode

* docs: Udpate changelog

* feat: Rename DM type parameter to Dm for ECC

* style: rustfmt

* feat: Rename crate::Mode to crate::DriverMode
2024-12-19 08:41:59 +00:00
Dániel Buga
97598968eb
GPIO: prevent woken task interrupting GPIO handler (#2838)
* Clear interrupt bit before allowing waker to wake a task

* Add test
2024-12-19 07:53:48 +00:00
Dániel Buga
b8f15f0a8b
Refine API-GUIDELINES recommendations (#2832)
* Refine C-COMMON-TRAITS recommendations

* Recommend deriving Error

* Clarify that Instance, State and Info are private implementation details at this point
2024-12-19 07:08:25 +00:00
Dániel Buga
f2b958b501
Convert into c_char (#2837) 2024-12-18 18:59:28 +00:00
Dániel Buga
f7c1bdbfc5
Implement Hash and defmt::Format for InterruptHandler (#2830) 2024-12-18 16:27:27 +00:00
Scott Mabin
78c63a7a0f
fix link to esp-wifi self hosted docs (#2836) 2024-12-18 14:43:38 +00:00
Dániel Buga
af8eaea1e3
Pin 1.83.0.1 in CI (#2835) 2024-12-18 12:29:48 +00:00
Juraj Sadel
1684ba10f0
Rename TOUCHMODE to Tm (#2829) 2024-12-18 08:37:09 +00:00
Dániel Buga
2ca1545b50
SPI: Implement interrupt-driven transfer_in_place_async (#2691)
* Implement transfer_async

* The start of our shiny future

* Add State

* Wake from interrupt

* Rename and remove return value

* Fix register write

* Fix S2

* Rename traits

* Async flushes

* Flush before async operations

* Fix comments

* Rename start fn, place async handler in RAM

* Explicitly stop listening before async operations
2024-12-18 07:32:12 +00:00
Frostie314159
f990957f21
Updated PACs and made Wi-Fi non virtual on the ESP32. (#2822) 2024-12-17 16:54:51 +00:00
Juraj Sadel
d9f1e9a53f
Rename DM type parameter to Dm (#2821)
* Rename DM type parameter to Dm

* Rename M, DmaMode, MODE type parameters to Dm

* fmt
2024-12-17 16:49:23 +00:00
Scott Mabin
85d30e9816
Updates for Xtensa enabled 1.83 compiler (#2615)
* test ci

* fix ci with new compiler

* god bless clippy fix

* refmuts

* clippy

* tests work

* use new compiler

* use new compiler

* bump MSRV of esp-hal and crates that depend on esp-hal

* fix eyesore

* clippy again

* remove hardcoded compiler version

* bump rust-version as well

* note MSRV bump in changelog
2024-12-17 15:02:03 +00:00
Dániel Buga
a12e7fece1
Fix WIFI_EVENT (#2817)
* Fix WIFI_EVENT

* Update esp-wifi/src/common_adapter/mod.rs

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-12-16 11:53:45 +00:00
Dániel Buga
bc0bedd628
Add priority-limited locks (#2684)
* Add priority-limited locks

* Rename to RawMutex, only provide lock() publicly

* Explode implementation and move into the interrupt module
2024-12-16 08:39:42 +00:00
Juraj Sadel
3a03dd88c7
Prefer line comments // over block comments /* */ (#2738)
* Prefer line comments // over block comments /* */

* esp-wifi: Prefer line comments // over block comments /* */

* Mention in our API guideline that // should be prefered over /* */
2024-12-12 15:53:38 +00:00
Dániel Buga
cc4e527eaf
Fix async USB OTG-FS driver (#2742)
* Use unwrap macro

* Clean up reset

* Better replicate synopsys init

* Fix indentation

* Clean up constructor

* Initialize before poll

* Remove prefix

* Keep the Usb PeripheralGuard around

* Remove example addition
2024-12-12 13:16:32 +00:00
Kaspar Schleiser
d66281609b
esp-hal: otg_fs: drop obsolete late cnak quirk (#2621)
* esp-hal: otg_fs: drop obsolete late cnak quirk

* build: bump embassy-usb-synopsys-otg to 0.2.0
2024-12-11 23:49:16 +00:00
Björn Quentin
62994578c2
Fix qa-test build.rs (#2722)
* Fix qa-test build.rs

* Once is enough
2024-12-10 15:32:29 +00:00
Dániel Buga
35d3ed301c
Clean the correct bit (#2721) 2024-12-10 14:09:11 +00:00
Dániel Buga
273fdc0928
ESP32-S2: implement CryptoDMA for AES (#2699)
* Changelog

* Split up PDMA into modules

* Add CryptoDMA implementation

* Move file

* Import SELECT only in the function where we use it

---------

Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
2024-12-10 13:02:20 +00:00
Dániel Buga
3cc8d611bd
Update PACs (#2719) 2024-12-10 11:23:52 +00:00
Jesse Braham
f6126502ae
Actually use a random seed in Wi-Fi examples (#2718) 2024-12-10 11:02:05 +00:00
Dániel Buga
d2f15d69d7
Fix signal fn recommendation (#2692) 2024-12-06 13:36:20 +00:00
Dániel Buga
5135965116
Hide most of the unstable peripherals (#2667)
* Hide most of the unstable peripherals

* Lint with correct toolchain, lint with unstable enabled

* Require unstable feature and lint using it

* Auto-lint xtensas with esp toolchain

* Fix msrv and ieee802154

* Add feature to examples

* Don't require building ieee802154 for all examples

* Mark modules in documentation
2024-12-06 11:03:56 +00:00
Dániel Buga
6b01f7993b
SPI and related changes (#2681)
* Define Octal SpiDataMode

* Fix BitOrder capitalization

* Hide DmaError

* Derive more traits

* Return error for unsupported half-duplex parameter combinations

* Remove unnecessary implementation detail

* Return error instead of silently breaking transaction

* Downgrade assert to debug_assert

* Expand on the enum variants

* Remove redundant imports

* Hide some unstable functions
2024-12-06 10:30:43 +00:00
Jesse Braham
d86a079ea9
Seal the PeripheralInput and PeripheralOutput traits (#2690)
* Seal the `PeripheralInput` and `PeripheralOutput` traits

* Update `CHANGELOG.md`
2024-12-06 09:13:39 +00:00
Dániel Buga
9458fd3ed4
[DMA 8/8] Burst configuration (#2543)
* Implement burst configuration

* Reject transfers if the DMA in incapable of accessing external memory

* Fix psram

* Rename, documentation

* Address a few review comments

* Check buffer length, too

* Return error instead of panic

* Allow users to only specify the relevant burst config

* Add missing conversion

* Add missing docs

* Fix IN alignment requirements

* Fix test

* Deduplicate chunk size literal
2024-12-06 08:30:58 +00:00
Dániel Buga
2d4ccd735f
Prevent creating GpioPin (#2688) 2024-12-06 06:20:49 +00:00
Dániel Buga
b4379b8518
Auto-implement Debug, PartialEq and defmt::Format for peripherals (#2682) 2024-12-05 13:33:12 +00:00
Jesse Braham
b26b31f1ce
Mention that config structs should derive procmacros::BuilderLite in the API guidelines (#2686) 2024-12-05 13:23:09 +00:00
Tommaso Clini
dfa96820f0
DHCP support added to wifi embassy access point example (#2683)
* added dhcp to access point example, also GW IP is configure from environment as shown in Cargo.toml

* changelog entry

* Revert "changelog entry"

This reverts commit 3412d1c194.

* default gateway IP in case env IP isn't provided

* dhcp server runs in a loop so that it will restart on an error
2024-12-05 11:22:36 +00:00
Kirill Mikhailov
033c4b84c6
RESERVED_INTERRUPTS to be INTERRUPT_TO_PRIORITY (#2676) 2024-12-04 16:43:41 +00:00
Dániel Buga
50387290d9
API-GUIDELINES tweaks (#2677)
* Add PeripheralGuard exception

* Add cfg! macro recommendation
2024-12-04 15:52:59 +00:00
Dániel Buga
dcded33d3d
Fix into_async/blocking on typed Spi (#2674) 2024-12-04 14:45:52 +00:00
Juraj Sadel
d54f8440a5
HIL(QOL): Use global timeout instead of timeout macros (#2489)
* HIL(QOL): Add missing timeouts to various tests

* Increase timeouts for ECC

* Use global timeout in hil tests

* sha: increase test_digest_of_size_1_to_200 timeout from 10 to 15 seconds
2024-12-04 12:03:39 +00:00
Dániel Buga
91d7f23982
Mark some dependencies as unstable (#2668)
* Mark some dependencies as unstable

* Fix docs

* Pass unstable to doctests

* Document the unstable feature
2024-12-04 09:58:41 +00:00
Jesse Braham
a189eff517
Use cfg_if in favour of multiple cfgs in set_rx_fifo_full_threshold function (#2670) 2024-12-03 09:27:08 +00:00
Jesse Braham
da59a4eb36
Use upper camel case for UART's StopBits variants (#2669)
* Use upper camel case for UART's `StopBits` variants

* Update `CHANGELOG.md`
2024-12-03 08:28:04 +00:00
Dominic Fischer
94e7ffbcef
Remove Dma[Rx|Tx]Buffer::length (#2587)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-12-03 08:27:13 +00:00
Dániel Buga
a6a83d3bb5
Track async GPIOs in memory (#2625)
* Track async GPIOs in memory

* Add an example

* Deduplicate interrupt handling

* Changelog

* Add gpio_bank_1 symbol

* Derive EnumCount

* Try to fix issues around manual listen calls and multi-core

* Fix test

* Update esp-hal/src/gpio/mod.rs

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

* Do not prevent pending interrupt from being handled

* Remove unnecessary unpin

* Add a note about interrupt status flags

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-12-02 15:35:10 +00:00
Jesse Braham
891a12e13f
Derive Builder Lite pattern for HAL configuration, update examples/tests (#2645)
* Derive Builder Lite pattern for `esp_hal::Config` and `WatchdogConfig`

* User builder pattern for `esp_hal::Config` in examples/tests

* Update `CHANGELOG.md`
2024-12-02 14:45:05 +00:00
Dániel Buga
9f3476b006
Unstable documentation proof of concept (#2628)
* Unstable documentation proof of concept

* Hide the red banner in esp-wifi documentation

* Changelog
2024-12-02 10:49:06 +00:00
Dániel Buga
2d3fdeb876
Don't require importing macro for esp-config (#2630) 2024-12-02 08:03:46 +00:00
Danila Gornushko
2d87bb0002
Add heap usage stats with defmt (#2619)
* feat(esp-alloc): Add heap usage stats and provide `esp_alloc::get_info!()` macro

* refactor(esp-alloc): Feature gate internal memory usage that requires extra computation.

- Introduce the `internal-heap-stats` feature for `esp-alloc`.
- Add `esp_alloc::get_info!()` to `psram_quad` example to show usage and
ensure coverage of the feature in tests.

* refactor(esp-alloc): Remove `get_info!()` macro in favour of documenting `HEAP.stats()`

* Implement defmt::Format for HeapStats and RegionStats

* rustfmt

* show usage percent + move bar drawing logic to separate functions

* update doc comments

* Fixed a typo in qa-test/src/bin/psram_quad.rs

Co-authored-by: Scott Mabin <scott@mabez.dev>

* minor improvements to write bar functions

* Aligned the indentation in Cargo.toml

Co-authored-by: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com>

* Fixed a typo in docs

Co-authored-by: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com>

* Nitpicking x2

Co-authored-by: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com>

* Surround a function call with backticks

Co-authored-by: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com>

* rustfmt

---------

Co-authored-by: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com>
Co-authored-by: Scott Mabin <scott@mabez.dev>
Co-authored-by: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com>
2024-11-28 13:07:36 +00:00
Björn Quentin
b6117d5040
Use opt-level to detect debug profile (#2622) 2024-11-28 10:52:11 +00:00
Dániel Buga
92910bf1cb
Constructor consistency update (#2610)
* UART: only implement constructors with config, define ConfigError

* UART: only implement interrupt functions for Blocking

* I2C: fallible constructors

* Lcd/Cam

* SPI

* Update tests and examples

* Changelog

* Add note about ConfigError

* Fmt
2024-11-28 09:28:50 +00:00
Jesse Braham
1a2bee6f1f
Add derive macro for BuilderLite, add #[non_exhaustive] to some enums and structs (#2614)
* Add a derive procmacro to implement the Builder Lite pattern for a struct

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in I2C module

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in UART module

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in SPI module

* Update `CHANGELOG.md`

* Fix build errors in HIL tests

* Fix generated doc comments

* Return a `ParseError` rather than panicking

* Add a method to set the value to `None` for `Option` types
2024-11-27 15:54:43 +00:00
Kirill Mikhailov
aeda6ac00a
Remove embedded-hal 0.2.x impls and dependency from esp-lp-hal package (#2609)
* removed eh02 dependencies, sh*tcode, not yet tested properly,copy-pasted

* changelog entry

* Don't implement eh1 traits
2024-11-27 14:54:00 +00:00
Björn Quentin
cfb83b153d
Fixed triggering a debug-assertion during scan (#2612)
* Fixed triggering a debug-assertion during scan

* CHANGELOGs

* Change `debug_assert` into warning level log

* Enable debug-asserts in hil-test, qa-test and examples

* Change the way we detect and warn about debug-builds

* Warn if opt-level is `0` or `1`
2024-11-27 14:14:04 +00:00
Scott Mabin
2512658653
[3/3] Timer refactor: Timer driver mode, ETM support and erasure (#2586)
* Add mode param and type erasure to high level timer drivers

* Add async impls for the timers plus eha impl

* re add etm example, fix etm for systimer

* re add tests

* Add Into<AnyTimer> + 'static bounds to the Timer trait

* remove set_alarm_active impl detail from the timer trait

* clippy

* doc fix ups

* changelog and migration guide

* review

* fix h2, reuse schedule for delay
2024-11-27 14:10:56 +00:00
Dániel Buga
b50a075449
Amend rust guidelines (#2617) 2024-11-27 12:41:51 +00:00
Scott Mabin
7095576e6a
Move interrupt related bits out of lib.rs and into the interrupt module (#2613)
* move interrupt related bits out of lib.rs and into the interrupt module

* changelog and migration guide

* review
2024-11-27 10:29:32 +00:00
Dániel Buga
eec75c8f82
Replace some esp-wifi critical sections with locks (#2554)
* Replace some esp-wifi critical sections with locks

* Remove critical section from event handlers

* Fix doc warnings and accidentally hard-coded esp32s3

* Use Lock in wifi_int_disable/restore

* Replace critical_section in ConcurrentQueue

* Deduplicate wifi_int_disable
2024-11-25 17:06:05 +00:00
Dániel Buga
aed0fac0eb
Rewrite time driver (#2559)
* Rewrite time driver

* Don't store priority

* Changelog

* Fix doc example

* Use separate locks for Alarms

* Mention generic queues

* Cache the next wakeup timestamp

* Immediately repoll if timestamp is in the past

* Add benchmark

* Remove equality check for now

* Enable interrupts when allocating the alarm

* Clean up

* Use relaxed ordering

* wut

* Typo

* Move benchmar

* fmt
2024-11-25 17:02:47 +00:00
Jesse Braham
b06c7a470c
Remove unnecessary features from esp-hal-procmacros, enable rtc-slow feature for Xtensa devices (#2594)
* Remove unnecessary features from `esp-hal-procmacros`

* Enable the `esp-hal-procmacros/rtc-slow` feature for Xtensa devices

* Update CHANGELOGs
2024-11-25 15:18:14 +00:00
Scott Mabin
6a008bf597
note rustdoc linkage (#2595) 2024-11-25 14:32:01 +00:00
Kirill Mikhailov
a00643f22d
Remove embedded-hal 0.2.x impls and deps from esp-hal (#2593)
* Initial remove

* update ssd1306 driver version

* small docs cleanup

* migration guide

* changelog entry

* update changelog entry (move under `Removed` section)

* eh migration guide link

* `Wait` trait linking
2024-11-25 14:13:10 +00:00
Dániel Buga
ef98e2b24f
[DMA 7/8]: Remove Dma, move channels to Peripherals (#2545)
* Move DMA channels into Peripherals

* Initialize DMA in the critical section needed for clock management

* Update esp-hal/MIGRATING-0.22.md

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-11-25 09:31:18 +00:00
Kirill Mikhailov
8b36a43c07
Remove more examples. Update doctests. (#2547)
* WIP

* WIP(1)

* done

* changelog entry

* swint example needs to lose some weight

+ fix psram

* get twai and touch examples back, lcd example to qa, less embassy

* more moving

* move changelog entry

* address reviews

upd: revert "is_not_release" check

* rebase + a bit more changes

remove useless feature

* address review

remove inappropriate doctest tutorial

* get all sleep examples back and to qa-test

fmt

* get rid of some redundant printlns in doctests

* etm timer upd

* make printlns great again

* writeln! -> println!

* clear "timer with interrupts" doctest
2024-11-25 08:13:35 +00:00
Dániel Buga
3adb0b288e
0.21 Migration guide fixes (#2592) 2024-11-23 15:20:14 +00:00
Dániel Buga
fe482bdd05
Auto-initialize PSRAM (#2546) 2024-11-23 14:10:44 +00:00
Dániel Buga
09511c750a
Trim down xtensa-lx (#2357)
* Remove mutex, InterruptNumber, bare_metal and spin

* Changelog
2024-11-23 01:01:37 +00:00
Dániel Buga
51215093ca
AES cleanups (#2588)
* Deduplicate DMA trigger impl

* Deduplicate write_mode

* Fix num_block

* Clean up CipherMode setting
2024-11-23 00:37:11 +00:00
Dániel Buga
45395d4cc9
Add custom AtomicWaker and embassy-sync mutex implementation (#2555)
* Add custom AtomicWaker

* Replace Option with a null waker

* Revert "Replace Option with a null waker"

This reverts commit 9a861571790d13087e1448fa9d209d2edf956cb8.

* Clippy

* Implement RawMutex

* Move AtomicWaker, reimplement using Generic
2024-11-23 00:36:32 +00:00
Scott Mabin
79ca9d07aa
[2/3] Timer refactor: TIMG (#2581)
* system timer simplfication

* Removes _all_ type params on Alarm
* Systimer no longer implements peripheral ref, the peripheral ref
  pattern is instead intended to be used on the higher level timer
  drivers
* Removed `Unit` as a type, in favour of an enum
* Alarms are back in the main `SystemTimer` "driver"
* Made all `Unit` modification methods unsafe, it's not possible to
  modify the `Unit`'s safely whilst timers and or the `time::now` API is
  in use

* fix examples and tests (by removing them :D)

* changelog and migration

* Review feedback

* changelog and migration

* /unit_count/unit_value/g

* changelog and migration

* /unit_count/unit_value/g

* system timer simplfication

* Removes _all_ type params on Alarm
* Systimer no longer implements peripheral ref, the peripheral ref
  pattern is instead intended to be used on the higher level timer
  drivers
* Removed `Unit` as a type, in favour of an enum
* Alarms are back in the main `SystemTimer` "driver"
* Made all `Unit` modification methods unsafe, it's not possible to
  modify the `Unit`'s safely whilst timers and or the `time::now` API is
  in use

* Make TimerGroup Timer's dumb and untyped

* changelog

* review

* review
2024-11-22 16:14:14 +00:00
Dániel Buga
e98674e8fa
[DMA 6/8] More helper types & working split (#2532)
* Add helper traits to simplify DMA channel trait bounds

* Document changes

* Update doc example

* Remove clutter from MG

* Move DmaEligible down to place helper types closer

* Rename

* Include split in the MG
2024-11-22 15:59:31 +00:00
Dániel Buga
c1f0c134c3
Use a separate lock in esp-println (#2567) 2024-11-22 12:29:26 +00:00
Dániel Buga
b5775667b4
[DMA 5/8]: Clean up macros (#2527)
* Deduplicate PDMA channel impl macro

* Explicitly provide AnyDma prefix, regblock and compatible peripherals

* Clean up defining interrupt handlers

* Clean up ad-hoc ignore macro branches
2024-11-22 11:28:41 +00:00
Scott Mabin
60a2c76005
[1/4] Timer refactor: system timer (#2576)
* system timer simplfication

* Removes _all_ type params on Alarm
* Systimer no longer implements peripheral ref, the peripheral ref
  pattern is instead intended to be used on the higher level timer
  drivers
* Removed `Unit` as a type, in favour of an enum
* Alarms are back in the main `SystemTimer` "driver"
* Made all `Unit` modification methods unsafe, it's not possible to
  modify the `Unit`'s safely whilst timers and or the `time::now` API is
  in use

* fix examples and tests (by removing them :D)

* changelog and migration

* /unit_count/unit_value/g

* etm doctest

* Review feedback
2024-11-22 11:24:06 +00:00
Dániel Buga
9c1d99d9b4
Don't read to clear interrupts (#2585) 2024-11-22 10:55:53 +00:00
Dániel Buga
3a4a7632b1
[DMA 4/8]: Apply Peripheral pattern (#2526)
* Create DMA Channels inside peripherals

* Add PARL_IO into_async functions

* Update tests and examples

* Restore configurable priority via DmaChannel

* Add mode param to DPI driver

* Fix test by raising SPI frequency

* Fix split

* Changelog

* Update esp-hal/CHANGELOG.md

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-11-22 09:05:22 +00:00
Dániel Buga
f81b5f6c7f
Run a custom script before running HIL tests (#2580)
* Do not cycle USB power

* Call a script before running tests
2024-11-21 15:17:35 +00:00
Dániel Buga
973671c3cb
[DMA 3/8] Remove ChannelCreator types, temporarily disable burst mode (#2403)
* Remove ChannelCreator types and burst mode

* Fix up I2sParallel

* Always enable burst transfering descriptors

* Configure burst transfer with a non-bool for future chip support

* Reuse buffer preparation code

* Update LoopBuf as well

* Update lcd_cam tests

* Rename config, fix changelog
2024-11-21 15:01:29 +00:00
Björn Quentin
f9203dc523
Disable peripherals when unused (#2544)
* Disable peripherals when unused

* Fixes

* CHANGELOG.md

* Fix

* Address review comments

* Have dedicated guards for CAM and LCD

* Re-use `Cam`'s guard

* De-duplicate, assert

* fmt

* Require CriticalSection

* Address comments

* Remove redundant guard

* Use `GenericPeripheralGuard`

* Renaming
2024-11-21 09:21:28 +00:00
Dániel Buga
457ed44802
Slight cleanup throughout (#2575)
* Slight cleanup throughout

* Explain empty build script
2024-11-21 09:06:49 +00:00
Jesse Braham
02ddad47c0
Add new migration guides (#2571) 2024-11-21 09:05:33 +00:00
Dániel Buga
a824963943
Avoid old API in SPI example in migration guide (#2578) 2024-11-21 08:25:33 +00:00
Scott Mabin
2fc10d684c
API guideline touchups (#2573)
* guideline touchups

* review comments
2024-11-21 07:41:26 +00:00
Dominic Fischer
8600c4009f
ESP32-S3: Added SDMMC signals (#2556)
* ESP32-S3: Added SDMMC signals

* fmt

* Daniel's request

* changelog

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-20 21:49:24 +00:00
Jesse Braham
3c1aba5088
Add --no-verify for esp-riscv-rt to xtask publish (#2570) 2024-11-20 10:44:24 +00:00
Jesse Braham
bdfec3781f
New package releases (#2569)
* New package releases

* Update `CHANGELOG.md` for all packages to be published
2024-11-20 09:16:33 +00:00
Dániel Buga
73a6e32971
Add pin driver examples, explain drivers a bit better (#2563)
* Add pin driver examples, explain modes

* Remove redundant blinky mention

* Wireless keyboard strikes agan

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>

* Add println macro to before_snippet

---------

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
2024-11-19 13:53:12 +00:00
Dániel Buga
432622ca9f
Clarify embassy migration guide (#2565) 2024-11-19 13:31:43 +00:00
Dániel Buga
70fe8fb077
Remove some unnecessary prelude reexports (#2564)
* Remove some unnecessary prelude reexports

* Fix test
2024-11-19 13:31:08 +00:00
Dominic Fischer
7821968df8
Introduce RGB/DPI driver (#2415)
* Introduce RGB/DPI driver

* Choose different pin for HIL test

* fail

* Use official devkit

* merge update

* non_exhaustive

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-19 10:15:09 +00:00
Dániel Buga
26fd1a40d9
Avoid polling for no reason (#2551) 2024-11-19 07:58:02 +00:00
Scott Mabin
9c06c69600
Touch up the migration guide for esp-wifi (#2561) 2024-11-18 14:41:11 +00:00
Dániel Buga
4f6d51fefa
Add missing Sealed impl (#2560)
* Add missing Sealed impl

* Typos

* It compiles
2024-11-18 14:15:40 +00:00
Jesse Braham
2472e36232
Add the qa-test package (#2558)
* Teach `xtask` about the `qa-test` package

* Create the `qa-test` package and move some examples to it

* Check `qa-test` package in CI

* Add `README.md`
2024-11-18 11:00:17 +00:00
Dániel Buga
c6404fe569
Forget our problems (#2541) 2024-11-14 15:30:48 +00:00
Jesse Braham
d68550c485
Add a publish subcommand to the xtask (which performs a dry-run by default) (#2539)
* Update and reorganize xtask dependencies

* Add a publish subcommand (which performs a dry run by default)

* Update xtask/src/main.rs

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>

---------

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
2024-11-14 11:27:30 +00:00
Dániel Buga
52c65dd149
[DMA 2/N] Split DMA IN/OUT handlers (#2521)
* Separate IN/OUT handlers

* Split DMA IN/OUT handlers

* Reset channel async status when re-creating

* Remove resolved TODO

* Hide Cpu iterator functions
2024-11-14 10:49:16 +00:00
Jesse Braham
64f4fea403
Remove some examples which are adequately covered by documentation (#2538) 2024-11-14 09:32:18 +00:00
Dániel Buga
38dde2ebbd
[DMA 1/N] Add mode to DMA channel drivers (#2519)
* Add mode to DMA channel drivers

* Swap dma Channel CH and DM

* Fix copy-paste mistake
2024-11-14 08:03:05 +00:00
Jesse Braham
959631ee55
Fix nightly lint errors (#2537) 2024-11-14 07:59:55 +00:00
Jesse Braham
014a04faad
Use correct toolchain when building documentation or running doctests via xtask (#2536)
* Add an alias for `fmt-packages` (since I always get this wrong)

* Use correct toolchain when building documentation or running doc tests
2024-11-14 07:38:50 +00:00
Jesse Braham
f3346a80b9
Update documentation to recommend esp-generate instead of esp-template (#2535)
* Update documentation to recommend `esp-generate` instead of `esp-template`

* Hide the `trm_link` macro in the documentation
2024-11-14 07:32:10 +00:00
Jesse Braham
c19c7fcf01
Remove get_core() in favour of Cpu::current() (#2533)
* Remove `esp_hal::core()` in favour of `Cpu::current()`

* Update migration guide

* Update `CHANGELOG.md`
2024-11-13 16:13:47 +00:00
Jesse Braham
92b91257e9
Remove get_ prefix from functions (#2528)
* Remove `get_` prefixes from functions

* Update migration guides for `esp-hal` and `esp-wifi`

* Update `CHANGELOG.md` files
2024-11-13 15:40:26 +00:00
Dániel Buga
b11fc0fce8
Remove NoClkPin (#2531) 2024-11-13 15:07:55 +00:00
Jesse Braham
099e0eacdf
Use newest published PACs (#2530) 2024-11-13 15:06:22 +00:00
Dániel Buga
b538e48ea4
Fix RMT test (#2529) 2024-11-13 13:52:11 +00:00
Björn Quentin
7da4444a7e
Fail RMT one-shot transactions if end-marker is missing (#2463)
* Fail RMT one-shot transactions if end-marker is missing

* CHANGELOG.md

* Add test

* Fix

* Fix

* RMT: use u32, turn PulseCode into a convenience trait

* Clippy

* Adapt test
2024-11-13 11:29:36 +00:00
Dániel Buga
8cbc249e2e
I2c: attempt empty writes (#2506)
* Attempt 0-length writes

* Deduplicate

* Changelog

* Test existing address

* Name addresses

* Fix formatting
2024-11-13 09:57:30 +00:00
Easyoakland
30276e1609
implement wifi event handling with data (#2453)
* implement event handling for apsta{,dis}connect and probe

add to wifi_access_point example

* hide internal `Option` to simplify api

* move handler call logic to event.rs

* update_handler_leak

* - Add comments

- match simpler api from `std::panic::update_hook`

- do not assume size_of in prelude

- make all events handleable

- box static instead of leak

* update changelog

* elide lifetime on default handler

* newtypes for all event types.

* add doc to newtypes

* fix previous doc example

* - `get_handler` -> `handler`
- pass critical section to event handlers
- comment on perf of Box<ZST>
- don't pass `prev` in `update_handler`, instead call previous handler first unconditionally

* pass cs to dispatch_event_handler

* don't print "unhandled event" for handled events.
2024-11-13 08:49:41 +00:00
Dominic Fischer
456bcfb7c6
Remove redundant Enable trait (#2523)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-13 08:26:18 +00:00
Björn Quentin
0b452f7933
C6/H2 Make higher LEDC frequencies work (#2520)
* ESP32-C6/H2: Make higher LEDC frequencies work

* FMT

* CHANGELOG.md
2024-11-13 08:11:01 +00:00
Dániel Buga
5d9cc1a588
Add ESP32-S2 alternate functions (#2512) 2024-11-12 12:18:16 +00:00
Björn Quentin
5d120f7a70
Remove the integrated blocking networking stack (#2488)
* Add simple example using `smoltcp-nal`

* Remove the blocking networking stack

* Renaming

* Fix CI

* CHANGELOG.md

* Fixes after re-base

* Update esp-wifi/MIGRATING-0.10.md

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

* Improve diff in migration guide

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-11-12 11:43:01 +00:00
Dániel Buga
6cb5d9643f
Deduplicate impl, chunk data in ehal transaction Operations (#2481) 2024-11-12 10:49:30 +00:00
Dániel Buga
fbc57542a8
Remove pins from Io (#2508)
* Split pins off of Io

* Remove the GPIO peripheral

* p.GPIO
2024-11-12 10:36:25 +00:00
Jesse Braham
321ca2f131
Add CHANGELOG.md for remaining packages which do not have one (#2518)
* Add `CHANGELOG.md` for remaining packages which do not have it

* Update `changelog` workflow to check all relevant packages
2024-11-12 10:17:11 +00:00
Jesse Braham
cf10f07a9e
Add validation to esp-config (#2475)
* Clean up and re-organize `lib.rs` a bit (sorry)

* Add configuration validation, some other refactoring/improvements

* Add a built-in range validator, re-document the `generate_config` function

* Update build scripts to reflect new configuration API
2024-11-12 10:14:14 +00:00
Jesse Braham
57fc5df858
Modify bump-version subcommand to also bump dependent packages' dependencies (#2514) 2024-11-12 07:08:32 +00:00
Jesse Braham
33659380dd
Update revision of PACs and fix all build errors (#2515) 2024-11-11 21:27:50 +00:00
Dániel Buga
4af44b1498
Introduce Driver and move implementation into it (#2480) 2024-11-11 15:43:07 +00:00
Dániel Buga
2c14e595db
I2C: add apply_config, implement SetConfig, add with_sda and with_scl (#2477)
* Implement apply_config, SetConfig

* Remove pins from constructors

* Implement timeout changes, document them

* Fix up changelog
2024-11-08 22:51:42 +00:00
Dániel Buga
e10ae2ddff
GPIO: do not overwrite interrupt handler (#2486)
* Prefer defmt unwrap

* Auto-bind the GPIO interrupt handler

* Changelog

* Bind interrupt handler when initializing the hal

* Remove user handler overhead unless user handler is bound

* Add tests

* Try to preserve direct-bound handlers

* Fix match

* Don't rely on the vector table to check direct binding

* Fix comment
2024-11-08 17:04:06 +00:00
Sergio Gasquez Arcos
7402ad61ed
Expose CSI API in esp-wifi (#2422)
* feat: (WIP) add CSI api

* feat: Enable G_CONFIG.csi_enable and update example

* fix: Allow user to set the dessired cb method

* fix: Clippy warnings

* fix: Add missing doccomments

* feat: Add csi_enable config

* refactor: Update CsiConfiguration c6 struct

* feat: Create set_csi WifiController and EspNowManager methods

* docs: Update changelog

* refactor: Rename CsiConfig struct

* docs: Document c6 version of CsiConfig

* feat: impl From<CsiConfig> for crate::include::wifi_csi_config_t

* style: Rustfmt

* docs: Fix comment

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* docs: Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* feat: Enable CSI on examples by default

* feat: Handle errors

* style: Rustfmt

* feat: Update error

* feat: Panic if csi config is not enabled

* feat: Cfg CSI stuff when CSI is disabled instead of panicing

* fix: Clippy lints

* feat: Fix signed bitfields

* feat: Pass the cb via ctx

* feat: Update CSI callback to use closures

* refactor: Rename promiscuous_csi_rx_cb to csi_rx_cb

* feat: Move extra boxing inside set_receive_cb

* feat: Refactor CSI callback to use generic types

* refactor: Remove Sized bound from CsiCallback trait

* feat: Add csi_enable field to EspWifiConfig and update CsiCallback trait for conditional compilation

* feat: Remove unnecessary boxes

* feat: Update callback type in set_csi to require Send trait

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-11-08 16:33:13 +00:00
Björn Quentin
3c4b7f0f66
Test more embassy interrupt spi dma (#2490)
* Add C3,C6 and H2 for `embassy_interrupt_spi_dma`

* Test more

* Don't require physically connected pins
2024-11-08 13:43:34 +00:00
Scott Mabin
50d8187e39
esp-wifi: Remove unneeded features (#2446)
* remove async features

* phy-usb config

* modem powersaving

* Fix examples

* make ps a runtime config

* fix linting

* changelog and migration guide

* revert esp-config changes

* remove blanklines after doc comments

* cfg away ps API
2024-11-08 13:30:33 +00:00
Dániel Buga
6d6f6a7baa
Move I2C driver to i2c::master (#2476)
* Move I2C driver to i2c::master

* Update esp-hal/CHANGELOG.md

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-11-08 12:28:53 +00:00
Dániel Buga
31d714a156
Tweak guidelines (#2482)
* Tweak guidelines

* Restore builder rule

* Address review comments
2024-11-08 11:50:52 +00:00
Dániel Buga
ac4679a1ae
Remove public hidden I2C APIs (#2474) 2024-11-08 10:37:13 +00:00
Dominic Fischer
d6f63d67a9
Fix I8080.set_byte_order() (#2487)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-11-08 08:01:36 +00:00
Dániel Buga
d5e6ba5ceb
SPI slave with_pin functions (#2485) 2024-11-08 07:29:37 +00:00
Dániel Buga
4233bddf23
Fix test warnings (#2483) 2024-11-07 15:05:49 +00:00
yanshay
639853ede9
Add MultiwriteNorFlash trait to FlashStorage (#2478)
* Add MultiwriteNorFlash trait to FlashStorage

* add PR number

* Revert "add PR number"

This reverts commit 28bf0acd24.

* Added changelog with PR number
2024-11-07 13:58:32 +00:00
Dániel Buga
ac819fb42f
Remove PeripheralMarker (#2468)
* Redo DMA compatibility check using DmaEligible

* Remove PeripheralMarker
2024-11-07 13:51:48 +00:00
Dániel Buga
8782429e9f
SPI slave: remove public hidden API (#2470)
* Redo declaration as macro

* Add Info

* Move impl out of Instance traits

* Publish traits
2024-11-07 09:41:16 +00:00
Dániel Buga
0da6eec089
Move I2S drivers to i2s::master and i2s::parallel (#2472)
* Move I2S drivers to i2s::master and i2s::parallel

* Remove mention of master mode
2024-11-07 09:39:08 +00:00
Dániel Buga
feac6f17c3
Mark State/Info as #[non_exhaustive] (#2471) 2024-11-07 09:37:56 +00:00
Dániel Buga
255f5e7c73
TWAI: Always configure a default filter (#2467) 2024-11-06 14:11:49 +00:00
Dániel Buga
4c5be2c907
Interconnect: force signals through GPIO matrix if split (#2419)
* Allow splitting off of gpio drivers

* Extract and correct low level connection bits

* Add Input/OutputSignal::connect_to

* Remove unnecessary public API

* Fix typos

* Remove unused private methods

* Add separate Direct signals that do bypass the GPIO matrix

* Do not disable stage input

* Clean up spi_slave test

* Constrain to static Flex

* Improve docs

* Separate input_enable and open_drain parameters

* Link to the chapter

* Changelog

* Clarify
2024-11-06 13:55:34 +00:00
Björn Quentin
ccb3a1ba40
Use diagnostic on DmaChannelConvert (#2465)
* Use `diagnostic` on `DmaChannelConvert`

* Typo
2024-11-06 11:43:25 +00:00
Dániel Buga
8860aba9b2
Spi master: remove public hidden APIs, add Config/apply_config (#2448)
* Remove hidden public SPI API

* Fix in_progress flags not being set

* Remove redundant checks, fix full-duplex flag

* Remove now-redundant Send impl

* apply_config

* SetConfig

* Return ConfigError

* Unwrap config result in ctor
2024-11-06 09:03:43 +00:00
Dániel Buga
eabb6fb1c6
ETM improvements (#2427)
* ETM simplifications

* Work with GPIO signals

* Fix changelog
2024-11-05 13:39:19 +00:00
Dániel Buga
665fb0e278
Flatten Uart module, remove unnecessary data, replace methods with apply_config (#2449)
* Flatten uart config

* Do not remember at_command config

* Don't save config values in memory

* Move config implementations to Info

* Changelog

* Remove unused methods

* apply_config, SetConfig

* Fix test

* simplify futures

* Update esp-hal/CHANGELOG.md

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>

---------

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
2024-11-05 09:56:14 +00:00
Dániel Buga
ed7960ce8b
Also add into_async for ParlIO (#2461) 2024-11-04 16:00:21 +00:00
Björn Quentin
ca9ee23b5e
Prefer ROM-fns over custom impl (#2462)
* Prefer ROM-fns over custom impl

* PR number
2024-11-04 15:55:23 +00:00
Dániel Buga
1e6820d1a7
Systimer improvements (#2451)
* Do not read to set update bit

* Deduplicate

* Try to bind interrupts to the correct core

* Inline poll_count into read_count

* Clean up

* Make sure only a single update is done at a time

* Changelog

* Fix docs

* Correct the channel count

* Assign enough timers for HIL test

* Use a lock to prevent re-update

* Remove locking, use esp-idf implementation

* Document timer count requirement
2024-11-04 11:36:34 +00:00
Dániel Buga
0c86740418
Peripheral interconnect redo, vol 2 (split()) (#2418)
* Replace peripheral connection conversions with split

* Constrain Flex conversions
2024-11-04 11:29:28 +00:00
Dániel Buga
177db100fb
Remove redundant lifetimes (#2459) 2024-11-04 10:51:12 +00:00
Dániel Buga
40c0a6944e
into_async (#2430)
* Remove configure_for_async

* Add into_async and into_blocking to I2c

* Add into_async and into_blocking to UsbSerialJtag

* Rework LCD_CAM

* Rmt

* RSA

* TWAI

* Uart

* Documentation

* Disable interrupts set on other core

* Move configure into RegisterAccess

* Disable interrupts on the other core

* Use EnumSet in RMT
2024-11-04 09:32:12 +00:00
Scott Mabin
c717f04d4d
Remove EspWifiInitFor & more granular init/deinit per driver (#2301)
* More granular init and deinit per driver

- Rework EspWifiInit
- No longer require EspWifiInitFor
- Add Drop impls for each driver, and add Drop for EspWifiController to
  fully deinit the stack

* unwrap! more stuff

* fixup examples and esp-now

* unwrap less stuff

* review feedback

* seal wifi traits, allow rng or trng to init esp-wifi

* changelog and migration guide

* return wifi error in esp now constructor instead of panic
2024-11-04 08:08:19 +00:00
Dominic Fischer
f9ba299f2e
Mark DmaDescriptors as Send (#2456)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-04 07:50:44 +00:00
Dominic Fischer
05f2ee5a72
Allow users to create DMA Preparations (#2455)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-04 07:38:46 +00:00
Dominic Fischer
b953f178b8
Add check owner support to DMA buffers (#2337)
* Add check owner support to DMA buffers

* More docs

* Explicit check owner bit setting

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-11-02 16:07:40 +00:00
Dániel Buga
111ae93cc5
Fix, clean up and type-erase parallel i2s (#2436)
* Fix, clean up and type-erase parallel i2s

* Fix capitalization

* Add link to esp-idf code that offsets by 8
2024-11-01 10:50:39 +00:00
Jesse Braham
fc4eaa1ebf
Make our nightly CI checks pass (#2356)
* Fix nightly lint errors for ESP32-C2

* Fix nightly lint errors for ESP32-C3

* Fix nightly lint errors for ESP32-C6

* Fix remaining nightly lint errors
2024-11-01 10:31:56 +00:00
Dániel Buga
a5c4aa1cea
Tweak interrupt API (#2442)
* Tweak interrupt API

* Constrain SPI interrupt handling to Blocking mode
2024-10-31 16:18:44 +00:00
Dániel Buga
7d717c6acf
Fix UART erratum on ESP32 (#2441) 2024-10-31 15:00:36 +00:00
Dániel Buga
f9c7d06a6e
Disable i2s test (#2439) 2024-10-31 14:16:39 +00:00
Björn Quentin
e5b923b678
Esp wifi/more dynamic allocations (#2396)
* Dynamic allocation of timers

* Replace statically allocated NPL events

* Remove NPL CALLOUTS

* Remove NPL EventQueue

* Use `Vec` instead of `heapless::spsc::Queue` internally in NPL

* Use `alloc` since we have it in NPL

* Refactor

* Fix

* More `Vec`

* Fix

* Fix nightly-warnings

* Limit RX_STA queue

* Revert unintentional change

* esp-now: Make data private

* CHANGELOG.md

* Clippy

* MSRV

* Move locking into RawQueue

* Remove unused import

* Simplify `queue_recv`

* Address TODO

* Clippy

* Review I

* Review II

* Clarify

* Review III

* Review IV

* Review V

* Fix

* `steal` RNG and RADIO_CLOCKS

* `drop_in_place`

* De-duplicate

* Use `VecDeque`

* Revert unintentional changes

* Fix

* Update esp-wifi/MIGRATING-0.10.md

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* assert

* Fix

* Expect `*mut ConcurrentQueue` where applicable

* Comment why stealing is fine

* Fix

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-10-31 12:26:10 +00:00
Jesse Braham
6fa2823e10
Use latest PAC which aligns TWAI field names (#2438) 2024-10-31 12:22:37 +00:00
Dominic Fischer
25d8390d68
Fix typo in migration guide (#2435) 2024-10-31 06:43:11 +00:00
liebman
448ed9a001
implement a parallel interface for esp32 using the i2s peripheral (#2348)
* i2s_parallel for esp32 - partially working

* i2s_parallel for esp32 - works sync 16bit (still WIP)

* i2s_parallel - add 8-bit

* i2s_parallel - naive async implementation

* i2s_parallel - clippy

* add examples (mainly for testing now and we can reduce these before merge)

* set tx_wrx2 in 8 bit mode or it updates on half clocks!

* adjust clock config (still really a hack)

* better clock calculation/configuration

* no need to reset dma or interrupts in start, the DMA DmaTxBuf handles that

* seems to need a short delay during tx_reset

* use 20 clocks instead of 1us

* 1us delay between dma start and tx_start (like idf)

* changelog & documentation

* remove debugging functions

* no need for option in example

* make async example actually use async & remove Option

* implement Drop for I2sParallelTransfer

* fix signal offset comment for I2S0

* small cleanup in i2s_parallel examples

* added a note re I2S0 not supporting true 8bit

* update doc & fmt

* instace functions take &self

* fmt

* if run at 240MHz (CPU) delay needs to be bigger

* wait for fifo on start and fixes for 240MHz

* update for esp-hal-changes

* fmt

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-10-30 18:55:47 +00:00
Tu Nguyen
9d4b8fdbc6
[TWAI] bus-off error is never reached when using transmit_async (#2421)
* cancel pending tx request when error is from tx

* fix format error

* update CHANGELOG.md
2024-10-30 16:59:11 +00:00
Björn Quentin
05a1ebead3
Use esp-wifi-sys from Git (#2426)
* Use esp-wifi-sys from Git

* Update esp-wifi-sys rev
2024-10-30 16:38:16 +00:00
Björn Quentin
416c1481ae
Circular dma improvements (#2409)
* Check for error when pushing into a circular dma transaction too late

* Adapt tests

* Adapt example

* Don't block forever if trxing to pop from a circular DMA transfer too late

* Have a dedicated error for circular-DMA reading/writing too late

* Stop I2S RX before resetting it

* Migration guide

* Address review comment, make CI pass

* Adopt ideas from review

* Fix

* Update esp-hal/MIGRATING-0.21.md

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

* assert

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-10-30 16:25:29 +00:00
Dániel Buga
4546f861c8
Reduce UART Instance trait to the bare minimum (#2410)
* Merge signal fns

* Remove logic from UART Instance, remove uart_number

* Use the unwrap macro

* Place peripheral info into static structs

* Clean up

* Clean up

* Update todo

* Rename

* Separate out state
2024-10-30 15:51:33 +00:00
Dániel Buga
a8fedf0130
Move some implementation details out of GPIO (#2429)
* Move macros out of gpio

* Align S2 impl
2024-10-30 15:11:48 +00:00
Kirill Mikhailov
3e42b76993
Add an option to configure WDT action (#2330)
* WIP

* revert example

revert config

* changelog entry

* Make `RWDT` API work correctly, make `RWDT` and `MWDT`APIs same

* update documentation code

oops

* rev

* Polishing

* Document bootloader limitation

+ typo fix

* Address reviews

* fix documentation examples
2024-10-30 09:46:34 +00:00
Dániel Buga
f07e25c970
Add option to disable waiti (#2329) 2024-10-30 08:12:15 +00:00
Björn Quentin
b7224ef4c9
RISC-V: Fix interrupt stack alignment (#2425) 2024-10-29 11:45:30 +00:00
Dániel Buga
8a23dbe1b6
Modernize UART interrupts (#2406)
* Modernize UART interrupts

* Also derive Debug and Format for interrupt enums

* Fix changelog

* Touch up API-GUIDELINES
2024-10-28 09:07:15 +00:00
Dániel Buga
4e257f74aa
Merge/remove some GPIO-related macros (#2404)
* Remove redundant macros

* Deduplicate rtcio dispatch macros

* Clean up unnecessary import

* Remove manual bank assignment
2024-10-28 07:08:53 +00:00
Dániel Buga
f3c5286028
Add Cpu::COUNT and clean up in esp-hal-embassy (#2411)
* Add Cpu::COUNT and simplify

* Avoid a bounds check during pending
2024-10-26 13:36:10 +00:00
Dániel Buga
6bf03f63a9
Small SPI slave cleanup (#2405) 2024-10-25 15:07:43 +02:00
Dániel Buga
681f4ef0aa
Implement UART type erasure (#2381)
* Simplify test

* Remove unnecessary refs

* Improve readability

* Require Instance: PeripheralMarker

* Take &self

* Avoid unsafe code on non-s2

* SImplify drain_fifo

* Simplify read_bytes

* Avoid a register read on ESP32

* Deduplicate is_idle functions

* Add missing inlines

* Move code out of trait

* Erase UART instances

* Disable LTO
2024-10-25 08:03:20 +00:00
Dániel Buga
561b582a80
Overhaul peripheral signal system, first run (#2388)
* Remove redundant bound

* Remove redundant Dummy variant

* Make PeripheralOutput extend PeripehralInput

* Rename AnyInputSignal to InputConnection

* Add OutputConnection

* Convert into type-erased interconnect conections

* Clean up LCD/CAM

* Document changes

* Review changes

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

* Clean up

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-10-25 07:01:45 +00:00
Dániel Buga
19b08efc1d
Rework how pin capabilities are declared (#2400) 2024-10-24 11:55:46 +00:00
Björn Quentin
a7d8b2009d
Use panic instead of process::exit (#2402) 2024-10-24 11:06:05 +00:00
Dániel Buga
2ac47868f7
Remove FullDuplexMode and HalfDuplexMode type params (#2373)
* Remove duplex type param

* Rename dma_ functions
2024-10-24 07:22:21 +00:00
Dániel Buga
f03527f6fc
Change example to set max clocks (#2399)
* Change example to set max clocks

* Update esp-hal/src/lib.rs

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-10-24 07:18:29 +00:00
Dániel Buga
c163b0586a
Erase TWAI (#2359)
* Swap order of generics

* Don't refer to Instance in irq handler

* Deduplicate a bit

* Take &self

* Reduce nesting

* Erase TWAI instance
2024-10-24 06:47:02 +00:00
Easyoakland
1de2483609
fix wifi async fn disconnect hanging if not connected when called (#2392)
* fix wifi async fn disconnect hanging if not connected when called

* update changelog

* clarify comment

* add pr number to changelog
2024-10-23 21:29:00 +00:00
Dániel Buga
5f6ca8d252
Fix embassy migration guide (#2393) 2024-10-23 13:49:20 +00:00
Dániel Buga
4c1c6131df
Wait more before re-enabling USB power (#2397) 2024-10-23 12:56:59 +00:00
Dániel Buga
71c4fc5a24
Add note to start_app_core (#2395) 2024-10-23 08:54:53 +00:00
Dániel Buga
5486cdb5e3
Clean up i2c add_cmd (#2394) 2024-10-23 08:44:30 +00:00
Dániel Buga
e367c83bde
Erase i2c peripheral instances (#2361)
* Clean up

* Erase I2C instance type

* Clean up

* Implement Peripheral

* Changelog

* Remove with_timeout constructors
2024-10-23 06:31:08 +00:00
Dániel Buga
1afc9eef89
Remove unnecessary generic from ChannelHW (#2387)
* Remove unnecessary generic from ChannelHW

* Changelog
2024-10-22 15:41:42 +00:00
Björn Quentin
54d4407042
Better align atoi to what the C-library does (#2380)
* Better align `atoi` to what the C-library does

* Address review comments

* Clippy

* More clippy

* Prefer `read` over `read_volatile`
2024-10-22 14:55:24 +00:00
Dániel Buga
632bbc6461
Fix interrupt executors waking up thread-mode executors on the first core (#2377)
* Clean up

* Add failing multi-core test

* Reset interrupts before main

* Changelog

* Add test case
2024-10-22 14:45:06 +00:00
Dániel Buga
aec83bdd31
GPIO cleanup (#2384)
* Return alternate function maps as slices

* Prefer steal() over ptr deref

* Clean up rtc_io
2024-10-22 12:56:45 +00:00
Jesse Braham
56cd5a288f
Update PACs to latest git revision (#2383)
* Update to latest git revision of all PACs

* Update RSA module to reflect changes in PACs

* Update TWAI module to reflect changes in PACs

* Further simplification
2024-10-22 12:33:36 +00:00
Björn Quentin
c574834ae3
Include ROM API symbols (#2374)
* Include ROM API symbols

* Fixes and CHANGELOG.md

* Fix

* Move migration steps to the right crate's migration guide

* Remove `-Trom_functions.x` where necessary
2024-10-22 10:02:49 +00:00
dimpolo
62ee60d43f
Fix conflict between RtcClock::get_xtal_freq and Rtc::disable_rom_message_printing (#2360)
* deduplicate some code in rtc_cntl

* mask out the RTC_DISABLE_ROM_LOG bit when reading RTC_XTAL_FREQ
2024-10-22 08:35:46 +00:00
Dániel Buga
a4bc0536a3
PAC update (#2378)
* PAC update

* Inline steals into reg expressions
2024-10-22 06:41:33 +00:00
Dániel Buga
d914a0301f
Erase i2s (#2367)
* Implement I2S type erasure

* Clean up
2024-10-22 06:33:27 +00:00
Dániel Buga
a754e411b1
SPI type erasure (#2334)
* Move SPI peripheral type to the last position

* Implement AnySpi

* Convert peripheral types

* Add new_typed constructors

* Implement PDMA

* Fix conditional

* Clean up constructors

* Fix test

* Move stuff to utils

* Extract any macros

* Merge PeripheralMarker defs into peripherals macro

* Changelogs

* Implement fn degrade

* Changelog num

* Fix typo

* Rename type-erased dma channel

* Remove degrade fn

* Remove utils

* Explain peripherals macro
2024-10-21 14:03:14 +00:00
Dániel Buga
f2aa3f9863
Update embedded-test (#2375) 2024-10-21 09:35:15 +00:00
Dániel Buga
d32a7336bb
Simplify traits and erratum 36 workaround, add Pins::steal (#2335)
* Simplify erratum 36

* Add Pins::steal

* Fix typo

* Move pin operations into Flex

* Cleanup braces

* Avoid panicking when handling erratum

* Add disable_usb_pad to other devices

* Touch up changelog

* Fix changelog
2024-10-18 14:17:43 +00:00
akesser
326e006335
doc: add hint for feature flag in wifi examples (#2365) 2024-10-18 14:14:21 +00:00
Dániel Buga
f0d0dd92c4
Do not optimise ecc test (#2366) 2024-10-18 14:05:02 +00:00
Björn Quentin
358d884643
Add option to place more .rodata in RAM for performance (#2331)
* Add option to place more `.rodata` in RAM for performance

* Make CI green, again

* Removed unnecessaries

* Split option into two

* Make `place-switch-tables-in-ram` default

* Xtensa

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-10-18 11:47:12 +00:00
Georges
9d51d1befe
fix doc (#2363) 2024-10-18 10:22:39 +00:00
Kirill Mikhailov
88c4dba9e0
esp-wifi docs improve (#2354)
* Improve esp-wifi docs (WIP)

* Finalize

* Address reviews, make cratewide public functions be `pub(crate)`.

* config -> configure
2024-10-18 08:23:16 +00:00
Dániel Buga
472d5f93e0
Add PeripheralRef::map_into (#2326)
* Add PeripheralRef::map_into

* Update clone_unchecked to take shared self

* Simplify pin erasure
2024-10-16 13:34:11 +00:00
Dominic Fischer
6e2606b367
Add burst transfer support to DMA buffers (#2336)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-16 13:25:48 +00:00
Dániel Buga
99a579973a
Preparatory i2s refactor (#2316)
* Take self

* Consolidate signal impls

* Remove traits

* Deduplicate impls

* Seal AcceptedWord

* Changelog

* Migration guide

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-10-16 13:04:00 +00:00
Jesse Braham
39c0baf2c7
New patch release for esp-hal (#2355) 2024-10-16 08:39:49 +00:00
Anthony Grondin
060aa7262c
feat(esp-wifi): Implement serde:{Deserialize, Serialize} for wifi structs (#2346)
* feat(esp-wifi): Implement `serde:{Deserialize, Serialize}` for wifi structs

* Update changelog

* Add missing serde feature for dependencies that supports it.
2024-10-16 07:10:43 +00:00
Dániel Buga
67bc37fb93
Add --fix to lint-packages (#2351)
* Add --fix to lint-packages

* Fix suggestion that breaks clippy
2024-10-15 09:33:15 +00:00
Dániel Buga
f0a361e448
Point to usage examples (#2349) 2024-10-15 09:24:46 +00:00
Dominic Fischer
da9c0b0579
Move mem2mem out of GDMA module (#2323)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-15 09:20:36 +00:00
Alexandra Clifford
a15cfe7f21
Make RX queue size configurable (#2324) 2024-10-15 07:38:09 +00:00
Dániel Buga
ef7842fab4
Reimplement blocking trait for async i2c (#2343) 2024-10-14 12:50:37 +00:00
Kirill Mikhailov
0dc8dcf8e2
XTASK: add a way to activate features per chip (docs) (#2287)
* XTASK: add a way to activate features per chip (docs)

* Address reviews
2024-10-14 09:04:38 +00:00
Dániel Buga
7aa8145213
Silence clippy (#2332) 2024-10-11 17:38:42 +00:00
Scott Mabin
e22103d867
fix esp-wifi docs (#2333) 2024-10-10 14:37:56 +00:00
Jesse Braham
d08dc3dcb7
Add new living migration guides (#2327) 2024-10-10 12:44:28 +00:00
Scott Mabin
f29d539a78
Prepare new radio related releases (#2328) 2024-10-10 12:20:52 +00:00
Jesse Braham
5af3d9ddf2
Add missing description field to Cargo manifest for esp-config (#2325) 2024-10-10 10:53:20 +00:00
Jesse Braham
d655fe665f
New package releases (#2310)
* Bump version numbers of all packages to be published, update deps as needed

* Update all `CHANGELOG.md` files

* Update migration guide headings
2024-10-10 10:19:04 +00:00
Dániel Buga
ba8daafb0b
Require float-save-restore in esp-wifi (#2322)
* Add failing test case

* Make sure task contexts are properly initialised

* Require float-save-restore for esp-wifi
2024-10-10 08:24:50 +00:00
Scott Mabin
0142703112
I2c rename, small docs clean up (#2320)
* cleanup prelude docs

* fixups and i2c rename

* changelog and migration

* fixup docs and examples

* fix lint
2024-10-10 07:26:13 +00:00
Dániel Buga
c26600f943
Fix first UART print (#2318)
* Fix first UART print

* Add test case

* Explicitly set level to cause problems
2024-10-09 15:16:56 +00:00
Dániel Buga
f93efa73a9
Clean up warnings (#2317) 2024-10-09 14:53:32 +00:00
Dániel Buga
be9dc0e0b7
Fix restoring of CPENABLE (#2315)
* Add tests Cp0Disabled issue

* Fix saving CPENABLE on context switch

* Fix position shift of registers

* Clean up
2024-10-09 10:33:31 +00:00
Dániel Buga
dc88cb13e8
Reimplement SPI DMA operations in terms of transfer (#2308)
* Reimplement SPI DMA operations in terms of transfer

* Deduplicate reset_dma

* Create empty constructors

* Introduce EmptyBuf

* Fix comment

* Undo unnecessary change

* Remove unnecessary slicing
2024-10-08 23:15:21 +00:00
Dániel Buga
b27482df3c
Mention silent esp-hal-embassy breaking change (#2307) 2024-10-08 15:17:38 +00:00
Dániel Buga
7ca1b4376f
Erase DMA type params (#2261)
* Split PdmaChannel into two

* Take &self in PDMA traits

* Implement type-erased PDMA channels

* Remove Degraded assoc type

* Move degrade fns to base trait

* Use PeripheralDmaChannel on constructors only

* Remove WithDmaAes use

* Erase DMA type params

* Clean up examples/tests

* Remove redundant trait bounds

* Remove peripheral-specific DMA traits

* Document i2s change

* Clean up parl_io

* Deduplicate InterruptAccess

* Fix cfg

* Implement runtime compatibility check

* Clean up a bit

* Document changes

* Swap Channel type params, erase dma channel

* Unsplit traits

* Remove redundant cfg

* Fix docs

* Simplify DmaEligible

* Remove unsafe code

* Revert "Swap Channel type params, erase dma channel"

This reverts commit 415e45e44b297fd3cb55b4261c9ce151cca4b9c9.

* Allow different degraded DMA types

* Allow converting into peripheral-specific DMA channel, use it for compat check

* Erase PDMA types without AnyPdmaChannel

* Hide degrade fns for now, remove from MG

* Clean up SPI slave

* Fix QSPI test

* Fix mem2mem, fix S3 peripherals

* Fix S2

* Remove AnyPdmaChannel

* Remove PeripheralDmaChannel

* Remove unnecessary degrade call
2024-10-08 14:09:27 +00:00
Dániel Buga
f26eef646a
Remove current_millis (#2304) 2024-10-08 14:04:59 +00:00
Björn Quentin
81f93698b0
Remove unused dependencies (#2306) 2024-10-08 13:49:49 +00:00
Dániel Buga
3a9abca148
Slight TWAI corrections (#2288)
* Fix ESP32 baud rate prescaler bit

* Explicitly disable CLKOUT

* Fix brp

* Loop example

* Clean up

* Impl traits for BaudRate

* Fix H2 125k

* Avoid self-receiving transmitted frames

* Fix self-reception flag

* De-CAN

* CI, more defmt impls

* Explain raw bit manipulation

* Fix spelling
2024-10-08 13:32:22 +00:00
Scott Mabin
08030d5541
bump all semver compatible deps (#2303) 2024-10-08 12:56:30 +00:00
Björn Quentin
ca5e8560bf
Replace ESP_LOGLEVEL and ESP_LOGFILTERby ESP_LOG (#2291)
* Replace `ESP_LOGLEVEL` and `ESP_LOGFILTER`by `ESP_LOG`

* CHANGELOG.md

* Clippy

* Fail build if using the now unsupported env variables
2024-10-08 08:53:42 +00:00
Björn Quentin
038d07f5b6
Use relevant features when building documentation (#2295)
* Use relevant features when building documentation

* CHANGELOG.md and migration guide

* Fix imports
2024-10-08 07:31:56 +00:00
Dániel Buga
16f277915b
Remove redundant feature (#2297) 2024-10-08 07:31:47 +00:00
dimpolo
754d8aa585
Fix typo (#2292)
Sorry 😅
2024-10-07 16:19:24 +00:00
Dániel Buga
af3f892381
ESP32 spi slave mode (#2278)
* Enable test on ESP32

* Enable module on ESP32

* Add ESP32 signal map

* Change pins

* Remove unknown signals

* Return to low level in test

* Fix bitlength

* Merge enable and reset

* Impl debug traits on DMA flags

* Disallow mods 0 and 2

* Docs tweaks

* Changelog

* Undo wait change
2024-10-07 15:00:15 +00:00
Dániel Buga
ba96bac776
Clean up impl_dma_eligible (#2290) 2024-10-07 14:39:26 +00:00
dimpolo
f4540a5508
add Rtc::disable_rom_message_printing (#2280) 2024-10-07 14:07:04 +00:00
Dominic Fischer
897a67808c
Add DMA buffer view support to I8080 driver (#2268)
* Add DMA buffer view support to I8080 driver

* reconstruct buffer before dropping

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-07 11:53:53 +00:00
Dániel Buga
3e16c5c623
Avoid moving inside SpiDmaBus, abort dropped transfers (#2216)
* Drop State from DMA

* Simplify Error paths

* Cancel dropped transfers, fix and test

* Fix C6

* Avoid cancelling a completed transaction

* Do not implement DmaTxRxBuf for references

* Remove unnecessary import

* Merge BufferRef structs

* Move wait impl to the peripheral

* Allow the current byte to complete

* Restore SpiDmaTransfer::is_done

* Explain cancel code

* Fix test formatting

* Changelog

* Simplify implementation

* Make sure everything gets dropped

* Remove unnecessary PhantomData

* Remove OptionalFuture

* Adjust test to a more realistic clock frequency
2024-10-07 10:04:50 +00:00
Björn Quentin
e5bc63916f
Change debug! to trace! to reduce logging noise (#2284) 2024-10-07 09:29:41 +00:00
Dániel Buga
efe58e94a2
I2C: clean up and remove stop condition from the middle of write_read (#2276)
* Remove I2COperation

* Clean up peripheral reset/enable

* Remove match on peripheral number

* Remove seemingly duplicate register write

* Clippy

* Restore compatibility with slices, publish async transaction

* Maybe with a stop between?

* Add missing inlines

* Read from the correct address

* write_read: don't generate stop after write
2024-10-07 07:29:23 +00:00
Dominic Fischer
62e991d749
Add GPIO Matrix support to Camera driver (#2279)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-07 06:20:06 +00:00
Dániel Buga
d3f03042f3
Clean up a bit (#2275) 2024-10-04 12:18:11 +00:00
Kirill Mikhailov
a4fe5e6e63
Adding a way to deinitialize the WiFi stack. (#2187)
* WIP

* cleanup

* WIP (BLE)

* WIP (BLE)

* c2 ble deinit doesn't work with ble alone, works in coex (WIP)

* fmt

* cleanup

* changelog entry

changelog entry

* WIP (do not check it)

 it's just to save things before weekend!

* polishing, refactor

* cleanup

* lint

* Addressing reviews

* address reviews

* utilize `EspWifiInitialization` in deinit

* example -> description

* reviews

* reviews

* fix memory leak + rebase

* typo

* fix

* init -> initialize

screwed up after rebase

* make esp32c6/h2 buildable again

* edit safety comment
2024-10-04 12:16:52 +00:00
Björn Quentin
00ad9b5eed
I2c: Inherent transaction function, lift size limits (#2262)
* I2c: Inherent transaction function, lift size limits

* CHANGELOG.md

* Simplify

* Fix

* Remove unnecessary lifetime

* Remove unused lifetime
2024-10-04 11:53:35 +00:00
Björn Quentin
18da679d8a
esp-wifi: Align default settings (#2251)
* Align esp-wifi defaults with ESP-IDF

* Check we assume the correct wifi-config defaults

* No WIFI-CONFIG for ESP32-H2
2024-10-04 09:34:42 +00:00
Dániel Buga
5a993fed38
Fix Rx/Tx order in SPI slave driver (#2272)
* Add basic test and fix SPI slave dma_transfer arg order

* Reset peripheral

* Add safe way to read signal value
2024-10-04 06:56:34 +00:00
Dániel Buga
c7a2368845
Print test panics using semihosting (#2257)
* Print panic messages using semihosting

* Don't use defmt's asserts

* Make RA_OFFSET available without panic-handler

* Re-add defmt imports where missing

* Revert unintended test change

* Initialise hal in critical-section test

* Disable defmt in tests by default
2024-10-04 06:31:39 +00:00
Dominic Fischer
3e9a506c00
Move DMA buffers to a different file (#2267)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-03 11:12:20 +00:00
Dániel Buga
e033162ffd
Clean up (#2266) 2024-10-03 07:02:34 +00:00
Dominic Fischer
30aef580e3
Migrate Camera to a move based API (#2242)
* Migrate Camera to a move based API

* update

* update

* ManuallyDrop

* Add default channel to transfer struct

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-02 13:23:14 +00:00
Dominic Fischer
8789ca3c3d
Migrate I8080 driver to a move based API (#2191)
* Migrate I8080 driver to a move based API

* fmt

* comments

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-02 13:23:10 +00:00
Björn Quentin
a3304c6cff
Fix eh0.2 set_high/set_low (#2265) 2024-10-02 12:45:11 +00:00
Dániel Buga
f5b8e4b914
Remove SPI slave prelude (#2260)
* Remove SPI slave prelude

* Changelog

* Update esp-hal/src/spi/slave.rs
2024-10-02 06:23:54 +00:00
Dominic Fischer
8e9f6b5015
Erase DMA channel type from Camera and AesDma drivers (#2258)
* Provide AnyDmaChannel

* Erase channel in Camera and Aes

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-10-01 08:11:49 +00:00
Dániel Buga
ed51cd8c35
Only read value types from efuses (#2259)
* Only read value types from efuses

* Changelog

* Clean up remaining bool reads
2024-10-01 08:09:28 +00:00
Dominic Fischer
f1bedbe3dc
Split DMA RegisterAccess trait into RX/TX (#2249)
* Reduce macro usage in PDMA

* Split DMA RegisterAccess trait into RX/TX

* Move set_isr to Ext trait

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-30 13:32:18 +00:00
Dániel Buga
487de0ff22
Round up in delay_nanos (#2256) 2024-09-30 13:23:31 +00:00
Dániel Buga
fcc6375ba5
TWAI: Return error instead of crashing (#2255)
* TWAI: Return error instead of crashing

* Deduplicate interrupt handler
2024-09-30 12:51:27 +00:00
Björn Quentin
b8a4d5f9ff
Remove unused functions (#2254) 2024-09-30 12:07:41 +00:00
Juraj Sadel
11c73caf89
esp-wifi: Remove log feature from default features (#2253)
* esp-wifi: Remove log feature from default features

* changelog
2024-09-30 11:10:58 +00:00
Björn Quentin
fa66a43949
Update drivers (#2239)
* Update drivers

* Fixes

* Changelogs

* Actually remove timers when we should

* Have one waker for all events

* Prefer `swap_remove` over `remove`

* Really implement new coex fucntions for C3/S3

* Real implementation for `coex_schm_flexible_period_set` and `coex_schm_flexible_period_get`

* Mute warnings
2024-09-30 08:40:44 +00:00
Dániel Buga
0981c1b619
SPI peripheral signal cleanup (#2245)
* Compact peripheral description a bit

* Enable QSPI on ESP32 SPI3

* Remove SPI4 from ESP32S2

* Changelog

* Remove inaccurate comment
2024-09-27 17:03:18 +00:00
Dániel Buga
4422ed3ccf
DMA: Deduplicate descriptor operations (#2219)
* Deduplicate descriptor operations

* Reuse constructor

* Reuse linked list construction logic

* Extract count calculations into DescriptorSet

* Reuse more code in DescriptorChain

* Refactor DescriptorChain

* Move DescriptorSet next to DescriptorChain

* Restore comment

* Merge fns

* Implement error conversion

* Further cleanup

* Rearrange some code

* Add some docs

* Clippy

* Restore macro behaviour when requesting 0 descriptors

* Restore the buffer directly, instead of tracking where we read from

* Move validation back into the buffers

* Revert use in dma_tx_buffer

* Rename iterator methods

* Outline eof logic

* Don't set up descriptor flags before time, rename methods

* Hide DescriptorSet

* Remove block size from DescriptorSet

* Move comment

* Fix renamed references

* Address review comments

* Simplify received_data fns
2024-09-27 09:33:26 +00:00
Dániel Buga
f50c6fc071
Only lock once in is_slice_in_psram, use usize (#2241) 2024-09-27 08:06:46 +00:00
Dominic Fischer
66f6737697
Mark DMA buffer traits as unsafe to implement (#2213)
* Mark DMA buffer traits as unsafe to implement

* update doc

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-27 08:02:35 +00:00
Dominic Fischer
00d892b214
Add stop_transfer method to DMA driver (#2236)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-26 16:22:57 +00:00
Dániel Buga
c481c49888
Fix incorrect QSPI setup (#2231)
* Fix QSPI mode on non-ESP32

* Update tests to count pulses on pins separately

* Fix ESP32 addressing phase issue

* Use defmt's assert

* Set fastrd bit

* Apply pulldowns to define signal level when not driven

* Transfer address bits in data phase on ESP32

* Changelog

* Use a separate buffer for the address, make the workaround configurable

* Remove now-unnecessary additions

* Force SpiDma to remain Send

* Clarify wording, remove prefix

* Clean up manual register manipulation

* Fix byte order
2024-09-26 15:28:18 +00:00
Dominic Fischer
4377ec083f
Make DmaDescriptor methods public (#2237)
* Make DmaDescriptor methods public

* clippy

* comments

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-26 13:40:54 +00:00
Sergio Gasquez Arcos
fd57488ce3
Remove embedded-svc traits and feature (#2235)
* feat: Remove embedded-svc traits and feature

* docs: Changelog entry
2024-09-26 11:14:42 +00:00
Scott Mabin
6d96810c56
Allow building docs from different tags (#2218) 2024-09-26 08:55:54 +00:00
Björn Quentin
9321a34dbe
Reduce (unnecessary) rebuilds (#2232)
* Reduce (unnecessary) rebuilds

* Avoid redundant clone

* Prefer `.display()` over `.to_str().unwrap()`
2024-09-26 08:15:41 +00:00
Dániel Buga
feaf66847c
Fix warning: 'creating a shared reference to mutable static is discouraged' (#2230)
* Fix warning: 'creating a shared reference to mutable static is discouraged'

* Shorten lifetime of Clocks reference
2024-09-25 15:31:24 +00:00
Dominic Fischer
3bb49b049a
Deduplicate half duplex SPI setup (#2223)
* Deduplicate half duplex SPI setup

* clippy

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-25 10:03:20 +00:00
Dániel Buga
5076d1ee8f
DMA macro cleanup (#2226)
* Fix typo

* Deduplicate dma macro implementations

* Remove accidental defmt

* Extract count macro, use const block
2024-09-25 07:16:48 +00:00
Dániel Buga
fc924bf929
Remove TxPrivate and RxPrivate (#2225) 2024-09-25 06:27:43 +00:00
Dániel Buga
04f43d28c3
Prevent reentry on single-core, add basic tests (#2209) 2024-09-24 20:17:27 +00:00
liebman
cf9050d5d7
Support PSRAM in DmaTxBuf (#2161)
* support psram in DmaTxBuf

* add example that sometimes works :-(

* fmt

* cleanups

* allow chunk_size upto (including) 4095

* this test is passing for me now

* remove chunk_size and compute based on block_size

* return error in `prepare_transfer` if psram is found on non-esp32s3
add `dma_tx_buffer` macro

* missing parens

* changelog

* default 4092 for esp32 & fmt

* no errors anymode

* use block_size is_some to flag invalid psram in prepare_transfer

* drop block_size from macro, the buffer allocation was not being aligned - its not needed for dram anyway.

* missed macro example

* use defmt::Format that decodes owner like Debug

* fix typo

* DmaTxBuf: its an error if buffer is in psram and block_size is none

* DmaTxBuf: its an error if buffer is in psram and block_size is none

* update for PSRAM feature changes

* address alignment comments
add simple test

* fmt

* better alignment test

* revert alignment test

---------

Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
2024-09-24 15:21:58 +00:00
Dominic Fischer
826754c482
Remove ChannelTypes trait (#2220)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-24 15:01:11 +00:00
Jesse Braham
4534ee13ae
Implement embedded_hal_async::delay::DelayNs for TIMGx timers (#2084)
* Update `hil-test` package dependencies, add simple test for async delay with `SYSTIMER`

* Implement `embedded_hal_async::delay::DelayNs` for the `TIMGx` timers

* Improve tests slightly

* Update `CHANGELOG.md`

* Enable `delay` and `delay_async` tests for the ESP32-H2

* Fix error in `delay_async` test after rebasing

* ESP32 does not have `SYSTIMER`, so don't try to test it :)

* Protect int_ena modifications with INT_ENA_LOCK, clear int_clr in ISRs, move interrupt binds from Future constructor into new_async constructor

* Fix wrong imports

* Address reviews: Remove duplicated/useless code and add HIL test for delay_us and delay_ms

* Implement DelayNs on Target instead of Periodic

* clean dead code

* fix after rebase

* fix build errors

* More accurate nanos to ticks calculation

* Fix wrong handler passed to set_interrupt_handler()

* Update esp-hal/src/timer/timg.rs

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* cleanup left over

---------

Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-09-24 08:50:06 +00:00
Scott Mabin
117327e206
esp-config: allow negative values (#2204)
* esp-config: allow negative values

* Add small test for parsing erroneous negative values

* split Value::Number into signed and unsigned
2024-09-24 07:07:06 +00:00
Dominic Fischer
26fc8871db
Simplify DMA interrupt handlers (#2215)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-23 16:55:54 +00:00
Dániel Buga
02d221ee52
Fix TWAI on ESP32 (#2207)
* Some more gpio cleanup

* Allow TWAI loopback using the same pin, enable ESP32

* Impl Format for ErrorKind

* Generic frame constructors

* More TWAI cleanups

* Fix signals

* Set self-reception bit

* Teach users to use const blocks

* Fix resetting TWAI

* Set opmode when starting

* Apply errata workaround

* Fix ESP32 baudrate

* Clean up read_frame a bit

* Changelog

* Clean up clippy

* Fix compile errors

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-09-23 15:24:27 +00:00
Dániel Buga
f2c473d3bc
Remove DMA RegisterAccess::init_channel (#2205) 2024-09-23 14:48:20 +00:00
Dániel Buga
d971d65c98
Add chip-specific features for tests/examples (#2175)
* Refactor metadata parsing to allow spaces in keys

* Emit separate examples per chip

* Allow setting features for specific chips
2024-09-23 11:42:11 +00:00
liebman
987f00bb1d
PARL_IO: fix for garbage output at the start of some TX operations (#2211)
* per TRM the TX clock should only be re-enabled after tx_start

* CHANGELOG

* added tests to check the for the correct number of clocks during valid

* parl_io: fix test for esp32h2

* tests: parl_io: h2 PCNT does not like 20MHz
2024-09-23 10:27:43 +00:00
Dominic Fischer
794cdb0af4
Use enumset for DMA interrupts instead of countless functions (#2196)
* [1/x] Use enumset for DMA interrupts instead of countless functions

* [2/x] Remove the countless functions from RegisterAccess

* Use Into

* [3/3] Use enums everywhere in the DMA module

* Remove redundant enum_set!

* Remove `available_` prefix

* Use `pending_` prefix

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-23 08:43:56 +00:00
Dániel Buga
89d9de67eb
Enable QSPI tests on ESP32 and clean up (#2198)
* Clean up qspi test cfgs, enable on ESP32

* Correct comments

* Clean up init_spi_data_mode

* Fix qspi_write on ESP32

* Further cleanup in SPI driver

* Clean up qspi_read

* Fix qspi_write_read test on ESP32

* Merge QSPI tests

* Clean up test

* Attempt to fix test GPIO assingment

* Update esp-hal/src/spi/master.rs

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

* Update esp-hal/src/spi/master.rs

* Make sure pins have no internal pullups

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-09-23 08:37:35 +00:00
Dániel Buga
3ee8fa61ee
Apply rustfmt fix (#2210) 2024-09-23 08:19:29 +00:00
Björn Quentin
37fa662fe7
Remove most PSRAM features (#2178)
* Make most of PSRAM features into run-time configs

* Make CI green again

* Make CI green again

* Update esp-hal/MIGRATING-0.20.md

Co-authored-by: Scott Mabin <scott@mabez.dev>

* Use Range

* CI

* Rebase fixes

* Update esp-hal/src/lock.rs

Co-authored-by: Scott Mabin <scott@mabez.dev>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-09-20 16:43:25 +00:00
Dániel Buga
d4e463b3ff
Slight general cleanup, enable dma-macros test, allow using virtual mem2mem channel on c2 (#2200)
* Cfg features, not devices

* Remove InterruptBinder

* Clean up allow(declare_interior_mutable_const)

* Small embassy cleanup

* Enable dma-macros for 32 and S2

* Use MEM2MEM1 on C2

* Remove esp32-specific code from test
2024-09-20 15:04:18 +00:00
Sergio Gasquez Arcos
3d0a1998fa
Allow configuring the watchdogs in the init config (#2180)
* feat: Allow configuring the watchdogs in the init config

* docs: Update changelog

* refactor: Remove unnecesary unsafe

* feat: Add a config module

* test: Add some init tests

* style: Rename all ocurrences to esp_hal::config::Config::default()

* style: Fix format

* fix: Doc errors

* revert: Move Config struct to lib.rs

* tests: Add default config test

* test: Add a test with CpuClock::max()

* test: Add timg1 test

* feat: Move Config struct to config module and reexport it in lib.rs

* fix: Fix init compilation for C2

* revert: Move Config struct to config module and reexport it in lib.rs

* fix: Use proper timergroup
2024-09-20 13:51:35 +00:00
Björn Quentin
370f54119f
Create mutexes in heap memory (#2202)
* Create mutexes in heap memory

* CHANGELOG.md

* Remove unnecessary CS usage
2024-09-20 12:45:57 +00:00
Dániel Buga
5324bce815
Rework locks (#2197)
* Move lock impls out of lib.rs

* Reimplement Lock using ReentrantMutex

* Reimplement Lock using ReentrantMutex

* Refactor away some duplicate lock logic

* Return owner from try_lock

* Rework critical section to avoid spinning in irq-free context

* Fail compilation on unknown architectures

* Explain what RESERVED_MASK is

* Create one lock per timer group
2024-09-20 11:05:37 +00:00
Dániel Buga
d5afeeddc8
H2: enable TWAI, enable delay test (#2199)
* Add TWAI support for H2

* Enable delay test on h2

* Also enable example

* Changelog

* De-CAN the example
2024-09-20 07:04:52 +00:00
Dániel Buga
5de267ab09
Fix known SPI issues (#2179)
* Re-enable tests

* Clean up

* Pass two lengths to configure_datalen

* Add Dominic's test changes

* Ensure DMA buffers are properly aligned

* Impl Format on DmaDescriptor

* Fix waiting for transaction to complete

* Fix DMA transfers

* Changelog

* Avoid explicit panic in test case

* Remove redundant test case

* Reintroduce wait for ESP32
2024-09-19 18:00:50 +00:00
Scott Mabin
ba63beb3b2
Move binary logging to sys crate (#2183)
* Move binary logging to sys crate

* make ieee take radio clks by value

* rename wifi-logs to binary-logs and fix compilation

* update sys to use correct size types

* move rtc_clk_xtal_freq_get to esp-hal

* changelogs and migration guide

* s/wifi-logs/sys-logs/g

* activate log features for esp-wifi-sys

* ble log fix c2

* fix logs using latest sys rev

* fix warning
2024-09-19 15:19:54 +00:00
Dániel Buga
25eff6a255
Enable I2S tests on ESP32 and work around first sample issue (#2194)
* Enable I2S tests on ESP32 and work around first sample issue

* Fix sample->channel assignment inconsistency

* Add to changelog
2024-09-19 15:13:25 +00:00
Scott Mabin
d9d771706f
esp-config (#2156)
* Initial esp-config poc, replacing the place-spi-driver-in-ram feature

* Allow documentation generation for configuration options

* add `Value::Number` and a macro to parse

* Add Value::String and replace esp-wifi's config

* repo maint

* make bool parsing stricter and number parsing more flexible

* use hand rolled const str to int

* Collect unknown config options

* friendly errors

* also batch invalid values

* dump msrv to 1.79

* Mention perf boost from disabling logging

* review suggestions

* output selected config

* changelogs and migration guides

* review feedback

* avoid multiple case conversions where possible

* refactor generate, fix bug, add full test

* run host tests in CI

* add more esp-config tests

* review comments

* add cargo env workaround
2024-09-19 08:58:29 +00:00
Dániel Buga
46be3b19b5
Some minor I2S cleanups (#2190)
* Clean up rx_start

* Improve readability of register manipulation

* Enable failing tests on ESP32

* Improve consistency

* Merge tests

* Disable ESP32 for now

* Clean up some cfgs

* Avoid as pointer-casts

* Inline wait_for_dma_done

* Remove a level of indirection

* Fix typos

* Resolve questionmarks
2024-09-19 07:33:52 +00:00
Dániel Buga
f765a6b094
Remove Debug2Format from esp-hal (#2184) 2024-09-18 19:53:19 +00:00
Dániel Buga
c0a9934e62
Pass --verify when running HIL tests (#2188) 2024-09-18 14:39:35 +00:00
Dániel Buga
b1ca30e404
Disable problematic ESP32 test (#2185) 2024-09-18 13:58:54 +00:00
Dániel Buga
d9532bbba7
Fix and enable I2S tests on ESP32-S2 (#2181)
* Fix PDMA channels, use peripheral signal instead of external connection

* Fix i2s test setup for esp32s2
2024-09-18 09:43:37 +00:00
Dániel Buga
344ee133bc
Move SPI tests into the same file (#2177)
* Implement Peripheral for Level

* Move SPI tests into the same file

* Fix test on H2

* Also fix C6 signal numbers
2024-09-18 07:08:51 +00:00
Dániel Buga
fc92beebe6
Guide: Clarify that Level can be used as an output signal (#2176)
* Clarify that Level can be used as an output signal

* Implement Peripheral for Level
2024-09-18 07:01:16 +00:00
Dominic Fischer
5ae76d727e
Remove pin generics from I8080 (#2171)
* Remove pin generics from I8080

* Doc example

* temp

* More docs

* doc fix

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-17 13:56:01 +00:00
Anthony Grondin
a787a13441
Implement TryFrom<u32> for ledc::timer::config::Duty (#1984)
* feat(buzzer): Add `esp-hal-buzzer` to drive a piezo-electric buzzer.

Provides a driver for a piezo-electric buzzer by abstracting LEDC and offering a user-friendly API for a buzzer

* Move songs into example and refactor songs module.

* Move `esp-hal-buzzer` to https://github.com/esp-rs/esp-hal-community/

* Update `CHANGELOG.md`

---------

Co-authored-by: Jesse Braham <jesse@beta7.io>
2024-09-17 13:44:12 +00:00
Dominic Fischer
9de459c663
Add more thorough I8080 HIL tests (#2173)
* Add I8080 HIL test

* add fixme comment

* fmt

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-17 12:01:27 +00:00
Dániel Buga
cc4c6e1a8e
Tweak xtensa interrupt handling (#2148)
* Tweak xtensa interrupt handling

* Deduplicate peripheral interrupt handling
2024-09-17 08:10:21 +00:00
Scott Mabin
45806dfba0
use esp types in peripheral docs (#2172) 2024-09-16 20:49:07 +00:00
Dániel Buga
65396dda1f
Fix UART when using RcFast clock source (#2170)
* Refactor test_send_receive_different_baud_rates_and_clock_sources

* Don't rely on external connections for UART test

* Enable (failing) RcFast for C2/C3

* Make sure fast clock is enabled
2024-09-16 20:48:25 +00:00
Dániel Buga
87c2741305
Migration guide fixes (#2168)
* Fix use of Input in guide

* Add AnyPin change to guide
2024-09-16 17:47:06 +00:00
Jesse Braham
f496579c3b
Remove the esp-hal-smartled package (#2169) 2024-09-16 17:17:26 +00:00
Dominic Fischer
d44affcbf5
Prevent screen tearing in I8080 example (#2167)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-16 14:36:21 +00:00
Dániel Buga
2971c08ed4
Fix double writes (#2159)
* Fix double writes

* Only flush if we need to read
2024-09-16 11:22:14 +00:00
Dániel Buga
c9c7aa9253
Slight timer cleanup (#2158) 2024-09-16 11:21:33 +00:00
Björn Quentin
831df5a83c
Be more clear about the esp-alloc feature in esp-wifi's migration guide (#2165) 2024-09-16 11:21:11 +00:00
Dániel Buga
dfb40c0416
Fix overflowing subtraction (#2164) 2024-09-16 10:47:16 +00:00
Dániel Buga
b5dd5aed17
Gpio cleanup (#2157)
* InterruptStatusRegisterAccess

* GpioRegisterAccess

* Remove GpioProperties

* Hide private methods

* Simplify the analog macro

* Fix typo

* Remove unused NMI status read

* Hide ISRA

* Fix macro syntax

* Simplify rtc_pins macro

* Fix type name
2024-09-16 10:14:34 +00:00
Dániel Buga
f48415e717
Fix esp_alloc doc (#2163) 2024-09-16 08:59:21 +00:00
Dániel Buga
2a74addee0
Fix DMA starving SPI (#2152)
* Fix DMA starving SPI

* Simplify cfgs

* Trigger an update before starting transaction

* Do not update after enable_dma, use start_operation
2024-09-13 08:51:31 +00:00
Demo for summer'23
351a64937b
one typo; one misleading comment fixed (#2153)
* one typo; one misleading comment fixed

* agreed simplification
2024-09-12 20:31:24 +00:00
Dániel Buga
562c891ef9
SPI pins are no longer optional (#2133)
* SPI pins are no longer optional, rename DummyPin

* Swap QSPI test expected levels

* Tweak documentation around Level, implement PeripheralOutput

* Fmt
2024-09-12 10:59:12 +00:00
Dániel Buga
515e67092b
Remove PcntSource (#2134) 2024-09-12 08:30:16 +00:00
Danila Gornushko
b5152dcae5
Add esp-alloc to trouble ble example (#2149)
* add esp-alloc to trouble ble example

* rustfmt
2024-09-12 07:11:54 +00:00
Dániel Buga
f8e2341116
Fix pin collision in I2S tests (#2147) 2024-09-12 06:34:31 +00:00
Dániel Buga
e7dab298f5
Rename and wrap ErasedTimer (#2144)
* Rename and wrap ErasedTimer

* Also rename conversion trait
2024-09-11 20:29:21 +00:00
Björn Quentin
24c545db4a
I2C error recovery (#2141)
* Recover from I2C errors (the hard way)

* Adjust test to cover the problematic case

* Replace macro-usage

* CHANGELOG.md entry

* Appease Clippy

* TIL: `Result::inspect_err` exists

* Turn public `recover` into private `internal_recover`
2024-09-11 15:50:25 +00:00
Dániel Buga
7a733a75db
GPIO interconnect (#2128)
* Allow accessing signal list via ErasedPin

* Replace AnyPin with more flexible signal config

* Update tests and examples

* Fix enable_from_gpio value

* Access signals from pin drivers

* DummyPin is not a pin

* Remove redundant public fns

* Various fixes, rename ErasedPin

* Changelog

* rustfmt

* Update i8080

* Typos and endless recursion

* Drop Pin suffix from traits

* Extract AF conversion

* Touch up changelog

* Clean up spi tests

* Refactor pull resistor handling

* Don't disable configured output functionality

* Clean up TODO

* Tweak docs

* Clean up examples
2024-09-11 15:15:55 +00:00
Dániel Buga
f2e0211c1b
Use AtomicPtr, explain caveats (#2110) 2024-09-11 10:39:29 +00:00
Dominic Fischer
127df3c311
Introduce traits for the DMA buffer objects (#1976)
* Introduce traits for the DMA buffer objects

* Move preparation to DMA module for reuse

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-11 10:31:29 +00:00
Juraj Sadel
f374d6a102
Enable SPI_DMA_XX_ASYNC and _PCNT tests on ESP32 and S2, remove GPIO usage from description (#2140) 2024-09-11 10:23:07 +00:00
Björn Quentin
312746fb14
Fix I2S examples (#2139)
* Fix I2S examples

* Fix remaining examples

* Mention asymmetric variant of the `dma_buffers!` macro in the migration guide
2024-09-11 09:11:42 +00:00
Dániel Buga
9f5a57d819
Clean up UART (#2132)
* Clean up

* Add note to significant order of ops
2024-09-10 16:11:00 +00:00
Dániel Buga
dafad9b487
Allow conjuring private::Internal (#2118)
* Allow conjuring private::Internal

* Hide reexport
2024-09-10 14:25:21 +00:00
Björn Quentin
7332f5834a
Fix SPI DMA write/read for ESP32, ESP32-S2 (#2131)
* Fix SPI DMA write/read for ESP32, ESP32-S2

* CHANGELOG.md

* Review comments
2024-09-10 13:23:52 +00:00
Sergio Gasquez Arcos
208339ddeb
fix: Matrix link (#2130) 2024-09-10 11:05:14 +00:00
Sergio Gasquez Arcos
6f40dc2cca
Add issue templates (#2124)
* feat: Add issue templates

* feat: Address review comments

* feat: Add GH discussion link
2024-09-10 10:32:55 +00:00
Alexandra Clifford
e1c27f1b22
Some minor esp-ieee802154 updates (#2114)
* Use default CCA threshold value (per esp-idf)

* apply different consts for h2 versus c6 in tx power convert func

* Fix compile error when building with binary-logs feature

* Fix possible integer underflow error
2024-09-09 17:15:57 +00:00
Björn Quentin
ddf4ff7e9d
Make sure we can compile with defmt (#2126)
* Set DEFMT_LOG in CI

* Set DEFMT_LOG in CI

* Set DEFMT_LOG in CI

* Fix BLE vs DEFMT issue

* Fix ESP32 defmt problems in psram.rs

* Use `defmt` feature on `bt-hci`
2024-09-09 16:40:30 +00:00
Dániel Buga
be82a6521a
Allow pin drivers as wakeup sources (#2095)
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-09-09 10:45:46 +00:00
Dominic Fischer
3ea95bd0d8
Faster SHA (#2112)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-09 10:18:38 +00:00
Björn Quentin
6295c5f9da
Esp wifi/fix wifi logs (#2117)
* Fix `wifi-logs` feature

* Some clarifications in the esp-wifi migration guide

* CHANGELOG.md

* Review comments

* Check more features
2024-09-09 10:15:52 +00:00
Dániel Buga
05941ccc37
Touch pin definition overhaul (#2109)
* Merge touch macros

* Add missing touch pins, remove trait impl indirection

* Remove unused stuff

---------

Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
2024-09-09 10:05:43 +00:00
amsam0
82a9abfff8
Allow setting RTC time (#1883)
* Initial WIP RTC set implementation

* Deprecate get_time_raw and add docs + some cleanup

* Update rtc time example

* Format

* Update changelog

* Add some comments linking the PR

* Small compilation fixes

* C6 and H2 fixes

* Remove parantheses from if statement lol

* Remove accidental changelog change

* Implement boot time wrapping to avoid overflows

* Remove unused get_rtc_time_ms and get_rtc_time_us functions

* Make get_rtc_time_us public and re-add get_rtc_time_ms as public

* Update changelog

* Remove get_time_raw and replace with public get_rtc_time_raw

* Changelog reordering

* Function renaming

* Use fugit and update changelog

* Small typo fix

* Fix changelog addition from merging

* Use chrono for current_time and set_current_time

* Fix changelog

* Update example

* Fix merge errors

* Rename `time::current_time` to `time::uptime`

* Revert "Rename `time::current_time` to `time::uptime`"

This reverts commit fe8446899747c88d5b9f945f319e1133b90773ee.

* Format

* Add info to migration guide

* Fix compilation for esp32c2

* Remove information about setting RTC time from migration guide since it isn't really relevant

---------

Co-authored-by: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com>
2024-09-09 08:32:15 +00:00
Björn Quentin
d71434adfb
esp-wifi uses global allocator, esp-alloc supports multiple regions (#2099)
* esp-wifi uses global allocator, esp-alloc supports multiple regions

* CHANGELOG.md

* Apply suggestions

* Use `alloc` when linting esp-wifi

* Make coex example build for ESP32

* Re-enable some wifi examples for ESP32-S2

* Optionally depend on `esp-alloc` (by default)

* Rename INSTANCE -> HEAP
2024-09-06 15:42:19 +00:00
Björn Quentin
b3d2aaddd0
Prepare esp-backtrace 0.14.1 (#2107) 2024-09-06 14:47:09 +00:00
Scott Mabin
a3f734028a
ensure that clock init happens after rtc domain is initialized (#2104) 2024-09-06 13:58:35 +00:00
Ulf Lilleengen
93f1012663
Add integration with bt-hci crate (#1971)
* Add integration with bt-hci crate

Implementing traits from bt-hci allows the BleConnector to
be used with the Trouble BLE stack.

* use packed based read interface

* Improve example to allow another connection after disconnect

* update trouble version

* Workaround for spurious command complete events

* fix formatting

* ignore notify errors in example

* fix clippy warnings

* remove async feature from hal dependency

* remove deprecated feature from example

* Adopt to api changes

* Api fix for esp32

* Set rust-version of esp-wifi

* bump MSRV to 1.77 for CI and esp-hal

* Add changelog entry
2024-09-06 13:08:25 +00:00
Szybet
e6da89627b
Update esp-println version in usage section (#2100) 2024-09-06 11:48:21 +00:00
Björn Quentin
598212a020
Make additional memory available as dram2_uninit (#2079)
* Make additional memory available as `dram2_uninit`

* CHANGELOG.md
2024-09-06 10:55:33 +00:00
Dániel Buga
d6813a4bf0
Random additional GPIO cleanups, implement Peripheral for drivers (#2094)
* Reuse enable_iomux_clk_gate

* Remove public functions

* Remove set_to_input

* Deduplicate constructor

* Deduplicate is_listening

* Hide PinFuture better

* Deduplicate set_int_enable

* Align macro indentation

* Typo

* Slightly simplify the touch_into macro

* Implement the AnalogPin trait directly

* Provide default impls for simple forwarding methods

* Newtype ErasedPin

* Merge rtc_pin macros

* Fmt

* Changelog

* Fix migration guide

* Fix example

* Fix ETM
2024-09-06 10:26:23 +00:00
Sergio Gasquez Arcos
b5f0246129
Reordered RX-TX pairs to be consistent (#2074)
* feat: Update rx-tx order in i2s

* feat: Update rx-tx order in dma macros

* feat: Update rx-tx order in spi

* feat: Update rx-tx order in aes

* feat: Update rx-tx order in mem2mem

* feat: Update rx-tx order in twai and split methods

* feat: Update rx-tx order in twai

* feat: Update rx-tx order in twai and uart docs

* docs: Add sentence about order

* docs: Update changelog

* feat: Update rx-tx order in embassy_interrupt_spi_dma tests

* style: Rustfmt

* docs: Migrating guide

* fix: Typo

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* fix: Diff

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* fix: Tests rx-tx order

* fix: Update new_with_default_pins order

* feat: Update rx/tx order in hil_test::common_test_pins!

* feat: Update dma_extmem2mem example

* fix: Revert deleted input arg

* style: rustfmt

* feat: Disable test_asymmetric_dma_transfer for S2

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-09-06 09:56:10 +00:00
liebman
492e35aa74
esp-wifi: other crates also provide strchr (littlefs2-sys) (#2096)
* esp-wifi: other crates also provide strchr (littlefs2-sys)

* esp-wifi: other crates also provide strchr (littlefs2-sys)

* changelog

* fmt :-(
2024-09-06 09:22:33 +00:00
Juraj Sadel
17daa464ba
Enable ESP32 HIL (#1977)
* Enable ESP32 HIL

* RMT fixed

* SPI DMA partially works, _pcnt tests not working

* bckup

* finish

* readme and cleanup

* rebase + cleanup

* RMT S2 pin typo + clean forgotten comments

* review comments

* update 10000

* indentation

* replace cfg gate with cfg_if
2024-09-06 08:53:27 +00:00
Anthony Grondin
fba475ee40
Add missing #[doc(hidden)] in xtensa-lx-rt-proc-macros (#2097) 2024-09-06 06:36:54 +00:00
Scott Mabin
70126c8149
Rename esp_hal::time::current_time to esp_hal::time::now (#2091)
* rename esp_hal::time::current_time to esp_hal::time::uptime

* changelog

* move more things to init

* s/uptime/now/g
2024-09-05 14:57:56 +00:00
Dániel Buga
f11c18a6b9
Optionally type-erased GPIO drivers (#2075)
* Remove type erased gpio structs

* Implement Peripheral for ErasedPin

* Simpler type erasing, accept ErasedPin in pin drivers, remove type erased drivers

* Reformulate pin drivers using Flex

* Erase gpio types by default

* Accept any pin in AnyPin

* Add changelog and migration guide

* Fix tests and examples

* Undo rename of clone_unchecked
2024-09-05 14:14:51 +00:00
liebman
a5ab73959e
i2c: fix embedded-hal transactions (#2028)
* i2c: fix embedded-hal transactions

* changelog+fmt

* small naming cleanup

* i2c: fix 1 byte reads

* typo

* small cleanup and add a few internal docs

* update changelog

* rebase & CHANGELOG

* extract next op conversion

* fix `setup_read()` logic for 0 length reads.

* return error for 0 length reads and 0 length  writes where start=false

* comment about max_len in setup_write()

* filter out 0 length read operations in `transaction()`

* Short circuit for problematic 0 lengths in read_operation and write_operation

* don't short circuit a 0 length write operation if stop=true

* handle write_read when the read bufer is empty
2024-09-05 14:05:00 +00:00
M4tsuri
4f97befdde
Implement sleep and wakeup functionalities for ESP32C2 #1920 (#1922) 2024-09-05 13:39:46 +00:00
liebman
a2af2ac65e
lcd_cam: fix wrong buffer length used if 16bit and len<=8192 (#2085)
* lcd_cam: fix wrong buffer length used if 16bit and len<=8192

* changelog
2024-09-05 13:07:00 +00:00
Gnome!
4d9ea52eae
[esp-hal-procmacros] Update to proc-macro-error2 (#2090) 2024-09-05 11:40:52 +00:00
Dominic Fischer
b6aceb1de8
Improve SHA driver API (#2049)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-05 11:39:46 +00:00
Dániel Buga
5370afb1eb
Build examples in debug mode (#2078)
* Build examples in debug mode

* Allow building psram examples in debug mode in CI

* Don't rebuild tests, try to avoid rebuilding dependencies
2024-09-05 10:04:07 +00:00
Dániel Buga
42a0417fba
Fix nightly warnings (#2082) 2024-09-05 07:40:22 +00:00
Scott Mabin
80c0a81718
fix issue handler, don't rebuild on main the merge queue checks this for us (#2077) 2024-09-04 16:02:47 +00:00
Dániel Buga
fb694110d2
Accept ErasedPin in AnyPin (#2072)
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-09-04 15:17:39 +00:00
Dániel Buga
e898e89f60
Remove AnyInputOnlyPin (#2071)
* Remove AnyInputOnlyPin

* Add section to migration guide

* Remove unnecessary enum

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-09-04 15:11:08 +00:00
Dániel Buga
39109a4a05
Remove gpio dispatch macro-defining proc macro (#2069)
* Keep a single PinType trait

* Merge impl blocks

* Deduplicate usb pad workaround

* Deduplicate some bit manipulation

* Remove gpio dispatch proc macro

* Inline PinType into GpioProperties
2024-09-04 14:47:24 +00:00
Dániel Buga
99bf346898
Remove the need to manually pass clocks around (#1999)
* Clean up passing clocks to drivers

* Update changelog

* Initialise Clocks in a critical section

* Fix calling now() before init

* Fix doc

* Fix esp-wifi migration guide

* Add safety comment

* Update tests
2024-09-04 14:13:51 +00:00
Dániel Buga
7688504289
Remove Gpio type aliasses (#2073)
* Remove Gpio type aliasses

* Clean up examples
2024-09-04 13:37:56 +00:00
Kirill Mikhailov
9bec6a1806
Adding I2C HIL test (#2023)
* i2c hil test

* pin

* fmt

* Test

* WIP (gpio test left)

* Finalize the CODE part (to be cleaned up)

fmt

* Smaller cleanup

* cleanup

* rebase

* fix

* getting last chips ready

* Addressing reviews
2024-09-04 12:45:58 +00:00
Jesse Braham
b7b916f03a
Remove most trait implementation features from esp-hal (#2070)
* Eliminate esp-hal's `ufmt` feature

* Eliminate esp-hal's `embedded-hal-02` feature

* Eliminate esp-hal's `embedded-hal` feature

* Eliminate esp-hal's `embedded-io` feature

* Eliminate esp-hal's `async` feature

* Update `CHANGELOG.md`

* Remove `async` from required features for HIL tests

* Update migration guide
2024-09-04 06:15:27 +00:00
Gnome!
49e14b7ccb
Remove lazy_static in favor of OnceLock (#2063)
* [esp-metadata] Remove lazy_static in favor of OnceLock

* [esp-wifishark] Remove lazy_static in favor of normal initialisation

* [ieee802154-sniffer] Shorten SelectorConfig initialisation

* [ieee802154-sniffer] Remove lazy_static in favor of normal initialisation
2024-09-03 14:43:35 +00:00
Björn Quentin
0cf7abfc47
Make esp-wifi build on stable, again. Bump to 0.9.1 (#2067)
* Make esp-wifi build on stable, again. Bump to 0.9.1

* CHANGELOG.md

* MSRV check esp-wifi

* ESP32-S2 doesn't support Bluetooth
2024-09-03 16:10:20 +02:00
Dániel Buga
647e34f401
Remove NoPinType (#2068) 2024-09-03 13:36:14 +00:00
Björn Quentin
9c3b17166f
Bump to esp-wifi 0.9.0 (#2066) 2024-09-03 13:30:28 +01:00
Björn Quentin
5420ce0959
WPA2 ENTERPRISE (#2004)
* WPA2 ENTERPRISE

* Defmt, Clippy, Changelog

* Defmt, again

* Clippy, again

* Mention corresponding JIRA ticket

* Rename

* fmt

* Use Mutex in scheduler

* Adapt wifi_delete_queue

* Adapt log level
2024-09-03 11:22:39 +00:00
Dániel Buga
9465244e0d
Fix various SPI/DMA issues (#2065)
* Add failing test

* Fix enabled interrupt

* Fix using the correct waker

* Changelog

* Enable test on more devices that have SPI3
2024-09-03 10:02:21 +00:00
Dániel Buga
08d406ee2b
storage: Clean up ROM function declarations (#2058)
* Clean up external function declarations

* Tweak syntax
2024-09-02 15:24:41 +00:00
Dániel Buga
c21287a5ef
Provide ehal impls for DummyPin (#2019)
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-09-02 15:16:26 +00:00
Gnome!
671003ace6
[esp-metadata] Make clap dependency optional (#2055) 2024-09-02 14:31:23 +00:00
Dániel Buga
580222758e
Fix hil-test xtask instruction (#2062)
* Fix hil-test xtask instruction

* Fix another mention
2024-09-02 14:08:17 +00:00
Dániel Buga
447411fb58
Rework hal initialization (#1970)
* Rework hal initialization

* Turn sw interrupt control into a virtual peripheral

* Return a tuple instead of a named struct

* Fix docs

* Remove SystemClockControl

* Move software interrupts under interrupt

* Re-document what's left in system

* Update time docs

* Update sw int docs

* Introduce Config

* Fix tests

* Remove redundant inits

* Doc

* Clean up examples&tests

* Update tests

* Add changelog entry

* Start migration guide

* Restore some convenience-imports

* Remove Config from prelude
2024-09-02 13:38:46 +00:00
Björn Quentin
d60bafbf05
Improve CP0-disabled error message (#2061)
* Improve CP0-disabled error message

* CHANGELOG.md
2024-09-02 13:38:10 +00:00
Scott Mabin
b620e35ebe
automatically apply status:needs-attention to new esp-hal issues (#2030) 2024-09-02 11:43:36 +00:00
Dominic Fischer
11f90b9e8b
Protect SYSTIMER/TIMG shared registers (#2051)
* Protect SYSTIMER/TIMG shared registers

* some review comments

* more review comments

* more review comments

* bring back portable_atomic

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-09-02 11:40:25 +00:00
Scott Mabin
6b4079be3a
release prep xtensa-lx-rt@0.17.1 (#2060) 2024-09-02 11:11:36 +00:00
Dániel Buga
44567f6687
Save/restore coprocessor state on stack (#2057)
* Whitespace

* Save and restore coprocessor enable state
2024-09-02 09:45:11 +00:00
Dániel Buga
c5e342a7a7
Clean up gigantic GPIO eyesore (#2048) 2024-09-02 08:58:54 +00:00
Björn Quentin
2dc285a947
QSPI tests (#2015)
* Add QSPI tests

* Simplify

* Add qspi_write_read test
2024-09-02 07:52:20 +00:00
Dániel Buga
8e6411bd31
Random cleanups in non-checked packages (#2034)
* Deduplicate feature check macros

* Re-enable rust-analyzer for most of the workspace

* Cargo fix

* Turn off defmt

* Only build xtask

* Clippy pls

* Fix CI

* Fix paths

* Always create doc directory first

* Revert r-a

* Update esp-hal-procmacros/src/lp_core.rs

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>

---------

Co-authored-by: Dominic Fischer <14130965+Dominaezzz@users.noreply.github.com>
2024-08-30 14:45:54 +00:00
Dániel Buga
fce510f50a
Disable object's unnecessary features in proc macro that loads LP code (#2018)
* Disable object/decompress

* Only enable elf support in object
2024-08-30 14:37:27 +00:00
Sergio Gasquez Arcos
f9ab55c38f
fix: Fix nightly errors (#1934) 2024-08-30 14:08:06 +00:00
Jesse Braham
533288d351
Begin next release cycle (#2039)
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-08-30 12:28:14 +00:00
Dániel Buga
897c92e389
Try to be more helpful (#2044) 2024-08-30 11:46:25 +00:00
Scott Mabin
aacc001e5d
Prepare v0.20.1 release (#2046) 2024-08-30 11:10:35 +00:00
Dániel Buga
28b5cd0158
Fix before_snippet failing in release (#2040)
* Fix before_snippet failing in release

* Fix esp-hal-embassy comment
2024-08-30 10:06:11 +00:00
Jesse Braham
5917275108
Version 0.20.0 (#2038)
* Update package dependencies and bump version numbers

* Update `CHANGELOG.md` for each package to be published

* Remember to update `xtensa-lx-rt` too :)

* Add and use TrapFrame::new() in esp-wifi

* Bump `xtensa-lx-rt` by minor instead of patch, as there are breaking changes

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>
2024-08-29 19:29:33 +00:00
Jesse Braham
bac6bfd1b4
Use newly published versions of all PACs in esp-hal (#2025)
* Use newly published versions of all PACs in `esp-hal`

* Address additional review comments
2024-08-29 13:55:59 +00:00
Dániel Buga
99c238d19d
HIL: Don't skip cleanup (#2024)
* Don't skip cleanup

* Make sure the power is off for a short while
2024-08-28 20:17:10 +00:00
Scott Mabin
6fb636be89
Remove unneeded logs (#2022) 2024-08-28 15:06:33 +00:00
Dániel Buga
84a060013d
Fix defmt compatibility (#2017)
* Fix defmt compatibility

* Update tests to cover macros
2024-08-28 14:07:09 +00:00
Scott Mabin
61bb240166
forward spi methods to SpiDmaBus (#2016)
* forward spi methods to SpiDmaBus

* changelog
2024-08-28 11:18:20 +00:00
Dániel Buga
16abd3d318
Only reserve the interrupt when executors are needed (#2014) 2024-08-28 09:56:22 +00:00
Dániel Buga
6abbc72e11
Test and fix async RSA (#2002)
* RSA cleanup & API consistency change, part 2

* RSA cleanup & API consistency change, part 3

* Add async tests

* Fix async for ESP32

* Merge impl blocks

* Backtrack on some mutability changes

* Use Acquire/Release ordering

* Fwd to write_multi_start instead of duplicating impl
2024-08-28 09:56:05 +00:00
Dániel Buga
c7a7760b51
Implement timer conversion for some arrays (#2012) 2024-08-28 09:54:58 +00:00
Björn Quentin
fbee4e5e4f
Fix (#2013) 2024-08-28 09:42:00 +00:00
Dániel Buga
5dcde78ccc
Re-add feature gate for software_interrupt3 (#2011) 2024-08-27 17:16:19 +00:00
Scott Mabin
65c5dc1781
SPI DMA: use State for both blocking and async operations (#1985)
* use `State` for both blocking and async operations, remove async version of SpiDmaBus in favour of being generic over the mode

* reuse wait_for_idle more

* changelog

* rename generic params for consistency

* Add duplex mode to SpiDmaBus

* implement HalfDuplexReadWrite for SpiDmaBus

* Docs on new async APIs

* Limit half duplex transfers to the capacity of the DmaBuf

* docs

* rebase tests

* address review comments

* remove duplex traits from spi

* fix tests

* spi docs rejig

* s/InUse/TemporarilyRemoved/g
2024-08-27 16:15:59 +00:00
Dániel Buga
8aa1a88a23
Prefer cfg_if (#2003) 2024-08-27 11:53:55 +00:00
Dániel Buga
1003ce0c0f
Clean up SHA, RSA, mandate #[must_use] on Futures (#2000)
* Janitor go brr

* Clean up SHA

* Use max CPU speed

* RSA cleanup part 1

* Clean up nonsense comments

* Mark all futures as must_use
2024-08-27 10:43:58 +00:00
Priit Laes
a41bc4cb3d
gpio: Make AnyPin, AnyInputOnlyPin, DummyPin available from gpio module (#1918)
Making these available straight from `gpio` aligns it with other Embassy
implementations (mainly nrf and stm32).

Signed-off-by: Priit Laes <plaes@plaes.org>
2024-08-26 18:30:24 +00:00
Dániel Buga
e1697310f6
Refactor SPI tests & re-enable S3 and some S2 (#1990)
* Deduplicate spi_full_duplex_dma_async

* Refactor SPI tests

* Separate out PCNT tests

* Re-enable test on S3

* Re-enable some S2 tests
2024-08-26 14:22:19 +00:00
Dániel Buga
d0f98b6c1f
Remove files after test (#1993) 2024-08-26 13:50:40 +00:00
Dániel Buga
341db16874
Use uhubctl to disable and enable usb ports (#1997) 2024-08-26 13:46:32 +00:00
liebman
5f0dc148ed
parl_io: use ReadBuffer/WriteBuffer for async DMA (#1996)
* parl_io: use ReadBuffer/WriteBuffer for async DMA

* CHANGELOG
2024-08-26 13:10:56 +00:00
Dániel Buga
b4ccb359ef
HIL: Multiple featuresets & conditionally enable generic-queue feature (#1989)
* Conditionally enable generic-queue feature

* Allow specifying multiple feature sets and run all of them
2024-08-26 06:19:03 +00:00
Scott Mabin
0e333f7aa2
tell cargo about all our custom cfgs (#1988)
* tell cargo about all our custom lints

* fixup the unexpected cfg lints, including remove clic
2024-08-23 12:56:00 +00:00
Scott Mabin
d610ee83db
Add tests to ensure that we don't reset current_time drivers (#1978) 2024-08-23 11:24:03 +00:00
Kirill Mikhailov
19db509403
Get rid of missing docs in a number of modules (#1967)
* Get rid of missing docs in a number of modules

* address reviews

* Address the rest of reviews

* remove all remaining `allows`

* are you serious?
2024-08-23 09:22:37 +00:00
Dániel Buga
f829c8f2ac
Fix C2 delays (#1981)
* Re-enable delay tests on S2 and C2

* Systimer: use fn instead of constant to retrieve tick freq

* Reformulate delay using current_time

* Take actual XTAL into account

* Re-enable tests

* Fix changelog

* Disable defmt

* Remove unused esp32 code

* Update esp-hal/src/delay.rs

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-08-21 17:33:46 +00:00
Dániel Buga
69cf454a5a
Fix S2 systimers (#1979)
* Add basic systimer interrupt tests

* Remove unnecessary condition

* Fix edge interrupt bitmasks

* Modify target_conf in critical section

* Remove unnecessary fn call

* Fix test

* Add failing test case

* Fix S2 systimer interrupts being fired unexpectedly

* Add changelog entry

* Format
2024-08-21 13:21:13 +00:00
Dominic Fischer
dc6c53ee47
Remove redundant WithDmaSpi traits (#1975)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-08-21 12:59:55 +00:00
Scott Mabin
7dfaca49ba
correct changelog sections (#1974) 2024-08-21 07:03:56 +00:00
Scott Mabin
a33ebe1ed6
Remove free(self) in HMAC which goes against esp-hal API guidelines (#1972)
* Remove `free(self)` which goes against esp-hal API guidelines

* changelog
2024-08-20 12:13:44 +00:00
Dániel Buga
686037be4d
Run HIL tests as part of PR checks (#1959)
* Run HIL tests as part of PR checks

* Cancel pending HIL runs

* Only run for ready PRs
2024-08-20 11:48:49 +00:00
Dominic Fischer
41f9925e2c
[3/3] DMA Move API: Introduce DMA buffer objects (#1856)
* [3/3] DMA Move API: Introduce DMA buffer objects

* Remove FlashSafeDma

* Add async HIL test

* Handle set_length(0) correctly

* Fix tx/rx booleans

* Unlucky

* Preserve previous blocking semantics

* Add delay between starting DMA TX and SPI driver

* Update CHANGELOG

* merge tidy

* Add with_buffers builder

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-08-20 11:47:55 +00:00
Dániel Buga
05582d3ca9
Fix 1GB elfs (#1962) 2024-08-19 14:46:30 +00:00
Anthony Grondin
70491b9e37
Refactor SHA to use trait. Implement Digest traits for SHA (#1908)
* feat(SHA): Refactor SHA to use trait. Implement Digest traits for SHA

* Fix CI. Fix wrong sha mode for esp32

* Save hash register for interleaving operation

An example (wip) `sha_fuzz.rs` was added to test different functionalities of the SHA driver and to ensure proper functionning under all cases.

* Use random data when testing SHA

* fix(SHA): Buffer words until a full block before writing to memory

This fixes interleaving operations by buffering words into the SHA context until a full block can be processed.

* Fix(SHA): Use correct length padding for SHA384 and SHA512.

- This fixes a long running issue with SHA384 and SHA512, where some digest of specific sizes wouldn't compute correctly, by changing the padding length of the size field.

* Re-export digest for convenience

* Remove completed TODO

* Remove SHA peripheral requirement.

- Document safety of the SHA driver.

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-08-19 14:43:47 +00:00
Dániel Buga
ec130877b7
Disable RTT polling in HIL tests by default (#1960)
* Disable defmt-rtt by default

* Update i2s test based on changes done to async

* fmt

* Update readme

* Update more tests
2024-08-19 13:47:22 +00:00
Juraj Sadel
6a38053c15
Patch typo in debug assist register name and used patched esp-pacs (#1968) 2024-08-19 13:44:22 +00:00
Juraj Sadel
42bbdaeb4f
Add basic HIL test for GPIO that can be configured as pin for (#1963) 2024-08-19 11:43:59 +00:00
Juraj Sadel
e708dbc777
Add more SPI DMA (full-duplex) HIL tests (blocking and async) (#1952)
* Add more SPI DMA HIL tests (blocking and async)

* move test repetitions into loops instead, add a description about why PCNT is used, import embedded_hal_async::spi

* clean up
2024-08-19 06:59:55 +00:00
Frostie314159
d1acacb757
Implement Sniffer API (#1935)
* Implemented queue_msg_waiting.

* Fmt.

* Adjusted changelog.

* Fixed CI.

* Fixed pointer mutability.

* Implemented experimental sniffer api.

* Fixed CI..

* Added safety comment.

* Featured gated, PromiscuousPkt

* Format.

* Adjusted imports.

* Added injection example.

* Made RxControlInfo::from_raw public.

* Format.

* Added sniffer example.
2024-08-19 06:51:18 +00:00
Dániel Buga
59728c523f
Some xtask/metadata cleanups (#1965)
* Clean up almost all clippy violations

* Remove redundant variable from context

* Do not clone configs

* Do not collect all config symbols into a vec needlessly

* Do not allocate so many strings
2024-08-19 06:49:05 +00:00
Dániel Buga
f95ab0def5
Simplify initialization APIs (#1957)
* Accept more types in embassy::init

* Apply the same treatment to esp-wifi

* Changelog

* Clean up

* Add doc examples

* Fix Alarm generic parameters
2024-08-16 16:33:29 +00:00
Dominic Fischer
6e706c5f11
Improve SYSTIMER API (#1871)
* Improve SYSTIMER API

* Remove config object

* fix things

* Allow erasure of unit and comparator numbers

* Merge fail

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-08-16 14:59:34 +00:00
Dániel Buga
eb1b295116
Do not reset UsbSerialJtag peripheral (#1961)
* Fix typos

* Add a function to detect debugger connection

* Do not reset USB peripheral

* Changelog

* Fix different register names

* Reuse xtensa_lx::is_debugger_attached
2024-08-16 14:51:34 +00:00
Fan Jiang
f6e69b06d0
Fix GPIO Touch pin I/O (#1956) 2024-08-16 12:39:20 +00:00
Dániel Buga
6127f5df11
Further clean up timers/executors test (#1953)
* Further clean up embassy_timers_executors

* Do not delay for so long

* Print timer values on assert failure

* Clean up some more

* Retry test a few times to counteract probe-rs halting us

* Fix formatting
2024-08-16 06:08:32 +00:00
Dániel Buga
a10f86dbaa
Clean up i2s_async test, add option to repeat (#1951)
* Simplify I2S async test

* Allow running tests repeatedly

* Fail at the first mismatch

* Clean up
2024-08-15 11:48:23 +00:00
Scott Mabin
361a6c58b7
make contribution docs more visible (#1947) 2024-08-15 07:58:06 +00:00
Kirill Mikhailov
f1ec4a2ac9
Removing raw addresses manipulations - part 3 (#1892)
* WIP state

* More fixes

* Roll back `esp-storage` changes

* Small fixes

Will not work, needs another patch for PACs

* update pacs dep

* Lint

* Get rid of unnecessary if-else

fix

* New pacs version
2024-08-14 16:38:00 +00:00
Dániel Buga
9e87792fb9
Update probe-rs, prebuild xtask for HIL tests (#1939)
* Update probe-rs

* Differentiate jobs

* Explicitly print that probe-rs's execution failed

* Do not capture stdin/stderr

* Pre-build xtask binary

* Use current_directory

* Print more info when a file can't be read

* Do not erase flash after a failure

* get_time: fail faster

* Make xtask runnable
2024-08-14 15:47:52 +00:00
Kirill Mikhailov
460eaa254a
Adding TWAI HIL test (#1946)
* Adding `TWAI` HIL test

* add `Frame` trait

* mutability
2024-08-14 14:06:08 +00:00
Kirill Mikhailov
945f8b3a19
ESP32C6: Make ADC usable after TRNG deinitialization (#1945)
* Make `ADC` usable after `TRNG` deinicialization (esp32c6)

* Changelog entry
2024-08-14 12:46:28 +00:00
Sycrosity
c83d1de974
Update to latest release (0.6.0) for embassy-executor in esp-embassy-hal (fixes #1941) (#1942)
* Updated to latest release (`0.6.0`) for `embassy-executor`

* update changelog

* update hil-test version of embassy-executor to 0.6.0

* update embassy-executor in `examples`

* reflect esp_hal change in `OneShotTimer` to not have a lifetime.

* update changelog

* revert OneShotTimer changes
2024-08-14 12:45:46 +00:00
Frostie314159
1173aac945
Implemented queue_msg_waiting. (#1925)
* Implemented queue_msg_waiting.

* Fmt.

* Adjusted changelog.

* Fixed CI.

* Fixed pointer mutability.
2024-08-14 12:44:48 +00:00
Dániel Buga
6b6e628940
Slightly clean up embassy HIL tests (#1937) 2024-08-13 19:39:36 +00:00
Kirill Mikhailov
c53ba38c43
Fix i2c + get rid of unused constants/enums (#1940) 2024-08-13 19:17:55 +00:00
Dániel Buga
352879abce
Fix an infinite loop in interrupt executors (#1936)
* Add failing test

Fix the name of the test fn

* Fix interrupt executor looping

* Fix formatting

* Fix changelog reference

* Move changelog to the right crate

* Remove dead code
2024-08-13 12:51:26 +00:00
Jesse Braham
a6e14067ae
Deny missing docs at the package level, adding exceptions for relevant modules (#1931) 2024-08-13 12:46:17 +00:00
Juraj Sadel
64a7d49a29
Reset peripherals on driver construction (where missing) (#1893)
* Reset peripherals on driver contruction (where missing)

* Don't enable and reset SHA in HMAC ctor

* changelog

* Don't reset the TIMG0
2024-08-13 12:09:04 +00:00
liebman
23f76b0bea
DMA: Don't require implementors of Read/WriteBuffer to be Sealed (#1921)
* DMA: Don't require implementors of Read/WriteBuffer to be Sealed

* CHANGELOG

* mark dma::ReadBuffer and dma::WriteBuffer traits unsafe
2024-08-13 11:48:43 +00:00
Kirill Mikhailov
a3a3ef12e4
Add self-testing mode for TWAI peripheral. (#1929)
* Add self-testing mode for `TWAI` peripheral

* changelog entry

* fix docs build

* fix async example

* Restore example to original state

fix comment

* `NoAck` -> `SelfTest`
2024-08-12 15:22:27 +00:00
KashunCheng
888e9425a4
chore: Update TimerClockConfig to support period updating method (#1898)
* chore: Update `TimerClockConfig` to support period updating method

* docs: added a change log entry
2024-08-12 13:20:02 +00:00
Dániel Buga
63a2d407ee
Fix some typos (#1930) 2024-08-12 12:20:58 +00:00
Alexandra Clifford
1371b11f32
More bandaid fixes for invalid range index and other array access panics (#1923) 2024-08-12 08:28:51 +00:00
Sergio Gasquez Arcos
2e8937a90f
Update probe-rs version (#1914)
* docs: Update probe-rs version

* feat: Simplify probe-rs args

* ci: Update the checkout action to use the fork
2024-08-09 14:11:29 +00:00
Kirill Mikhailov
cb0016aa43
Removing raw address manipulations - PSRAM (#1854)
* WIP state

* WIP state (PSRAM ESP32)

* Use PAC - PSRAM

* Removing "leftover" debug comments

ooops

* Quick fix in `TRNG`

* remove unnecessary unsafe blocks

* Update `esp-pacs` dependency + small fix

* Update to latest PAC version

* Removing wrong code in a comment
2024-08-08 12:19:11 +00:00
Kirill Mikhailov
1574e53b0e
Make C6 ADC calibration work properly again (#1911)
* Reverting changes which provoke wrong `ADC` behaviour

* Minor example fix

* clocks update
2024-08-08 11:52:08 +00:00
Kirill Mikhailov
bb6e710327
Removing unnecessary bitfield from I2C driver (#1900)
* Getting rid of bitfield usage

fmt

* use `variant` methods for opcode

* update pacs dependency
2024-08-08 09:40:13 +00:00
Sergio Gasquez Arcos
6ac56a25dc
Update channels being used in CI jobs (#1910)
* ci: Use stable to build HIL tests

* ci: Remove useless line

* fix: Avoid setting toolchain based on the target
2024-08-08 08:37:22 +00:00
Fan Jiang
3473dda774
TWAI: GPIO pins are not configured as input and output (#1906)
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-08-07 14:22:30 +00:00
Sergio Gasquez Arcos
e58b4d8d89
Check packages with nightly for RISC-V devices (#1881)
* ci: Check pacakges with nightly

* ci: Remove duplication

* perf: Nightly clippy fixes

* revert: Revert unsafe changes

* ci: Use an action to remove duplication

* ci: Update trigger conditions

* ci: Update S2 serial port

* ci: Rename action
2024-08-07 13:32:48 +00:00
Juraj Sadel
54ee364130
ESP32(SPI): Disable the write side when reading is being done in DMA … (#1894)
* ESP32(SPI): Disable the write side when reading is being done in DMA mode

* disable and re-enable MISO and MOSI in write and transfer methods

* changelog
2024-08-07 13:23:49 +00:00
Jesse Braham
56d8d58443
Deny Rust 2018 idioms in esp-hal (#1901) 2024-08-06 15:59:41 +00:00
Jonathan
94db708f49
Touch support for ESP32 (#1873)
* Added touch pad support

* touch: Introduced blocking mode

* touch: moved fns out of TouchPad to prepare async code

* touch: added async support and embassy example
2024-08-06 07:19:41 +00:00
Gavin Li
3049f2804a
esp-wifi/ble/npl: increase event queue size (#1891)
With my ESP32-C6 device, I saw the following panic when scanning was
enabled and there were many BLE devices in vicinity:

    unwrap of `EVENT_QUEUE.enqueue((*event).dummy as usize)` failed: 14,

This occurs because the NPL event queue has overflowed. I increased the
queue size from 10 to 16, and the panic went away. I also did some
testing and discovered that there were at most 13 elements on the queue
at any given time, so a queue size of 16 (which allows for 15 elements)
should give us some margin. This also gives a slight overhead reduction
as the heapless crate recommends the queue size to be a power of two.

Co-authored-by: Gavin Li <git@thegavinli.com>
2024-08-05 21:50:41 +00:00
Juraj Sadel
c5ea0e9149
esp-hal: Add HIL test for embassy timer and executor (#1886)
* esp_hal: Add embassy timers and executors HIL test

* Add timeout to each test

* cfg-gate out systimer tests for ESP32
2024-08-05 21:49:57 +00:00
Sergio Gasquez Arcos
0c29c4381c
ci: Use stable channel for RISCV devices (#1896) 2024-08-01 17:42:49 +00:00
Sergio Gasquez Arcos
40d5481edd
ci: Disable test_asymmetric_dma_transfer for S3 (#1888) 2024-07-31 15:47:44 +00:00
Jesse Braham
311f0127de
Implement embedded_io::{ReadReady, WriteReady} traits for WifiStack (#1882)
* implement `ReadReady` and `WriteReady` traits from `embedded-io` for Wi-Fi

* Allow non-static lifetime for `WifiStack`

* Update `CHANGELOG.md`

* clippy
2024-07-31 07:29:10 +00:00
Jesse Braham
81f3776aa7
Deny warnings in CI (#1877)
* Deny warnings when building in CI

* Build RISC-V using `stable` release channel again
2024-07-30 07:38:57 +00:00
liebman
dd2e475f00
lcd_cam: i8080 fix bad len calculation (missed from ReadBuffer update) (#1876) 2024-07-29 15:13:59 +00:00
liebman
67bb6c54bb
Implement async for lcd_cam i8080 (#1834)
* implement async for lcd_cam i8080

* lcd_cam: implement InterruptConfigurable for blocking and improve async

* lcd_cam: use new async interrupt semantics from #1835

* lcd_cam: move interrupt handler binding into `new_async()`

* lcd_cam: Instance::is_listening_lcd_done not used

* i8080: no need for seperate `new_async()`

* i8080: don't use DmaTxFuture, just test for dma error after complete

* add HIL tests for LCD_CAM i8080 in blocking and async.

* lcd_cam_i8080: test channels configured for async as well since teh compiler can't prevent it for now

* fmt :-/

* lcd_cam fix comment

* changelog

* lcd_cam async: no need to enable interrupts until polled

* lcd_cam: i8080 update for ReadBuffer changes
2024-07-29 13:59:52 +00:00
Björn Quentin
56806313bd
Fix time_driver (#1875)
* Fix time_driver

* CHANGELOG.md
2024-07-29 13:48:11 +00:00
Alexandra Clifford
36ed7bdf14
Adds temporary fix for rcv frame panic issue (#1862) 2024-07-29 07:36:39 +00:00
Jesse Braham
237804efb6
Add a new constructor to gpio::Io which does not bind an interrupt handler (#1861)
* Add a new constructor to `gpio::Io` which does not bind an interrupt handler

* Update `CHANGELOG.md`
2024-07-26 13:28:00 +00:00
Dominic Fischer
2744a5dd86
SPI: Clear DMA interrupts before (not after) DMA starts (#1859)
* SPI: Clear DMA interrupts before (not after) DMA starts

* Fix Rust 1.80 doc thingy

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-26 08:51:39 +00:00
Björn Quentin
c6207c0f59
Lift static requirement on DMA buffers (#1837)
* Lift `static` requirement on DMA buffers

* Seal `Word`, use `size_of_val`

* Fix

* CHANGELOG.md

* Use Clippy's safety comment style

* Top-level docs regarding mem::forget
2024-07-25 13:55:02 +00:00
Jesse Braham
45db1b55ec
Add #![deny(missing_docs)] to the aes, analog, clock, and dma modules (#1849)
* Deny missing documentation within the `analog` module

* Deny missing documentation in the `dma` module

* Remove unused `ENCRYPT_MODE`/`DECRYPT_MODE` constants from `AesFlavour` trait

* Deny missing documentation in the `aes` module

* Deny missing documentation in the `clock` module

* Update `CHANGELOG.md`
2024-07-25 13:05:59 +00:00
Jesse Braham
3215d93f53
Use peripheral ref pattern for OneShotTimer and PeriodicTimer` (#1855)
* Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer`

* Update tests and examples to reflect changes in timer API

* Update `CHANGELOG.md`
2024-07-25 12:52:34 +00:00
liebman
c7218fba2b
Implement DMA to/from psram on esp32s3 (#1827)
* initial non-working attemt for dma from psram on esp32s3

* flush cache - now works for extmem as source but not for extmem as destination

* use cache_invalidate_addr on destination address

* update changelog

* require dma transfers to/from psram to be aligned to dcache line size

* cache_writeback_addr() should suspend/resume dcache autoload

* no need for cfg(esp32s3) in esp32s3 specific module

* dma: document alignment requirements for DMA to/from PSRAM

* fix doc typos
2024-07-25 12:51:02 +00:00
Björn Quentin
7f251b457a
Fix i2c freeze (#1847)
* Check errors while waiting for TXFIFO_WM

* Limit iterations in `wait_for_completion`

* Detect errors in async-I2C

* CHANGELOG.md

* async `wait_for_completion` ESP32 special treatment

* Simplify ESP32 workaround

* Clippy
2024-07-24 15:09:46 +00:00
Dominic Fischer
4ef91c5941
Change semantics of DMA futures (#1835)
* Change semantics of DMA futures

* Only clear specific interrupt bit when listening for an "in progress" interrupt

* Fix PARL_IO Rx

* Only enable interrupts when future is polled

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-24 14:26:39 +00:00
Björn Quentin
38f1d28585
Fix async PARL_IO RX (#1851)
* Fix async PARL_IO RX

* CHANGELOG.md
2024-07-24 13:19:19 +00:00
Juraj Sadel
3299348ebc
esp_hal: Warnings in examples cleanup (#1852) 2024-07-24 13:18:50 +00:00
Scott Mabin
e8b0a376eb
Check all features and targets in CI when linting (#1824)
* Check more features and targets in CI when linting

* Address clippy lints

* Address clippy lints for esp-wifi

* Expand println and storage checks

* Remove uneeded clippy lint

* Check every package for each target

* resolve esp-wifi clippy lints

* use defmt when building esp-wifi

* clean up

* fix warning in meta crate

* simplify CI workflow

* split up clippy jobs
2024-07-24 11:45:41 +00:00
BMCG0011
5d6354ccbd
Expose InputPin.is_interrupt_set in implementation of esp-hal::gpio::… (#1839)
* Expose InputPin.is_interrupt_set in implementation of esp-hal::gpio::Input

* Move entry in changelog from changed to added
2024-07-23 19:47:59 +00:00
Björn Quentin
426c8fb0bd
Improve Xtensa backtraces (#1838) 2024-07-23 19:47:46 +00:00
Björn Quentin
8be7f81e34
usb-serial-jtag example: Hint for Windows users (#1845) 2024-07-23 19:23:35 +00:00
Björn Quentin
d5bff95a1b
Fix I2s async-tx (#1833)
* Fix I2s async-tx

* CHANGELOG.md

* Add async i2s test

* Cleanup

* Use `Spawner::for_current_executor()` instead of manually creating the executor
2024-07-23 18:09:58 +00:00
Scott Mabin
c090191afb
try to fix espflash command not found in HIL CI (#1848)
* try to fix espflash command not found in HIL CI

* Specify espflash port

---------

Co-authored-by: Juraj Sadel <juraj.sadel@espressif.com>
2024-07-23 17:38:44 +00:00
Björn Quentin
1424f2a43d
Implement InterruptConfigurable (#1819)
* Implement `InterruptConfigurable`

* Fix doc-tests

* Clippy

* Fix lp_core_uart example

* CHANGELOG.md

* Have DEFAULT_INTERRUPT_HANDLER

* Fix docs

* Clippy

* Add `set_interrupt_handler` for WDT
2024-07-18 13:37:46 +00:00
Juraj Sadel
bc7c53f668
esp-hal: Remove duplicated branch in ESP32 PSRAM (#1830) 2024-07-18 11:22:46 +00:00
Björn Quentin
917756a7bf
Prettier panic message printing (#1823)
* Prettier panic message printing

* CHANGELOG.md
2024-07-18 09:32:53 +00:00
Jesse Braham
776f34cff1
Re-export the esp_hal_procmacros::main macro from esp-hal-embassy instead of esp-hal (#1828)
* Re-export the `main` procmacro from `esp-hal-embassy` rather than `esp-hal`

* Fix documentation warnings

* Flatten the `time_driver` module

* clippy

* Update `CHANGELOG.md`
2024-07-18 09:31:03 +00:00
dimpolo
02c99786f9
esp-backtrace: Add custom-pre-backtrace feature (#1822) 2024-07-18 07:38:40 +00:00
dimpolo
0eb30c5286
make esp_println::Printer::write_bytes public again (#1812) 2024-07-18 06:16:46 +00:00
Sergio Gasquez Arcos
32be53d618
CI Improvements - Part 1 (#1821)
* ci: Fix condition to erase-flash

See https://docs.github.com/en/actions/learn-github-actions/expressions#example-of-failure-with-conditions

* ci: Remove path-ignore attributes to avoid CI not being triggered

* ci: Build documentation

* ci: Install nightly toolchain

* ci: Deny warnings for building docs

* fix: Documentation warnings

* ci: Remove duplicated step
2024-07-17 15:55:27 +00:00
Björn Quentin
2c8bb07be2
Prepare esp-wifi 0.7.1 (#1820)
* Prepare esp-wifi 0.7.1

* CHANGELOG.md
2024-07-17 10:57:15 +00:00
Juraj Sadel
884db5aa32
esp-hal: Add (where missing) used GPIOs to example descriptions (#1810)
* esp-hal: Add (where missing) used GPIOs to example descriptions

* review comments
2024-07-17 08:34:13 +00:00
Jesse Braham
e33b060734
Add xtensa-lx and xtensa-lx-rt packages (#1813)
* Add the `xtensa-lx` package

* Add the `xtensa-lx-rt` and `xtensa-lx-rt-proc-macros` packages

* Exclude new packages from workspace, add to `xtask::Package`

* rustfmt

* clippy
2024-07-17 08:32:52 +00:00
Kirill Mikhailov
14baad4625
Remove raw addresses usage (part 1) (#1795) 2024-07-16 14:11:05 +00:00
Björn Quentin
37299237cb
esp-wifi: Check no password given for AuthMethod::None (#1806)
* esp-wifi: Check no password given for AuthMethod::None

* CHANGELOG.md
2024-07-16 13:46:22 +00:00
Scott Mabin
04cad71926
bump esp-backtrace to 0.13.0 (#1804)
* bump esp-backtrace to 0.13.0

* disable spi_half_duplex_write for esp32s2
2024-07-16 13:19:16 +00:00
Dominic Fischer
31a135c0f1
Add SPI Half Duplex Write HIL test (#1801)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-16 10:19:16 +00:00
Dominic Fischer
6fd9443c13
Allow users to easily name DMA channels (#1771)
* Introduce public DmaChannel trait

* Use DmaChannel trait in all peripherals

* Simplify ChannelTypes trait

* changelog

* Rename things

* missed a spot

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-16 08:52:48 +00:00
Jesse Braham
af1febfb8c Begin next release cycle 2024-07-15 22:56:31 +00:00
Jesse Braham
eddcb7354f
Actually bump the esp-hal version number (oops) (#1802) 2024-07-15 22:17:15 +00:00
Jesse Braham
77b6cb8615
New package releases (#1800)
* Use published versions of all dependencies, update dependencies as needed

* Fix `embassy_usb_serial` example build errors after updating `embassy-usb`

* New package releases
2024-07-15 20:23:13 +00:00
Sergio Gasquez Arcos
7ea471c1ac
Remove unnecessary delay (#1794)
* fix: Remove unnecesary delay

* docs: Update changelog

* fix: Remove unused variable

* fix: Remove clippy warning from examples
2024-07-15 13:09:47 +00:00
liebman
10c900a53f
gpio: DummyPin + hub75_i8080 example (#1769)
* gpio: DummyPin + hub75_i8080 example

* changelog

* cmall cleanup in the example

* reduce memory usage by 50% by using i8080 pixel clock

* updated to latest git hal version

* remove complex hub75 example

* remove complex hub75 example dep
2024-07-15 12:39:14 +00:00
liebman
1631f22083
support dma chunk sizes other than 4092 (#1758)
* support dma chunk sizes other than 4092

* fmt

* update CHANGELOG

* fix 0 size static assert

* review changes:
- `.div_ceil()`
- return errors for bad chunk size and buffer sizes in Mem2Mem constructors
- correct 0 chunk size check in descripter macros

* dma: clear the mem2mem bit when channel is configured instead of in Drop
2024-07-15 12:00:33 +00:00
Björn Quentin
7e981a5376
Fix reading/writing small buffers (#1760)
* Fix reading/writing small buffers

* CHANGELOG.md
2024-07-15 11:06:03 +00:00
Juraj Sadel
45c8107ecd
esp-hal: remove warnings in PCNT example and HIL test (#1793) 2024-07-15 10:49:39 +00:00
Dominic Fischer
0cae79b4cc
Improve PCNT API (with HIL tests) (#1765)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-15 09:31:35 +00:00
Jesse Braham
0363169084
Remove unnecessary build dependency from esp-backtrace (#1788) 2024-07-12 15:07:37 +00:00
Jesse Braham
bc74e2bb61
Add additional public functions to esp-lp-hal for Delay and UART, deny missing documentation (#1789)
* Add `Delay.delay_millis` function

* Provide basic UART functionality without requiring `embedded-hal`/`embedded-io` traits

* Deny missing documentation

* Update `CHANGELOG.md`
2024-07-12 14:56:34 +00:00
Sergio Gasquez Arcos
7e9f9c7528
Update module documentation - Part 2 (#1777)
* docs: Update assist debug mod documentation

* docs: Update delay  mod documentation

* docs: Update ecc  mod documentation

* docs: Update hmac mod documentation

* docs: Update i2c mod documentation

* docs: Update i2s mod documentation

* docs: Update usb otg mod documentation

* docs: Update parl_io mod documentation

* docs: Update peripheral mod documentation

* docs: Update prelude mod documentation

* docs: Update reset mod documentation

* docs: Update rmt mod documentation

* docs: Update rng mod documentation

* docs: Update sha mod documentation

* docs: Update system, time and trace mod documentation

* docs: Update uart mod documentation

* docs: Update usb_serial_jtag mod documentation

* docs: Add modules documentation format

* docs: Address feedback

* style: Format documentation
2024-07-12 09:48:45 +00:00
Jesse Braham
dcc6c896de
Housekeeping: fix warnings, rename some examples, etc. (#1786)
* Build HIL tests for ESP32 in CI, fix resulting build errors

* Fix some warnings in the `hil-test` package

* Fix warnings in examples

* Remove "esp_" prefix from Wi-Fi example file names

* Resolve the last of the known warnings
2024-07-12 09:35:55 +00:00
Dominic Fischer
bb8660d3c5
Add SPI Half Duplex Read HIL test (#1782)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-11 12:55:59 +00:00
Scott Mabin
6c3ccb6043
Add read_bytes method to uart (#1784)
* Add read_bytes method to uart

* Changelog
2024-07-11 12:55:42 +00:00
W Etheredge
a2883ac318
Take 2 on #[ram] soundness (#1677)
* Improve `#[ram]` soundness

* Allow `Atomic*` in `#[ram(persistent)]`

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-07-10 13:30:48 +00:00
Jesse Braham
2bef914e7c
Update and improve esp-lp-hal (#1754)
* Fix warning in `esp-hal-procmacros` when building for `esp-lp-hal`

* Document cargo features, use `embedded-hal@1.x.x` by default

* Derive more traits on public types, assorted cleanup and improvements

* Implement `embedded-hal-nb` and `embedded-io` traits for UART

* Update `CHANGELOG.md`

* Silence `clippy` for now...

* Module documentation for UART

* Update module documentation format
2024-07-09 17:06:54 +00:00
Jesse Braham
eb9bfd52b1
Fix clippy warning in esp-wifi, remove Cargo patch and update semihosting dependency (#1778)
* Update `semihosting` dependency and remove Cargo patch

* Fix clippy error in `esp-wifi`
2024-07-09 09:50:09 -07:00
Björn Quentin
a5be31fadc
Improve and use timer abstractions (#1753)
* Make esp-wifi timer agnostic

* Use timer-abstractions in embassy time driver

* Refactor

* Fix

* Fix

* Docs

* Adapt examples

* Adapt tests

* Refactoring

* Changelogs

* Fix example

* Adapt xtask

* Make CI pass

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-07-09 15:59:38 +00:00
Sergio Gasquez Arcos
8e0a2012dc
Update module documentation (#1763)
* docs: Update GPIO docs

* docs: Update other GPIO modules docs

* docs: Update AES mod documentation

* docs: Update Analog and ADC mod documentation

* docs: Update DAC mod documentation

* docs: Update lib docs

* docs: Update clock  mod documentation

* docs: Update dma  mod documentation

* docs: Update interrupt  mod documentation

* docs: Update lcd_cam  mod documentation

* docs: Update ledc  mod documentation

* docs: Update mcpwm mod documentation

* docs: Update pcnt mod documentation

* docs: Update rom mod documentation

* docs: Update rsa mod documentation

* docs: Update rtc_cntl mod documentation

* docs: Update spi mod documentation

* docs: Update timer mod documentation

* docs: Update twai mod documentation

* docs: Format headers

* style: Fix fmt

* refactor: Change visibility instead of hidding docs

* style: Fix header

* Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* Fix typo

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

* docs: Add tracking issue

* docs: Remove architecture and simplify sentence

* fix: Update visibilities remove hidden docs

* Fix type

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

* docs: Improve wording

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

---------

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-07-09 15:40:31 +00:00
Juraj Sadel
d5b6c850f9
esp-hal: ESP32 typo in cfg-gate in embassy_i2s_read example (#1775) 2024-07-09 13:48:08 +00:00
Scott Mabin
e75d43d3f0
Fix new clippy lints introduced in 1.78 & 1.79 (#1776)
* Fix new clippy lints introduced in 1.78 & 1.79

* Patch semihosting
2024-07-09 13:23:19 +00:00
Kirill Mikhailov
eb54168228
Update CONTRIBUTING.md (#1311) 2024-07-09 14:37:44 +02:00
Grant Moyer
dfe628c53d
Fix UsbDm and UsbDp for Gpio19 and Gpio20 (#1764)
GPIO pins 19 and 20 had USB D- and D+ swapped. This change fixes which pin is which USB data line according to the pin descriptions in the ESP32-S2 and ESP32-S3 data sheets (sections 2.2 and 2.3.2 respectively). Since these GpioPins are only used by Usb for lifetime tracking, and UsbDp and UsbDm are always used as a pair, this change is only semantic and doesn't affect functionality.
2024-07-08 13:37:57 +00:00
Kirill Mikhailov
253b013c2a run-doc-test README entry 2024-07-08 13:34:09 +00:00
Sergio Gasquez Arcos
ea34196d8d
Properly update the Uart config in examples (#1759)
* fix: Properly update the config

* feat: Make rx_timeout optional

* docs: Update changelog
2024-07-08 09:30:45 +00:00
Jesse Braham
967c478846 Update CHANGELOG.md 2024-07-05 13:09:09 +00:00
Jesse Braham
bb4321838e Prevent multiple versions of esp-println from being included in the dependency tree 2024-07-05 13:09:09 +00:00
Nathan Henrie
dc4ddcb3fe
Fix broken link to embassy book (#1756) 2024-07-05 08:27:00 +00:00
Kirill Mikhailov
163f45076e
Enable i2s HIL test for esp32h2 (#1755)
Delete invalid comment
2024-07-04 15:28:37 +00:00
Jonas Spinner
c4ad9d37ab Fix docs.rs link in esp-wifi/README.md 2024-07-04 12:37:52 +00:00
Kirill Mikhailov
921ecc4d56
Feature: correct TRNG mechanism (#1538)
* interstate

* Use type-state over creating new struct

* Getting revert_trng function into the driver

* Finish revert functions

* More progress

* Adjust for new driver release

* Small fixes

fmt

* Fmt + clippy + changelog

* Comments, `RngCore` trait for `Trng`

* fmt

* Make ADC work correctly on TRNG drop, PAC functions instead of raw regs

* Get docs buildable

rustfmt

* Doc comments fix

fmt

* Fix docs for esp32

* Small fixes + exclude `downgrade` and `drop` for `esp32c6`

Downgrade for `esp32c6` is not implemented so far

* TRNG/ADC on `esp32c6` warning comment
2024-07-04 09:03:53 +00:00
Sergio Gasquez Arcos
786682c0b2
HIL: Erase flash on failure (#1748)
* ci: Erase flash on failure

* docs: Add espflash install instructions and fix format
2024-07-04 07:50:40 +00:00
Dominic Fischer
c62bd8b332
Add PCNT HIL test (#1746)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-04 06:23:14 +00:00
liebman
cc7077624c
dma: add Mem2Mem to support memory to memory transfer (#1738)
* dma: add Mem2Mem to support memory to memory transfer

* fmt

* update CHANGELOG

* removed some debugging

* use "gdma" as the selector for support

* fix empty else

* clippy

* Mem2Mem::new now accepts the peripheral to use

* mark Mem2Mem::new() unsafe

* fmt :-/

* add Mem2MemN values for gdma on non-esp32s3
tested on esp32c3,esp32c6 (will have an esp32h2 in a few days)

* support the esp32c2 (esp8684)

* DmaEligible trait providing dma peripheral value & safe constructor for Mem2Mem dma.

* added hil-test for Mem2Mem

* fmt dma_mem2mem test

* remove `debug!()`

* reset the mem2mem bit (mem_trans_en) in in_conf0 on drop
2024-07-03 17:56:37 +00:00
Björn Quentin
4f9dc960c6
Improve xtensa interrupt latency (#1735)
* Avoid U128

* Avoid unnecessary calls

* CHANGELOG.md

* Simplify

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-07-03 15:43:01 +00:00
Kirill Mikhailov
cd0272ee81 Make links be in the same format 2024-07-03 12:53:17 +02:00
Kirill Mikhailov
f177b945b7 docs: Add missing link to HIL README 2024-07-03 12:53:17 +02:00
Björn Quentin
63ef16fae6
Fix set_protocol (#1742)
* Fix `set_protocol`

* CHANGELOG.md

* Clippy
2024-07-03 08:16:00 +00:00
Björn Quentin
cc08da2ad8
Improve the top level crate documentation (#1733)
* Improve the top level crate documentation

* More detailed PeripheralRef explanation
2024-07-03 07:37:33 +00:00
Dominic Fischer
fc826caf18
Expose optional HSYNC input in LCD_CAM (#1707)
* Expose optional HSYNC input in LCD_CAM

* Fix DMA wait check in LCD_CAM

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-07-02 16:56:53 +00:00
Kirill Mikhailov
bdd3e93de2
Fix regi2c_* functions for esp32h2 (#1737)
* Fix `regi2c_*` functions for `esp32h2`

* Changelog entry
2024-07-01 13:26:10 +00:00
Björn Quentin
40810a5c1d
Add UART wakeup source (#1727)
* Add UART wakeup source

* CHANGELOG.md
2024-07-01 06:43:36 +00:00
Sergio Gasquez Arcos
3af45a2ed0
Update changelog CI (#1725)
* docs: Add missing changelogs and unify format

* ci: Check changelog update for all the packages

* ci: Update actions/checkout version
2024-06-28 14:15:01 +00:00
Sergio Gasquez Arcos
60b9d5c704
fix: Update probe-rs arguments for run-elfs subcommand (#1734) 2024-06-28 13:42:30 +00:00
Björn Quentin
8cb921f73b
Add GPIO as wake-up source (#1724)
* Add GPIO as wake-up source

* CHANGELOG.md

* Clippy

* Doc fix
2024-06-28 11:14:29 +00:00
Björn Quentin
347ef5188b
ESP32-C6: Support wake-up from lp-core (#1723)
* ESP32-C6: Add wake from lp-core

* lp-hal PAC update

* Update PAC dependency for lp-hal

* CHANGELOG.md

* CHANGELOG.md

* Clippy
2024-06-28 07:11:31 +00:00
Jesse Braham
4ca2398bc1
Documentation and housekeeping for esp-ieee802154 (#1730)
* Derive more traits on public types

* Document cargo features

* Minor documentation updates, remove an unused struct field
2024-06-28 07:00:15 +00:00
Sergio Gasquez Arcos
d0cd890e51
Update some modules documentation (#1726)
* docs: Add inverting documentation and examples

* docs: Update I2C mod docs

* docs: Update LEDC documentation

* docs: FIx format

* Fix a typo in docstring in `esp-hal/src/uart.rs`

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-06-27 16:50:30 +00:00
Fan Jiang
565faf723b
Fix ESP32-S3 ROM address of ets_update_cpu_frequency_rom (#1722)
Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
2024-06-26 15:59:57 +00:00
Björn Quentin
891d476de1
ESP32-C6: make basic light sleep work (#1720)
* ESP32-C6: make basic light sleep work

* CHANGELOG.md
2024-06-26 15:30:27 +00:00
Dominic Fischer
7753551671
[2/3] DMA Move API: Move DMA descriptors to peripheral drivers (#1719)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-06-26 14:31:41 +00:00
Sergio Gasquez Arcos
e46e80b8c1
Enable C2 HIL (#1680)
* ci: Enable c2 hil

* docs: Update pins and add C2

* feat: Update C2 probe-rs args

* test: Update pins and disable failing tests

* docs: Update S3 wires

* ci: Enable C2 hil tests
2024-06-26 14:17:40 +00:00
Jesse Braham
c9925b7f6d
Don't include dependencies in generated documentation when building with xtask (#1713) 2024-06-26 07:43:25 +00:00
Dominic Fischer
0b5eb1f00e
[1/3] DMA Move API: Pull out driver specific state in DMA driver into separate structs (#1716)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-06-25 13:14:54 +00:00
Dominic Fischer
9d5fb31c4b
TIMG: Fix interrupt handler setup (#1715)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-06-25 13:01:40 +00:00
Alex Vinyals
d4ec063cec
esp-wifi(initialize): no longer requires maximum CPU clock (#1688)
This patch replaces a CPU clock check that enforced running the MCU
at maximum clock speed during WiFi radio initialization. The previous
was incompatible for low power settings.

Now, the check ensures the CPU runs with at *at least* 80MHz, which
is the minimum required clock speed for proper WiFi radio functionality.

For `esp32s3` MCUs, the call to `ets_update_cpu_frequency_rom` has been
moved to the `esp-hal` clocks module. This call is now only made when
configuring CPU to a non-default setting.
2024-06-25 07:42:11 +00:00
Björn Quentin
fd467c2f07
Fix wifi-logs feature (#1709) 2024-06-24 13:45:46 +00:00
Demo for summer'23
c864c8a982
Fix: allow defmt-espflash + auto configuration @ esp-println (#1687)
* esp-println: Fix 'defmt-espflash,auto' feature combination

* formatted according to instructions

* restructure, compiles also on 'esp32'

* Added CI check for compiling with 'dfm-espflash' feature

---------

Co-authored-by: Asko Kauppi <akauppi@gmail.com>
2024-06-24 13:26:08 +00:00
Felix Wirth
9691141fed
implement embedded_io::ReadReady for Uart & UartRx (#1702)
* implement `embedded_io::ReadReady` for `Uart` & `UartRx`

* update CHANGELOG.md
2024-06-21 16:01:40 +00:00
Dominic Fischer
eee20de116
Patch up LCD_CAM example (#1701)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-06-20 13:27:50 +00:00
Björn Quentin
13d6b517d8
Improve RISC-V interrupt latency (#1679)
* Improve RISC-V interrupt latency

* CHANGELOG.md

* Clippy
2024-06-19 16:36:28 +00:00
Dominic Fischer
bb806d35e0
Add remaining GPIO pins for ESP32-S2/S3 ULP (#1695)
Co-authored-by: Dominic Fischer <git@dominicfischer.me>
2024-06-19 15:17:48 +00:00
Sergio Gasquez Arcos
2c03266061
Prepare esp-backtrace@0.12.1 release (#1696)
* build: Bump version

* docs: Update changelog
2024-06-19 14:42:49 +00:00
Björn Quentin
d34a872230
Additional move base dma api (#1672)
* Additional owning DMA transfers for SPI half-duplex

* CHANGELOG.md

* CHANGELOG.md

* Clippy
2024-06-19 13:17:22 +00:00
Björn Quentin
1630868d06
Improve DMA pop implementation (#1664)
* Improve DMA `pop` implementation

* CHANGELOG.md

* Minor Fixes

* Cover more edge-cases in DMA pop, make sure the test is testing these

* Fixes

* Working available/pop

* Remove misleading `last_in_dscr_address`

* Remove unnecessary check from `available`

* Remove now-unused function

* Remove duplicate change-log entry
2024-06-19 12:51:24 +00:00
Jesse Braham
2d90fa3021
Make esp-wifi build when using the defmt feature with +stable toolchain (#1691) 2024-06-18 15:50:46 +00:00
Scott Mabin
0d418fe837
esp-bracktrace: only print float registers on chips that have them (#1690)
* only print float registers on chips that have them

* Add CHANGELOG.md
2024-06-18 15:01:53 +00:00
Kaspar Schleiser
152c0180df
esp-hal-wifi: make executors optional (again) (#1683)
* esp-hal-wifi: make executors optional (again)

* esp-wifi: don't use default-features of `esp-hal-embassy`
2024-06-17 10:23:31 +00:00
Björn Quentin
bd711517f3
esp-backtrace: Fix for nightly after 2024-06-12 (#1681)
* esp-backtrace: Fix for nightly after 2024-06-12

* Fix

* Fix defmt
2024-06-17 08:55:54 +00:00
Björn Quentin
65b956d6a8
Fix mk_static macro (#1674) 2024-06-12 15:09:43 +00:00
Andres O. Vela
05076697ec
Rename PSRAM examples for better discoverability (#1675) 2024-06-12 14:23:55 +00:00
Andres O. Vela
fb90fe780c
esp-hal: fix esp32-s3 psram docs (#1673) 2024-06-12 13:52:50 +00:00
Sergio Gasquez Arcos
e7f8f50e82
Update embedded-tests and wiring docs (#1652)
* build: Update embedded-test

* docs: Update probe-rs version

* docs: Revert probe-rs update

* docs: Update wiring

* docs: Update source command
2024-06-12 10:12:04 +00:00
Sergio Gasquez Arcos
d2a93894f5
feat: Avoid using a macro for default pins (#1671) 2024-06-11 15:49:44 +00:00
Björn Quentin
1122df15e2
Check DMA descriptors and buffers addresses (#1670)
* Check DMA descriptors and buffers addresses

* Add PR id

* Add test for the memory region check

* Clippy
2024-06-11 14:42:46 +00:00
Sergio Gasquez Arcos
a33159a021
Rework Uart constructors, add UartTx and UartRx constuctors. (#1592)
* feat: Add with_pins methods for UART

* feat: Remove configure_pin methods

* docs: Update changelog

* fix: Update tests and examples

* style: Fix format

* Add UartTx/Rx constructors

* feat: Add new_with_default_pins methods

* docs: Update changelog

* feat: Remove optional cts/rts arguments

* feat: Add UartTx/Rx::new_async methods

* fix: Attach interrupt handler to new_ascyn UartRx/Tx

* style: Avoid long module paths

* feat: Make flush_tx public

* test: Use Uart async instead of UartTx/Rx async

* test: Add tests for UartTx/UartRx

* feat: Add configuration method to constuctors

* feat: Move set_rx_fifo_full_threshold and set_rx_timeout to UartRx

* docs: Fix changelog

* test: Fix executor

* feat: Configure UartRx threshold and timeout

* docs: Update changelog

* test: Update uart instance

* feat: Add default_uart0_pins macro to simplify examples

* feat: Address feedback pt1

* feat: Address feedback pt2 - Make constructors fallible

* fix: Doctest
2024-06-11 13:07:17 +00:00
Juraj Sadel
4c5e493b1b
esp-hal: Add runnable doctests to peripheral drivers (#1663)
* Check docs examples II

* rebase and update

* fix root crate macro expansion in doctest snippets

* clean up and fmt

* add xtask run-doc-test subcommand and check in CI

* address review comments

* remove commented printlns

* fix the host target check

* rebase and update

* hide docs for before_snippet macro and remove commented block code in twai
2024-06-11 10:18:09 +00:00
Björn Quentin
b8af24071e
Add Flex/AnyFlex pin drivers (#1659)
* Add Flex/AnyFlex pin drivers

* CHANGELOG.md
2024-06-10 15:23:55 +00:00
Jesse Braham
dc8e0a6496
Refactor Dac1/Dac2 drivers into a single Dac driver (#1661)
* Refactor `Dac1`/`Dac2` drivers into a single `Dac` driver

* Fix unrelated build errors resulting from updated PACs

* Add new `Instance` trait to `prelude` module, update `dac` example

* Update `CHANGELOG.md`

* Fix example in module documentation

* Turns out these are 0-indexed after all
2024-06-10 13:52:00 +00:00
Björn Quentin
fd4676d434
Add RMT hil-test (#1665)
* Add RMT hil-test

* Fix compilation error on ESP32/ESP32-S2
2024-06-07 10:31:42 +00:00
Björn Quentin
e680900f50
esp-backtrace: Fix warning when using semihosting feature (#1667) 2024-06-07 09:49:59 +00:00
Dominic Fischer
a20054c90c
Fix misuse of INT_CLR (#1651)
* Fix misuse of INT_CLR

* Use LCD_START instead of interrupt to check for completion
2024-06-05 13:40:55 +00:00
Björn Quentin
f125c20cf2
Add auto-detection feature to esp-println (#1658)
* Add auto-detection feature to esp-println

* CHANGELOG.md

* Minor README change

* Build `esp-println` in CI
2024-06-05 10:44:17 +00:00
Jesse Braham
8a47e4254f Begin next release cycle 2024-06-04 16:48:59 +00:00
Jesse Braham
e50f663842
New package releases (#1654)
* Bump dependencies and version numbers of packages to be published

* Update relevant `CHANGELOG.md` files
2024-06-04 16:11:42 +00:00
Jesse Braham
ebcd26fd51
Update xtask to support generating documentation for multiple packages (#1653)
* Update `xtask` dependencies

* Update `xtask` to support generating documentation for multiple chips

* Update CI and Documentation workflows

* Fix minor mistake in documentation index template
2024-06-04 15:27:41 +00:00
Jesse Braham
48e3e912f3
Extract embassy support into esp-hal-embassy package (#1595)
* Extract embassy support into `esp-hal-embassy` package

* Update relevant packages/examples/tests to get CI green again

* Add back `defmt` support

* Re-export `Executor` and `InterruptExecutor` rather than making `executor` module public

* Document the `esp-hal-embassy` package

* Update `CHANGELOG.md`

* Hack together a "fix" for the `SYSTIMER` time driver

* Make `clippy` shut up
2024-06-03 11:27:20 +00:00
Björn Quentin
cb91828e5e
Fix DMA related doc-links (#1648) 2024-05-31 14:22:18 +00:00
Jesse Braham
40c327eeae
Housekeeping (#1647)
* Remove version from path dependencies in `examples` and `hil-test` packages

* Remove unused constant from `esp-println`

* Consistent badges across `README.md` files
2024-05-31 13:58:54 +00:00
Jesse Braham
2fd1594637
Fix feeding of RWDT (#1645)
* Fix feeding of `RWDT`

* Update `CHANGELOG.md`
2024-05-31 08:02:15 +00:00
Scott Mabin
4d9441ef99
Enable the CI feature to check more features in MSRV checks (#1641)
* enable the CI feature to check more features in MSRV checks

* Rename eh1 feature in esp-lp-hal
2024-05-30 14:22:03 +00:00
Scott Mabin
4dbe5d35a6
Build the extras/ crates in CI (#1640) 2024-05-30 13:07:40 +00:00
Björn Quentin
83dfb5b803
Add IEEE802.15.4 Wireshark Extcap (#1636) 2024-05-29 14:04:44 +00:00
Björn Quentin
79d617da38
Add I2S HIL test (#1635)
* Add I2S HIL test

* Disable I2S HIL test for H2

* Disable interrupt latency test for now

* Avoid triggering rustfmt check
2024-05-29 13:56:54 +00:00
Scott Mabin
db39d0197a
Examples and test cleanup (#1590)
* initial cull of examples

* Remove direct vector example, replace with interrupt latency test

* Remove clock monitor in favour of just a test
2024-05-28 18:58:48 +00:00
liebman
06bf505093
esp-wifi: fix unused timer result (#1633) 2024-05-28 16:12:56 +00:00
Jesse Braham
8aee84f842
[3/3] Timer abstraction: cleanup, simplification, and documentation (#1630)
* Add a new `timg_timer1` symbol to `esp-metadata` definitions

* Make `Timer::load_value` fallible (when the value is too large)

* Clean up, simplify, and document the `timer` module and its submodules

* Fix various issues

* Update the timeout value verification for `SYSTIMER`

* Clippy

* Introduce new `PERIOD_MASK` constant for validating timeout values
2024-05-28 14:12:06 +00:00
Björn Quentin
7c25750e3a
Improve xtask on Windows (#1632)
* Improve `xtask` on Windows

* Use already existing `windows_safe_path` function
2024-05-28 13:27:15 +00:00
Björn Quentin
0ad4ee0c91
esp-wifi: Fix clippy issues (#1631)
* Don't activate additional features in esp-hal

* Apply `clippy --fix`

* Clippy

* Clippy

* Clippy

* Clippy

* Enable linting esp-wifi

* Fix

* Fix typo
2024-05-28 12:49:55 +00:00
Jesse Braham
e67d489737
Use published PACs (#1629) 2024-05-28 06:39:42 +00:00
liebman
e446d78410
esp-hal: rmt: make ChannelCreator public (#1597)
* esp-hal: rmt: make ChannelCreator public

* esp-hal: rmt: fmt-packages

* esp-hal: rmt: fix ChannelCreator missing docs for other (non-esp32s3) implementation

* esp-hal: update CHANGELOG

* rmt: ChannelCreator: remove allow(missing_docs)

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-05-27 16:16:54 +00:00
Björn Quentin
60e4b882ef
Add esp-storage to esp-hal repo (#1627)
* Add esp-storage to esp-hal repo

* Include needed feature to lint esp-storage

* Don't lint esp-wifi for now

* Remove redundant copies of license texts

* Try `git-fetch-with-cli`

* Fix esp-pacs URL

* git-fetch-with-cli, again

* desperately trying
2024-05-27 15:28:05 +00:00
Jesse Braham
3b9a4938cb
Add a lint-packages subcommand to xtask, use in CI workflow (#1594)
* Add a subcommand to lint all packages using `clippy`, use in CI

* Address `clippy` warnings
2024-05-24 20:00:04 +00:00
Björn Quentin
06315b8c8c
Add esp wifi to monorepo with history (#1582)
* Move the existing `esp-wifi` package into a directory

* Update READMEs

* Don't prefix the ROM functions linker script with the chip name

* Address a couple comments from review

* Move the `esp-wifi` README back to the root of the repository

* Add esp-now support

* Don't use underscores in feature names

* Smoltcp 0.9 upgrade (#124)

* switch to heapless for SimpleQueue

* Merge Network into WifiStack

- Merge the Network and Wifi structs into WifiStack
- Get it building & running with just TCP socket for now

* get dhcp example building with changes and no warnings

* fixup error checking

* Fix other examples

* fmt

* Remove redundant comment

* fix unused results

* bump BT_INTERNAL_QUEUE to 10

* add back static ip configuration in work()

* Async WiFi (#125)

* Async WiFi with embassy

- Add embassy_net::Driver impl for WifiDevice
- Add embassy_dhcp example
- Update README with embassy_dhcp running instruction

Notes:

TCP connection may fail a few times until the esp gets an IP address, it
seems there is no way to await dhcp completion in embassy_net yet.

* Put embassy-net behind feature

- Whilst other embassy crates can be used behind the async feature,
  embassy-net should be put behind its own feature

* wait for dhcp to complete in example

* fmt

* Simplify embedded-io import

* Update README, use new bleps

* Ensure internal wifi buffers are freed (#128)

Regardless of whether we can do anything with the incoming packets, we
*must* ensure the drivers packet memory is free.

* Async WiFi: connect/disconnect/scan/wait_for_event (#129)

* Add async scan_n()

* WifiFuture and async connect

- Don't compile the blocking `WifiStack` when using the embassy-net
  feature
- Improve WifiEventFuture to have a waker for each WifiEvent
- Stub out async versions of embedded-svc trait

* Add async start/stop/connect

- All works first time
  - Fails on reconnect, but this is a bug in the svc implementation
- Implements `IntoFuture` for `WifiEvent`
  - Is it possible to await the event in two seperate futures? or will
    one overwrite the other?

* Async connect/disconnect

- Now working in fully async fashion
- Improved embedded-svc `Wifi` trait impl
  - is_started etc still needs work
- spotted memory leak when not transmitting anything

* Fix async start

Can now succesfully reconnect to a network

* Fix `is_started`

Closes https://github.com/esp-rs/esp-wifi/issues/126

* link state waker

* Only wake the transmit waker if we have something to send

* Correct WifiEventFuture

Instead of relying on the current state, it now tracks events and clears
the event before trying to listen.

* wifi: split into device and controller

- Split the wifi into two parts, the device part which is used within the
network stack and the controller, which handles the wifi connection
parts

- Remove the uneeded `Wifi` impl now that the two parts are separate

* undo cfg of blocking stack

* small fixups

* controller: add `wait_for_event`

- This solves the waker overwrite issue, as the function takes `&mut
  self`, meaning its only possible to await for the same event once.
- Sadly this means we have to remove the really clean `into_future` impl
  :(, but atleast we don't have to bump MSRV.

* Fix examples

* fmt

* make globals pub(crate)

* make all events awaitable

- Add wakers for all events
- Add some docs
- Make WifiEventFuture pub(crate)

* fix esp-now

* Add basic AP support (#134)

* Add basic AP support

* Remove IS_AP global static

* Remove uneeded features from examples and esp-wifi (#135)

* Adjust for latest HAL (#139)

* Adjust for latest HAL

* ESP32-S3 adjustments needed after update

* Use ESP32-C2 HAL 0.5.1

* ESP32-C6 WiFi support (#142)

* ESP32-C6 WiFi support

* Explain the `run_after_initialze_hack` function

* ESP32-C6 cleanup (#148)

* Use ESP_HAL to read mac address (#149)

* Refactor examples (#146)

* Move some boilerplate code into own examples-util crate

* Have an `examples-esp32XXX` folder for each target

* Cleanup dependencies

* Use workspace dependencies

* Adjust CI workflow

* `cd` into the right directories

* Don't pass chip selection features for examples

* Fix ESP32-C6 CI

* Refactor Socket::write to prevent infinite loop on long writes (#151)

* Use HAL's radio clock control (#153)

* Feature/radio singletons (#141)

* Use RADIO singletons

- Uses the RADIO singletons when creating wifi/ble/esp_now
- Updates all examples to use the singletons
- Simplfy esp_now::ReceiveFuture

* Fixup examples

* fmt

* fix examples

* Feature "big-heap", fix `calloc` (#155)

* Use types from `core::ffi::` (#159)

* Add wifi_set_mode for Wifi Protocol Support (#156)

* Add set_mode

* Revert unnecessary changes

* Review changes

* Removed unecessary change

* Review changes, merge conflict fix

* Add missing ROM functions for ESP32-S3/ESP32-S2 (#160)

* Add missing ROM functions for ESP32-S3/ESP32-S2

* Cut down nocoex + big-heap heap-size

* Async ble (#161)

* Async BLE HCI

* Add async-ble example

* Use nightly-2023-03-09 for CI (for now)

* Use a more sane default MTU, have features to change MTU (#164)

* Improve packet dumps (#165)

* packet-dump dumps the raw packets

* Update README, serialport config in wifishark

* Update embassy (#166)

* chore: update embassy's executor rev sync to 0.2

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix: examples - enable features for different example architectures

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix: examples riscv executor feature name

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* chore: update embassy-net & net-driver

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix - Cargo - on wifi, enable the embedded-svc feature

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix - config.toml - enable target atomic operations

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix: rustflags for atomic operations

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* fix: esp32s2 example - fix target cfg

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* chore: update crates & revisions

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* feat: patch to latest revision of esp hal crates

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>

* Adapt to esp-hal changes

* Use published esp-hal, published embassy-executor

---------

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>
Co-authored-by: Lachezar Lechev <elpiel93@gmail.com>

* Fix DHCP handling (#173)

* Don't use DHCP when using fixed IP

* Make it possible to connect to another AP

* A way to update iface-config (#177)

* fix(esp-wifi): Update is_started() implementation (#180)

The old implementation of is_started() returns `Ok(true)` is the sta or ap is enabled, which is true before wifi_start() has been called. This results in the function returning true, before `start()` has been called.

* Basic IPv6 Support

* Don't panic on full BLE receive queue

* Activate embedded-svc with wifi feature

* A way to dequeue a complete HCI packet

* Make ESP32 BLE work again

* preempt improvements (#185)

* [Xtensa] ensure CPU interrupts are re-enabled

Once the scheduler is enabled.

* [Xtensa] preempt: reduce from 2000hz -> 1000hz

This brings the task switching hz inline with the values for the RISCV
chips

* reduce preempt hz to 100 (freertos default)

* remove WIFI_BB interrupt from esp32_timer

* fix typo in timer_esp32s3

* peer_exists now returns bool

* De-duplicate init code

* What to initialize is now a runtime decision

* COEX is now an explicit feature

* Panic when trying to use BLE and WIFI w/o coex

* Improve feature gating of COEX check

* Make it possible to use ESP-NOW with (STA) WiFi

* Simplify async feature, update all examples

* Make timer type alias public

* Less verbose cfgs

* use linkage = 'weak' for missing intrinsic stub (#191)

* Workaround to make ESP32-C2 BLE work again

* Fix ESP32-C2 BLE

* Don't require timg0 as timebase

* ESP32 and ESP32-C2 working

* BLE works on C3 / S3

* Fix COEX for C3 and S3

* Make COEX for ESP32 compile again

* Remove embassy-net dependency

* Update smoltcp, embassy-net, embassy-net-driver

* Return all pending wifi events

* Clear the correct events, clear after polling, simplify scan_n

* Provide specialized futures

* Remove event in future when polling

* Avoid clearing interesting events

* Add DNS query interface to WifiStack (#213)

* feat(dns_query): add dns_query on WifiStack

* ref(dns_query): separate dns socket creation and dns query

* fix(dns_query): missing self parameter in is_dns_configured

* ref(dns_query): configure_dns now replaces and drops the old socket

* feat(dns_query): add proper dns_query error kinds

* feat(dns_query): dns_query now checks if name is already an ip

* feat(dns_query): dns server is set with dhcp configured event

* ref(dns_query): move dns update to configured case

* Update dependencies (#198)

* Clear state on stop (#217)

* fix log_timestamp value (#218)

The divider should be applied only on the TICKS_PER_SECOND, rather than on the whole systimer count, to get the proper value in millis

* Scan related refactorings (#221)

* Clean up scan result processing

* Remove redundant ap count reading

* Fix scan result API returning clipped AP count

* Inline closure

* Don't copy ssid

* Properly set initial config (#223)

* Properly set initial config

* Make new_with_config fallible

* Make EspWifiInitialization non-exhaustive

* Replace panic with error

* Enable wifi/bt power domain (#220)

* Refactor TCP socket read impl to handle correctly EOF and no data (#216)

* ref(tcp_read): tcp read now checks for eof and no data

* ref(tcp_read): SocketClosed is returned instead of Ok(0)

* Configurable tuning parameters (#233)

* Make certain settings configurable

* Add MD documentation

* Update HALs, uncomment commented code in S2 power domain enable (#235)

* Update esp dependencies

* S2: Properly reset radio power domain on enable

* Wait for esp now send callback to be called after sending (#232)

* Make check_error result propagatable with ?

* Wait for esp_now_send callback after sending #229

* Updated examples

* Add more configuration options (#234)

* Add more configuration options

* Remove obsolete mtu feature

* Simplify DEFAULT_HEAP_SIZE

* Make EspNow methods take immutable borrowed self (#237)

* Reduce stack-allocations (#243)

* Reduce stack-allocations

* Avoid explicit panic on exhausted backing memory

* Remove unnecessary `transmute`

* Add defmt::Format to some types (#251)

* use intset intclear now they are recognized by llvm (#248)

* use intset intclear now they are recognized by llvm

* Bump readme MSRV

* Remove comment

* Clean up btdm initialization (#254)

* Make log optional, add feature and macros to route to defmt (#252)

* Debug-print pointers

* Make log dependency optional

* Add Format to Config

* Add defmt log option

* Add panic macro

* Add unwrap macro

* A few DataFrame-related fixes (#257)

* Clean up DataFrame::from_bytes

* Fix potential typo

* Fix potential memory leak

* Clean up

* Only allocate data frame if queue is not full

* Free DataFrame on drop

* Fix warning

* Remove embedded-hal dependency (#258)

* Don't depend on PACs directly (#260)

* Remove DataFrame, Leverage the internal WiFi heap (#259)

* use heap allocated buffers for RX instead of memcpy to Rust

* remove tx queuing, leverage wifi heap again

* Allow sending up to TX_QUEUE size packets, instead of one at a time

* share tx & rx consume impls. move inflight check into function

* defmt related improvements (#255)

* Replace custom macros with fmt.rs

* Fix missing Format errors

* Update Cargo.tomls

* CI: deduplicate, assert that defmt feature compiles

* Update dependencies

* Fix examples

* Implemented duplex ESP-NOW correctly (#240)

* HAL cleanups & remove example macros (#261)

* use Systimer from hal where possible

* Remove RTC and clocks macros in favour of hal primitives

* Remove system! macro

* Remove the timer macro

* remove the radio macros

* Make utils a single file module for remaining util items

* Fix rebase issues

* Remove redundant example, update esp-now examples

* ESP32-C6 BLE Support (#262)

* ESP32-C6 BLE Support

* Reformat

* Docs & README changes for release (#263)

* Make internal functions/structs private where possible

* Top level docs

* Rework README, move examples into own file
* Include README as top level docs in esp-wifi

* Document public items

* Implement floor() using libm (#272)

* Support ps-max-modem (#273)

* Task/semaphore tweaking (#276)

* Query current systick once

* Use pattern matching to clean up task

* Work with references of timer slots

* Unwrap WORKER_HIGH

* Avoid unwrap by using exact length buffer, simplify types

* Log if work is lost

* Move memory fence to the end of the critical section

* Remove redundant cast

* Only reset timer fields once

* Import some types

* Replace manual borrow_mut

* Remove extra loop

* Deduplicate semaphore index calculation

* Use pattern matching instead of unwrap

* Use option instead of separate flag

* Unwrap REAL_WIFI_QUEUE

* Simplify lock_mutex

* Process message outside of critical section

* Remove unnecessary return statement

Co-authored-by: Scott Mabin <scott@mabez.dev>

* Remove unused import

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>

* Avoid AtomicU64 if possible, fix race condition (#278)

* Xtensa: avoid AtomicU64 in get_systimer_count

* Fix get_systimer_count racy behaviour

* Improve code consistency

* Xtensa: Copy TrapFrame in one statement (#279)

* Remove StrBuf (#280)

* Allow using AP when `ps-max-modem` is enabled (#283)

* Set inactive time only for ps-max-modem

* Set inactive time regardless of modem sleep mode

---------

Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de>

* Config for failure_retry_cnt and scan_method (#282)

* Deduplicate SoC/arch-specific task switching related code (#284)

* Clean up imports, refer to crate-relative hal

* Move timer* files to submodule, split out common code

* Deduplicate time-based task switching

* Extract common setup fn

* Fix overflow in timestamp calculation (#287)

* Fix log strings (#292)

* Fix typo in ble feature name (#297)

The `initialize` function checks if wifi and ble are enable simultaneously without coex, but it was mistakenly using `feature = bluetooth` instead of `feature = ble`. This meant the check was actually never compiled in.

* Enable `vsnprintf` on compilers newer than `1.73.0.1` (#293)

* Add compiler version check for VaListImpl support

* Raise log level of puts

* Split wifi state for AP and STA (#288)

* Split wifi state for AP and STA

* Use atomic enum to store state

* Clean up unnecessary unsafe blocks

* Misc. simplifications (#298)

* Hide os_adapter

* Remove global is_connected fn

* Extract state management

* Set mode when creating the controller, extract some fns

* Encapsulate WifiMode a bit better

* Simplify setting addresses to static data

* Only set verbose logging once

* Clean up imports

* Deduplicate wifi auth method conversion

* Clean up powersave mode setup

* Remove unnecessary condition

* Explain transmute

* Misc small readability improvements

* Remove unnecessary conversion

* Prepare waiting for multiple interfaces to start and stop

* Pull up wifi interface to caller

* Remove unnecessary binding

* Don't log warnings twice

* Simplify dump_packet

* Explain default config in constructor

* Remove always-panicking new

* Elide lifetime

* Fix sometimes-unused import

* Implement gettimeofday and __assert_func (#304)

* Implement gettimeofday

* Implement __assert_func

* Reimplement log_timestamp

* Configure burst size on async Device, allow 0 as no maximum (#308)

* Set burst size for async Driver

* Use 0 to indicate no max burst size

* Remove unused import (#310)

* Prevent some leaks & a bit of cleanup (#306)

* Decrease inflight counter if internal tx fails

* Clean up recv_cb

* Avoid leaking AP list when scan is cancelled

* Also register transmit waker when calling receive

* Shorten unsafe block

* Explain and reuse FreeApListOnDrop, split up unsafe block

* Block until mutex can be locked (#318)

* Block until mutex is locked

* Don't drop EspWifiPacketBuffer in a critical section

* Misc small changes (#312)

* Set levels to trace, unify some stuff, implement int disable

* Remove unnecessary paths

* Only check once if random is set, copy impl from esp-hal

* Avoid matching on constant

* Print current time in same line as other arming params

* Simplify tick <-> time conversions

* Work around espflash resolving timer addresses

* Raise compat_timer_setfn level to debug

* Resolve warnings

* Fix malloc pointer mutability

* Simplify import

* Resolve commented question

* Clean up a bunch of timer code, use `heapless::Vec` instead of array of options (#313)

* Fix early timeout when counter overflows

* Store the correct fn pointer type

* Remove wrapper around ets timer functions

* Sort out timer: ets_timer, other pointer types

* Use heapless::Vec to store timers

* Fix and clean up npl

* Fix hal_uart_init_cbs signature

* Queue fixes and cleanups, work queue `->` task spawn (#316)

* Clean up imports

* Clean up queue operations

* Clean up task spawning and running

* Move syslog out of common, implement `%ll{u,d}` (#317)

* Move syslog out of common

* Handle escaped percent sign (%%)

* Handle long longs

* Make sure the scheduling won't start before everything is setup (#324)

* Add some config validations from esp-idf (#325)

* Added support for Wifi scan options (#302)

* I added support for wifi options

* Implement a lot of suggestions

* Update esp-wifi/src/wifi/mod.rs

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* Refactor

* Make it a little more prettier

* Add more documentation

* Update esp-wifi/src/wifi/mod.rs

Co-authored-by: Dániel Buga <bugadani@gmail.com>

---------

Co-authored-by: Dániel Buga <bugadani@gmail.com>

* Replace a panic with a compile error (#321)

* Fix fn pointer signatures

* Clean up scoping a bit

* Simplify clock validation

* Make WifiBle option only available when coex is enabled

* Check for wifi and ble if coex is enabled

* Simplify BTDM osi funcs setup

* Xtensa: Set up time slice before switching task, tweak tick rate (#323)

* Set up time slice before switching task

* Make timer code a bit more obvious

* Divide clock cycles by a multiple of 8

* Unify examples (#296)

This PR merges the chip specific examples into one folder, inside the
esp-wifi project.

To simplify building, alias' have been added to
`esp-wifi/.cargo/config.toml` per chip to automatically select the right
target and enable the chip feature.

Add build script detection for invalid features

Fix CI, use build instead of check to detect linker errors

enable async feature of hal, this breaks because of interrupt definition for systimer

upgrade hal rev

upgrade hal rev c6

undo binding modifications

fix esp now

fix esp coex

use released hals, update async examples

sync example names

sync example names

Update examples.md

Document alias

update build alias

* Add a benchmarking example for blocking and async (#328)

* Unify examples

This PR merges the chip specific examples into one folder, inside the
esp-wifi project.

To simplify building, alias' have been added to
`esp-wifi/.cargo/config.toml` per chip to automatically select the right
target and enable the chip feature.

Add build script detection for invalid features

Fix CI, use build instead of check to detect linker errors

enable async feature of hal, this breaks because of interrupt definition for systimer

upgrade hal rev

upgrade hal rev c6

undo binding modifications

fix esp now

fix esp coex

use released hals, update async examples

sync example names

sync example names

Update examples.md

Document alias

update build alias

* Add bench server

* Add bench example

* Add async bench example

* Add bench example to ci

* fmt

* fix CI

* Document bench example

* Use embassy-net 0.2 (#289)

Co-authored-by: Hailey Somerville <hailey@hailey.lol>

* Clean up examples a bit (#332)

* Revise API docs (#330)

* Revise API docs

* Rephrase description of `WifiStack`

* Formatting

* Simplify multitasking (#334)

* AP-STA mode (#299)

* Configure AP-STA mode

* Split up link state waking into two branches

* Add WifiMode::ApSta

* Simplify mode setup

* Deduce wifi mode from config if available

* Rework internals to support AP-STA mode

* Add `new_ap_sta` constructor

* Demote Rx token warning

* Allow using is_sta_enabled and is_ap_enabled

* Disallow certain config changes

* Update readme

* Return capability based on configuration

* Add a default-config constructor for AP-STA

* Shorten unsafe block

* Typestate devices

* Add examples

* Use CCMP instead of TKIP (#338)

* Add basic automated tests (#339)

* Don't enable default features for esp*-hal (#303)

* Add support coex for ESP32C6 (#327)

* Rebase main branch and support coex for esp32c6

* Revert default value of tx_queue_size and add coex feature for esp32c6

* Fixed the formatting issue

* Add features to disable various network protocols (#340)

* Add features for various network protocols

Disable smoltcp if none of them is enabled, as well.  Restructure the
cargo features to make this possible: utils isn't needed unless one of
the protocols is on, but embedded-svc is needed even for sending and
receiving raw frames.

In order to do the latter, we also need a receive and transmit method on
the WifiDevice, rather than using the methods on the smoltcp Device impl
-- and we don't need to give them an Instant.  Copy the implementation.

* Add all combinations of network features to CI

* Document new features

Also fix up a couple references in old ones.

* Tolerate leading v in version string (#348)

* Tolerate leading v in version string

* Pin executor

* Esp32c2 coex (#347)

* Support COEX on ESP32-C2

* Fix script

* Remove WiFi scan from COEX example

* Don't crash on unexpected version string format (#358)

* Prepare release (#343)

* Prepare first release

* Always enable `async` for `bleps`

* Remove obsolete patch

* Fix README.md include (#359)

* Fix README.md include

* Fix links

* add "scan_with_config" method to sync WifiController, like for async (#350)

* add "scan_with_config" method to sync WifiController, like for async

* rename to "scan_with_config_sync", unsure why "scan_n" is fine lol

* Reliably avoid `r_ble_hci_ram_hs_cmd_tx` assert (#362)

* Remove recommendation against LTO (#363)

* Fix broken links (#364)

* Remove embedded-svc feature (#366)

* Make COEX work on ESP-32 (#349)

* Remove big-heap (#367)

* Remove big-heap feature

* Implement get_free_heap_size

* Don't require smoltcp as a dev dependency (#365)

* Don't require smoltcp as a dev dependency

* Document the smoltcp feature

* Some feature/README-related cleanup (#368)

* Clean up embedded-svc feature remnants

* Improve serial jtag section

* Improve feature descriptions

* Label ESP32 COEX as supported (#369)

* Exclude 1.74.0.0 from xtensa vaarg supported compilers (#372)

* Update dependencies, port to portable-atomic (#342)

* Update dependencies, port to portable-atomic

* Drop futures-*

* Add patches

* Make portable-atomic optional

* Don't depend on smoltcp and embedded-svc releases

* Update esp-hal to disallow duplicate versions

* Backtrack on the S2 changes

* Remove features from cargo run aliasses

* Update esp-hal, always use portable-atomic

* H2: Add BLE support (#352)

* H2: Add BLE support

* fix ci

* fix ci 2

* Add H2 into test scripts

* update to latest changes

* revert smoltcp change

* Update smoketest.bat

Co-authored-by: Scott Mabin <scott@mabez.dev>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>

* Update current support (#381)

* docs: Update current support

* docs: Fix format and typos

* docs: Fix typo (#382)

* Bump esp-hal versions, patch embassy-net (#386)

* Bump esp-hal versions, patch embassy-net

* Make bench.rs example compile again

* Patch all the embassy-* dependencies

* Avoid overwriting HCI buffer until sent (#398)

* Avoid overwriting HCI buffer until sent

* Fix formatting

* move set_isr to chip_specific (#390)

* Reset DHCP socket when the link up is detected (#401)

* Use embassy-net-driver only is esp-wifi, make enet a dev dep (#402)

Also bump enet to 0.3

* Prepare release 0.2.0 (#403)

* Bump version to 0.2.0

* Fix warnings

* Small correction to coex warning message (#404)

* Include coex in list of enabled features for docs.rs (#405)

* Update driver blobs (#410)

* Update driver blobs

* Update README.md

* Don't build embassy-bench for S2 in CI

* Don't build embassy-bench for S2 in CI

* fix(#383): Use a random local port when initializing the wifi stack. (#414)

* Add minimal amount of default features, and instead enable the previously default features only for examples (#420)

* Update everything to use latest `esp-hal` and `embedded-hal-async 1.0.0`, smoltcp to `0.11.0` (#417)

* Update everything to use latest esp-hal

* Change to upstream as PR is merged

* Remove hard dep on backtrace

* Add required feature for heapless

* Update examples

* Update

* update rev

* Remove patches to crates as they are released

* Remove last patch as  is released

* Update changelog

* Prepare release 0.3.0 (#424)

* Bump esp-wifi-sys

* Fix code warning

* Fix test script

* Bump esp-wifi

* Prepare CHANGELOG.md for next release cycle

* Remove "no token" warnings. (#428)

They happen often in normal use, such as downloading/uploading a big file
as fast as possible, and they tank performance if logging is enabled.

* Make embedded svc really optional (#429)

* Make embedded-svc really optional

* Update README.md

* CHANGELOG.md entry

* Performance improvement (#430)

* Improve response times

* Revert "Improve response times"

This reverts commit 77c437a252c8accd4e52b228752c03019b50b60b.

* Fix embassy_bench

* Yield from tx_token/rx_token if no progress can be made otherwise

* CHANGELOG.md entry

---------

Co-authored-by: Karl Rikte <karl.rikte@gmail.com>

* Instead of duplicating the config, we now use const eval to validate the config (#432)

* Update esp-hal etc. (#434)

* Update esp-hal etc.

* Adapt build-aliases

* Fix workflow

* Use published HAL

* Use esp-hal `0.16.1`

* CHANGELOG.md entry

* Prepare release 0.4.0 (#439)

* Fix a compile error when smoltcp can return more than 1 DNS result (#442)

Update the WifiStack::dns_query() return type to match the type returned
by smoltcp, rather than assuming the result size is always 1.

* update for changes in latest esp-hal git (#449)

* Use esp-hal 0.17.0 (#456)

* Bump version, CHANGELOG.md (#458)

* Prepare CHANGELOG.md for next release cycle (#459)

* Prepare CHANGELOG.md for next release cycle

* Fix docs-rs build

* Bump to 0.5.1, make sure docs will build (#462)

* Remove direct embedded-hal v0.2 dependency (#466)

* Remove direct embedded-hal v0.2 dependency

* Add changelog entry.

* Adapt esp-wifi for current HAL

* Move examples to example folder

* Remove dev-dependencies from esp-wifi

* Add bench-server etc.

* Update links in README.md

* Remove useless patch

* Compilable on stable

* Set env-vars used in esp-wifi examples

* Set env-vars used in esp-wifi examples

* Use `esp-build`

* Don't use esp_build::warning

* Fixes after re-checking examples

* Fix workflow file

* Fixes

* Make examples build on stable

* Exclude some examples from H2/S2

* Address review comments

---------

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>
Co-authored-by: Jesse Braham <jesse@beta7.io>
Co-authored-by: Scott Mabin <scott@mabez.dev>
Co-authored-by: Sebastian Lauwers <sebastian.lauwers@gmail.com>
Co-authored-by: Nereuxofficial <37740907+Nereuxofficial@users.noreply.github.com>
Co-authored-by: Lachezar Lechev <elpiel93@gmail.com>
Co-authored-by: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com>
Co-authored-by: Nereuxofficial <nereux@tuta.io>
Co-authored-by: Dániel Buga <bugadani@gmail.com>
Co-authored-by: Sofiane <sofiane.meftah@outlook.fr>
Co-authored-by: Kayo Phoenix <kayo@illumium.org>
Co-authored-by: M4tsuri <me@m4tsuri.com>
Co-authored-by: Ellis Hoag <ellis.sparky.hoag@gmail.com>
Co-authored-by: Paul Liétar <lietarp@gmail.com>
Co-authored-by: Hannes <55623006+umgefahren@users.noreply.github.com>
Co-authored-by: Hailey Somerville <hailey@hailey.lol>
Co-authored-by: Tu Nguyen <126753419+TuEmb@users.noreply.github.com>
Co-authored-by: Bryan Kadzban <github@kadzban.net>
Co-authored-by: Matt H <mhammerly@users.noreply.github.com>
Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
Co-authored-by: Jan Niehusmann <jan@gondor.com>
Co-authored-by: Fan Jiang <ProfFan@users.noreply.github.com>
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Co-authored-by: Karl Rikte <karl.rikte@gmail.com>
Co-authored-by: Adam Simpkins <adam@adamsimpkins.net>
Co-authored-by: liebman <liebman@zod.com>
Co-authored-by: Onestacked <chrisi.schrefl@gmail.com>
2024-05-24 17:41:59 +00:00
Timo
83398a7ca0
esp-backtrace: Add custom-halt feature (#1589) 2024-05-24 15:44:24 +00:00
Jesse Braham
28d26e9f45
Use esp toolchain for all clippy checks, add --check option to fmt-packages subcommand in xtask (#1593)
* Update `fmt-packages` subcommand to allow checking formatting as well

* Use the `esp` toolchain for all `clippy` checks in CI
2024-05-24 15:43:51 +00:00
Jesse Braham
b98dbe10d2
Top-level README.md updates, change to path dependency for esp-backtrace in hil-test package (#1588) (#1591)
* Use path dependency instead of git for `esp-backtrace` in the `hil-test` package

* Top-level `README.md` updates
2024-05-24 09:33:18 +00:00
Sergio Gasquez Arcos
a0a02ce2a8
ci: Define GH token (#1584) 2024-05-23 13:56:33 +00:00
Jesse Braham
49ebc23a6d
Add the esp-backtrace package to the repository (#1583) 2024-05-23 13:52:52 +00:00
Dominic Fischer
bd4b044748
Fix new clippy lint (#1581)
* Fix new clippy lint

* All the RISCVs
2024-05-23 13:25:34 +00:00
Jesse Braham
cc28c3eb09
Add the esp-println package to the repository (#1575)
* Add the `esp-println` package to the repository

* Update esp-println version in README.md

Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
Co-authored-by: Sergio Gasquez Arcos <sergio.gasquez@gmail.com>
2024-05-23 10:20:41 +01:00
Jesse Braham
5facb759ae
[2/3] Timer abstraction: add OneShotTimer/PeriodicTimer drivers, Timer trait (#1570)
* Add the `Timer` trait, `OneShotTimer` and `PeriodicTimer` types

* `PeriodicTimer` now working for `TIMG`

* `OneShotTimer` now working for `TIMG`

* `OneShotTimer` now working for `SYSTIMER` (plus, some cleanup)

* SYSTIMER now mostly working for ESP32-S2 as well

* Update `timer_interrupt` example and fix clippy lint to make CI happy again

* Update `CHANGELOG.md`

* Make `SYSTIMER` work correctly with `PeriodicTimer`, address some review comments

* Make `Timer::now()` return a `fugit::Instant`
2024-05-23 06:21:12 +00:00
Scott Mabin
ec8308058b
Riscv stable CI (#1491)
* Remove interrupt and thread executor embassy features

* Reserve sw interrupt 3 (4) instead of 0 for multicore systems with the embassy feature enabled

* Add thread mode context id and fix up examples

* Use stable rust for riscv CI

* Add binary-logs feature to 8021504 driver

* Add binary-logs feature to 8021504 driver
2024-05-22 16:36:39 +00:00
Juraj Sadel
76ed67ad35
ESP32-S2: Add SPI Slave support (#1562)
* SPI Slave for ESP32 / ESP32-S2

* CHANGELOG.md

* Clippy...

* Revert ESP32 changes and keep ESP32-S2 only

* changelog

* review comments

---------

Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de>
2024-05-22 13:21:22 +00:00
Juraj Sadel
60d39e9f33
GPIO: Use Level enum instead of plain bool in constructors (#1574)
* GPIO: Use Level enum instead of plain bool in constructors

* changelog
2024-05-22 12:37:03 +00:00
maxwen
c6ffbb6c9d
Cleanup ESP32-PICO-V3-02 psram efuse bit masking functions (#1571)
Those functions where just copy paste from the C macros
2024-05-22 12:15:44 +00:00
Björn Quentin
45926a1142
Fix wrong baser-address for H2 802.15.4 (#1572) 2024-05-22 08:45:38 +00:00
Björn Quentin
1eb22a27a6
Fix absolute links to API-GUIDELINES.md (#1573) 2024-05-22 08:00:39 +00:00
Björn Quentin
683a0e072c
Add API-GUIDELINES.md (#1543)
* Add `API-GUIDELINES.md`

* Address review comments

* Reference the API guidelines in contributing guide, README and PR template
2024-05-21 16:36:36 +00:00
Scott Mabin
9acf72df33
Mention how handlers are run when drivers are moved across cores (#1568) 2024-05-21 08:22:35 +00:00
Björn Quentin
ef290a9a78
Remove pin generics from PARL_IO (#1545)
* Remove pin generics from PARL_IO

* CHANGELOG.md

* Fixes after rebase
2024-05-17 14:54:48 +00:00
Björn Quentin
9f1cf17c99
Fix async-serial-usb-jtag (#1561)
* Fix async-serial-usb-jtag

* CHANGELOG.md
2024-05-17 14:49:55 +00:00
Björn Quentin
9edd098da5
De-duplicate DMA transfer implementations (#1550)
* De-duplicate DMA transfer implementations

* CHANGELOG.md

* Renaming

* Fix

* Get rid of the lambda

* Clippy
2024-05-15 16:42:35 +00:00
Jesse Braham
8a1df42309
Add the esp-ieee802154 package to the repository (#1554)
* Add the `esp-ieee802154` package to the repo

* Add examples for `esp-ieee802154` package
2024-05-15 15:22:27 +00:00
Sergio Gasquez Arcos
3c05759556
Enable gpio::test_gpio_interrupt for Xtensa targets. (#1555)
* docs: Update probe-rs

* tests: enable test_gpio_interrupt for Xtensa targets
2024-05-15 09:13:43 +00:00
Björn Quentin
2faa2654cb
GPIO Refactoring (#1542)
* GPIO Refactoring

* CHANGELOG.md

* Addressed review comments

* Use `Level` instead of plain bool in public API

* Let drivers enable analog functions
2024-05-15 08:49:33 +00:00
Kirill Mikhailov
68628fc008
Add format subcommand to xtask (#1551) 2024-05-14 13:49:26 +00:00
nan-mu
58f40e95e5
pub UartRx read_byte (#1548)
* Fix for #1547

* a changelog

* fit pr request

* Add read_byte doc

* fit rustfmt
2024-05-13 13:56:24 +00:00
Jesse Braham
865823cace
Update PACs and fix resulting errors, convert IEEE802154 from virtual to real peripheral (#1549)
* Update to latest git revision for PACs, fix resulting build errors

* Make `IEEE802154` peripheral concrete rather than virtual
2024-05-10 14:19:50 +00:00
Kortan
2c1e66e9b3
spi: fix dma wrong mode when using eh1 blocking api (#1541)
* spi: fix dma wrong mode when using eh1 blocking api

* spi: fix dma blocking eh1 type

* Update CHANGELOG.md

* Make ErrorType generic over mode
2024-05-09 06:29:20 +00:00
Jesse Braham
df2b7bd847
Refactor and clean up xtask package (#1540)
* Simplify building/running examples, allow building a single example

* Simplify building/running of tests a bit

* Clean up the `run_elfs` function a bit

* Remove unnecessary duplication in `cargo` module
2024-05-07 10:15:25 +00:00
liebman
8567d35cdc
spi: implement setting bit order (#1537)
* spi: implement setting bit order

* update changelog

* spi: fixed bit order for c3
2024-05-06 14:54:48 +00:00
Jesse Braham
c22a64e37f
Add a lint exception rule for unexpected_cfgs (#1539) 2024-05-06 14:07:54 +00:00
Sergio Gasquez Arcos
0c95668e7a
ci: Update build-test name to match the required CI jobs (#1536) 2024-05-06 06:22:47 +00:00
Kirill Mikhailov
209a82bdc7
Fix delay on esp32h2. (#1535)
* Fix delay on `esp32h2`

* Add changelog entry

* Enable `esp32h2` chip in `get_time` HIL test
2024-05-03 17:09:17 +00:00
Jesse Braham
5a8c76ebdc
Use esp-rs logo in docs and enable nightly feature in docs for esp-alloc (#1533) 2024-05-02 21:47:07 +00:00
Scott Mabin
f32565b4af
Embassy enable thread and interrupt by default, enable embassy when building docs (#1485)
* Remove interrupt and thread executor embassy features

* Reserve sw interrupt 3 (4) instead of 0 for multicore systems with the embassy feature enabled

* Remove uneeded #[feature()] from examples

* Fix HIL tests

* Add thread mode context id and fix up examples

* improve embassy module docs

* changelog

* fixup hil tests

* Fixup usb examples
2024-05-02 15:58:04 +00:00
Sergio Gasquez Arcos
edd03717d2
Enable C3, H2, S2 and S3 HIL (#1513)
* ci: Enable C3, H2, S2 and S3 HIL tests

* feat: Disable H2

* test: Disable S2

* ci: Update test folder

* docs: Update setup

* revert: Revert S2 changes

* ci: Update hil tests targets

* test: Adapt uart test for S2

* ci: Enable H2 HIL

* feat: Filter unsupported targets for the tests failing

* test: Filter failing targets

* ci: Remove the test folder

* test: Filter S2

* feat: Add supported targets

* feat: Remove TODOs and format code

* docs: Remove outdated comment

* feat: Add run-elfs xtask subcommand
2024-05-02 15:35:23 +00:00
Jesse Braham
68a4fb29ed
[1/3] Timer abstraction: refactor systimer and timer modules into a common timer module (#1527)
* Refactor `systimer` and `timer` modules into a common `timer` module

* Update `CHANGELOG.md`

* Rebase and update new example
2024-05-02 13:27:33 +00:00
Dániel Buga
fd1c7b4fc7
embassy-usb support (#1517)
* embassy-usb support

* Add changelog entry

* Update embassy-usb-synopsys-otg

* Change VID/PID to match the blocking example

* Add missing initialisation

* Clean up

* fmt

* Remove log init

* Use released crate

* Revert to released embassy-usb

* Update vid/pid

* Remove redundant TAIT feature gate
2024-05-01 20:38:59 +00:00
Zgarbul Andrey
ee4424961e
PCNT cleanup (part2) && SYSTIMER update (#1520)
* PCNT cleanup (part2)

* SYSTIMER update pac

* etm update
2024-04-30 16:08:04 +00:00
liebman
f70ef1a593
i2c: implement I2C:transaction for embedded-hal and embedded-hal-async (#1505)
* i2c:

* i2c: refactor transaction() and reuse for master_read, master_write, and master_write_read

* i2c: cargo fmt

* i2c: fix an issue with not clearing interrupt bits & move where we reset fifo and command_list

* i2c: fix async compile error

* i2c: fix for esp32 & esp32s2

* i2c: real fix for esp32 (End command never gets cmd_done bit set!)

* i2c: fmt and removal of an unwrap() that I was using while debugging

* i2c: only define opcode values in one place
i2c: use CommandReg in add_cmd

* i2c: async direct & embedded_hal support working

* i2c: cargo fmt

* examples: cargo fmt
2024-04-30 13:41:07 +00:00
Dominic Fischer
d5d3f1f46b
Add LCD_CAM Camera driver (#1483)
* Add LCD_CAM Camera driver

* comments

* 16 bit

* Expose most config

* Module documentation

* Remove GPIO generics

* Fix breaking change

* Remove Pin generics from Camera type

* Fix unsafe

* Another breaking change

* fmt
2024-04-29 14:23:16 +00:00
Zgarbul Andrey
157ac17be1
update adc pac (#1506) 2024-04-29 11:55:15 +00:00
Zgarbul Andrey
840c395a11
PCNT cleanup (part1) (#1519) 2024-04-29 09:49:59 +00:00
Juraj Sadel
db8a5912b7
Add Delay HIL test (#1415)
* Add  HIL test

* fmt
2024-04-29 09:36:45 +00:00
Seb Ospina
c77b0614d0
1376 - I2C runtime ISR binding example update (#1516)
* 1376 - I2C runtime ISR binding example update.

After #1376 the reference example requires the extra
Option<InterruptHadnler>, adding it to the doc example/snippet.

Signed-off-by: Seb Ospina <kraige@gmail.com>

* Update i2c doc example with interrupt_handler parameter

Signed-off-by: Seb Ospina <kraige@gmail.com>

* Upd read_base_mac_address vns get_mac_address example

Signed-off-by: Seb Ospina <kraige@gmail.com>

---------

Signed-off-by: Seb Ospina <kraige@gmail.com>
2024-04-29 07:08:14 +00:00
Jesse Braham
03548807fc
Add additional HIL tests for UART (#1511) 2024-04-26 10:02:45 +00:00
Zgarbul Andrey
b2b43049c1
spi pac update (#1501)
* spi pac update

* try to optimize
2024-04-24 15:49:14 +00:00
Björn Quentin
03b3245eeb
Cleanup PARL_IO (#1508)
* Cleanup PARL_IO

* remove not-needed `#[non_exhaustive]`
2024-04-24 13:39:31 +00:00
Björn Quentin
fa99a1ad43
Cleanup dma module (#1480)
* DMA Cleanup

* Fix ESP32 SPI

* Consider `unsafe fn` as `unsafe block`
2024-04-24 13:38:07 +00:00
Björn Quentin
c77f48388a
Assorted doc improvements (#1507)
* Assorted doc improvements

* Fix `missing_docs`

* Remove unnecessary `mut`

* Chip specific ESP-IDF link for ETM and RNG

* Move `chip!` macro to soc-module
2024-04-24 12:59:51 +00:00
Björn Quentin
373735f96a
Add current_time (#1503)
* Add `current_time`

* CHANGELOG.md

* Add HIL test for `current_time`

* Fix after rebase
2024-04-23 14:59:28 +00:00
Jesse Braham
ad1176865e
Eliminate the GpioExt trait (#1496)
* Eliminate the `GpioExt` trait

* Update `CHANGELOG.md`

* `&self` -> `self`
2024-04-23 13:47:08 +00:00
Jesse Braham
086b6059b9
Remove the SystemExt trait and rename SystemParts to SystemControl (#1495)
* Convert `SoftwareInterrupt` to a unit struct

* Remove the `SystemExt` trait and rename `SystemParts` to `SystemControl`

* Update all examples an HIL tests to reflect previous API changes

* Clean up imports in `hil-test` package, address `clippy` lint warnings

* Update `CHANGELOG.md`
2024-04-23 13:25:03 +00:00
Sergio Gasquez Arcos
0023473068
feat: Reduce method duplication (#1502) 2024-04-23 12:55:22 +00:00
Dominic Fischer
e5b46b5024
Make software interrupts shareable (#1500) 2024-04-23 10:42:08 +00:00
David Herberth
94bca218c9
SmartLedsAdapter example requires clocks and interrupt handler (#1504) 2024-04-23 10:39:05 +00:00
Scott Mabin
e0610f7997
Undo TRNG changes in RNG (#1498)
* Backout the TRNG

* changelog
2024-04-22 19:27:30 +00:00
Scott Mabin
dd8083dbdc
changelog (#1469) 2024-04-22 19:44:29 +01:00
Scott Mabin
56a7553b2d
Camel case structs (#1473)
* Remove uneeded usb generics

* Ensure all structs are consistently CamelCased

* changelog
2024-04-22 17:27:53 +00:00
Seb Ospina
f5dfca7f27
Adapting maxwen branch to v0.16.1 (#1424)
* Adapting maxwen branch to v0.16.1

maxwen@6ba9b84

closes #1155

Signed-off-by: Seb Ospina <kraige@gmail.com>

* ESP32-PICO-V3-02 init

Signed-off-by: Seb Ospina <kraige@gmail.com>

* rustfmt

* Update CHANGELOG.md

---------

Signed-off-by: Seb Ospina <kraige@gmail.com>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-04-22 17:01:39 +00:00
Jesse Braham
c4383196fa
Remove unused files, clean up some #[cfg]s and #[allow] attributes (#1494)
* Remove unnecessary files

* Use config symbols instead of feature names for remaining `cfg` attrs

* Clean up some attributes/TODO comments in UART driver
2024-04-22 16:29:33 +00:00
Jesse Braham
4d2ab5bc8f
Create virtual peripherals for CPU control and radio clocks (#1428)
* Create a virtual `CPU_CTRL` peripheral for ESP32/S3

* Create a virtual `RADIO_CLK` peripherals for all devices with radios

* Use `PeripheralRef` for the `CpuControl` constructors

* Update `CHANGELOG.md`
2024-04-22 15:21:08 +00:00
Dominic Fischer
866933bf6f
Fix entry macro for ULP hal (#1488) 2024-04-22 14:42:10 +00:00
liebman
5f79be6c9b
i2c: i2c1_handler used I2C0 register block by mistake (#1487)
* i2c: i2c1_handler used I2C0 register block by mistake

* update CHANGELOG
2024-04-22 14:41:59 +00:00
Scott Mabin
4d44f4179e
Document more EspAlloc invariants (#1474) 2024-04-22 14:41:46 +00:00
Droog71
7e5895c5fd
Fix for issue #1419 (#1441)
* Fix for issue #1419. Removed ESP32 specific code for resolutions > 16 bit in ledc embedded_hal::pwm max_duty_cycle function. Fixed division by zero in ledc embedded_hal::pwm set_duty_cycle function and converted to set_duty_hw instead of set_duty to eliminate loss of granularity.

* Updated change log.

* Fixed indentation in ledc set_duty_cycle function.

* Removed unused ChannelIFace import for ehal mod.
2024-04-22 14:41:34 +00:00
Sergio Gasquez Arcos
20c77891d8
ci: Adapt HIL tests to use RPi (#1493) 2024-04-22 14:28:01 +00:00
Scott Mabin
3dfea214d4 next release cycle 2024-04-18 16:51:30 +00:00
Jesse Braham
822bef12c7
New package releases (#1464) 2024-04-18 16:02:45 +00:00
Scott Mabin
39a75bae90
Improve the top level crate documentation (#1467) 2024-04-18 15:50:20 +00:00
Dominic Fischer
763bd638e7
Expose e-hal ErrorKind::NoAcknowledge in I2C driver (#1454)
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-04-18 11:28:50 +00:00
Dominic Fischer
8f2ee88491
Add remaining peripheral signals for LCD_CAM (#1466) 2024-04-17 23:05:42 +00:00
Adam Simpkins
3d9f117beb
Add peripheral signals for the USB external PHY (#1463)
These signal definitions appear to be missing, and it seems like these
are needed to use an external PHY.  I copied these values from the
gpio_sig_map.h headers in the ESP-IDF.
2024-04-17 20:30:39 +00:00
Björn Quentin
c4d1eb492e
Address gpio module todos (#1462)
* Add `set_state` for GpioPin

* `#![warn(missing_docs)]` for GPIO module

* CHANGELOG.md
2024-04-17 16:07:42 +00:00
Kirill Mikhailov
6f91367d6c
Add mechanism to configure UART source clock (#1416)
* Creating mechanism for setting UART source clock

* Format + examples updating

* Changelog entry

* Smaller fixes (reviews)

* Move RC_FAST_CLK constant to soc

* Fix REF_TICK value

* Add doc comments

update doc comments

* fmt
2024-04-17 15:27:47 +00:00
Scott Mabin
111dcda103
SystemTimer fixups (#1455)
* Resolve TODOs, add wait_until to target alarm, add &mut self to public API

* changelog
2024-04-17 15:09:48 +00:00
Jesse Braham
71db9fa55c
Remove partial support for the ESP32-P4 (#1461)
* Remove all code for and mentions of the ESP32-P4

* Update `CHANGELOG.md`
2024-04-17 14:49:00 +00:00
Björn Quentin
54f4f0e90d
Add Safety comments (#1460) 2024-04-17 12:48:07 +00:00
Björn Quentin
29d9cfbe31
Verify C6 signals / compared to ESP-IDF (#1459) 2024-04-17 10:46:35 +00:00
dimpolo
0fa3214971
MCPWM deadtime improvements (#1378)
* MCPWM deadtime improvements

* allow changing deadtime config after pin creation
* constify DeadTimeCfg
* fix some wrong bit values
* remove some unsafe blocks

* fix some typos

* enable PwmPin as a last configuration step

* introduce mcpwm::operator::LinkedPins and move deadtime related method there

* Typo

* variant() -> bits()

* formatting

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-04-17 09:23:31 +00:00
Björn Quentin
803fbb4d94
Use AlignmentHelper for AES (#1458)
* Use `AlignmentHelper` for AES

* Make Clippy smile
2024-04-17 09:00:42 +00:00
Juraj Sadel
000617b876
esp32: fix ledc (#1457)
* esp32: fix ledc

* changelog
2024-04-17 07:39:10 +00:00
Kirill Mikhailov
17492f6b62
Support 192 and 256-bit keys for AES (#1316)
* Support 192 and 256-bit keys for AES

* quick fix

* Not `panic`ing on wrong key length

* fmt + hil

Update comment

* Add more doc comments

* Use `Key` enum for DMA mode

fix

* API fix: make some critical functions private

* Use `Into<Key>` instead of forcing users to call funcs with `key.into()`
2024-04-16 16:51:25 +00:00
Jesse Braham
3c2dccd51c
Move the esp-alloc package into the repository (#1449) 2024-04-16 15:11:05 +00:00
Björn Quentin
2a750dfedc
Use esp-synopsys-usb-otg 0.4.1 (#1452) 2024-04-16 15:00:25 +00:00
Björn Quentin
e368be0565
Turn some not-too-useful TODOs into useful documentation (#1451) 2024-04-16 14:46:27 +00:00
Scott Mabin
48ced47874
fixmes be gone (#1448) 2024-04-16 13:52:45 +00:00
Scott Mabin
89a3d56b15
Adding errors for receive and transmit read/write async (#1445)
* Adding errors for receive and transmit read/write async

* rebase and fix ups

---------

Co-authored-by: konsulten <nordmarkclaes@gmail.com>
2024-04-16 13:22:15 +00:00
Sergio Gasquez Arcos
1a5ca65eed
Enable S3 HIL (#1338)
* feat: Add HIL support for S3

* ci: Add dummy s3 job

* test: Filter interrupt test for Xtensa devices

* ci: Install Xtensa toolchain
2024-04-16 12:09:18 +00:00
Jesse Braham
586744070b
Remove some #[allow] attributes and an unused function (#1440)
* Remove TODO comments from linker scripts for ESP32-C6/H2

* Small refactor in Xtensa interrupt module to get rid of some allow attributes

* Remove unused function and attribute from `esp-hal-procmacros`
2024-04-16 10:45:57 +00:00
Jesse Braham
66cab5dfb4
Update to latest (unpublished) PACs and fix all breaking changes (#1439) 2024-04-16 10:45:45 +00:00
Sergio Gasquez Arcos
6b742968b1
Add SPI Full Duplex DMA test (#1443)
* test: Initial SPI Full Duplex DMA tests

* feat: Add timeouts

* tests: Add symestric_transfer_huge_buffer and asymestric_transfer tests

* style: Fix tests names
2024-04-16 10:26:53 +00:00
Scott Mabin
46c8527123
spi housekeeping (#1438) 2024-04-16 06:43:29 +00:00
Sergio Gasquez Arcos
381ce9530c
Clock monitor HIL test (#1425)
* tests: Add clock_monitor HIL test

* feat: Adjust accepted freq ranges

* fix: Get the estimate a second time if its very off

* test: Update ranges and check
2024-04-15 09:54:55 +00:00
Sergio Gasquez Arcos
634191203f
AES DMA HIL Tests (#1426)
* test: Initial AES DMA HIL tests

* test: Cover all the AES modes

* feat: Reset aes at the end of the tests to avoid errors in `aes` test

* feat: Reset the interrupt state when finishing the transform
2024-04-15 09:24:07 +00:00
Sergio Gasquez Arcos
da3375bbe4
test: Cover all aes modes (#1423) 2024-04-11 15:46:15 +00:00
Sergio Gasquez Arcos
5d61074c85
HIL SHA tests (#1422)
* feat: Add missing cfg(test)

* feat: Initial SHA HIL test

* test: Test all the SHA modes
2024-04-11 15:42:15 +00:00
Sergio Gasquez Arcos
a22b817ee5
HIL updates (#1412)
* docs: Document new xtask features

* style: format deps

* feat: enable all the aliases

* feat: Update embedded-tests executors

* feat: Enable running only one test

* feat: Exit if a test fails

* docs: Fix typo in command

* build: Enable xtensa-semihosting in xtensa targets

* feat: Handle probe-rs esp32 chip name

* style: Clippy lints

* revert: Exit if a test fails

* chore: Remove aliases

* feat: Remove unnecesary toogle

* feat: Error if a test fails and print failed tests
2024-04-11 14:04:32 +00:00
Jesse Braham
dfc6d86a58
Warn users when attempting to build esp-hal using the dev profile (#1420)
* Warn users when attempting to build `esp-hal` using the `dev` profile

* Update `CHANGELOG.md`
2024-04-11 13:04:55 +00:00
Jesse Braham
f6925480f2
Remove unused function from esp-hal-procmacros (#1421) 2024-04-11 09:29:29 +00:00
Juraj Sadel
c73a2d91ae
Add HIL test for ECC (#1418)
* Add HIL test for ECC

* review changes: remove forgotten SysTimer in C2 test
2024-04-10 15:16:20 +00:00
Sergio Gasquez Arcos
86f4f50b3e
test: Add CRC and MD5 HIL tests (#1417) 2024-04-10 14:51:12 +00:00
Sergio Gasquez Arcos
02c2825b2c
HIL RSA tests (#1414)
* docs: Update documentation

* test: Add rsa hil test
2024-04-10 14:43:10 +00:00
Björn Quentin
1fdfc9270e
Remove the #[interrupt] macro (#1409) 2024-04-09 10:11:57 +00:00
Björn Quentin
41aa556764
Avoid "missing_transmute_annotations" warnings (#1410) 2024-04-08 11:47:36 +00:00
Kirill Mikhailov
52e5b94bd5
PCNT: Runtime ISR binding (#1396)
* PCNT: Runtime ISR binding

* Changelog entry

* fmt + warnings

* Unify `interrupt_handler` + alignment with latest changes

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-04-05 15:16:11 +00:00
Juraj Sadel
1e6165e04b
Runtime ISR binding and simple public API docs for RTC (#1405)
* Runtime ISR binding and simple public API docs for RTC

* changelog

* import dependencies instead of using full paths
2024-04-05 14:54:13 +00:00
Scott Mabin
315b8cc0ff
HIL xtask support (#1404)
* allow running tests via xtask

* Add run-tests xtask subcommand

* Use xtask in HIL ci
2024-04-05 14:39:20 +00:00
Jesse Braham
fd9f7895f6
Extract inner modules of gpio module into their own files (#1397)
* Extract inner modules of `gpio` module into their own files

* Update `CHANGELOG.md`

* Add missing doc comment in `gpio::lp_io` module

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-04-05 12:33:49 +00:00
Björn Quentin
b3bc28efef
Software interrupts runtime binding (#1398)
* Split software interrupts

* Make swint0 unavailable on a multi_core target when using thread-executor

* Clarify why embassy_multiprio example needs two executors

* Make interrupt-executor require a SoftwareInterrupt<n>

* Improve code

* CHANGELOG.md

* Don't use `#[interrupt]` in thread-executor

* More docs

* Typo fixed
2024-04-05 12:33:21 +00:00
dimpolo
d26b1bd504
xtensa: fix AdcConfig::adc_calibrate (#1379)
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-04-05 11:44:35 +00:00
dimpolo
2437d82554
fix commented out paths in adc_cal example (#1400) 2024-04-05 09:40:41 +00:00
Markus Kasten
43f284034c
Fix panic when setting LEDC duty cycle to 0 with SetDutyCycle::set_duty_cycle (#1403)
* Fix panic when setting LEDC duty cycle to 0 with `SetDutyCycle::set_duty_cycle`

Fixes #1390

* Update Changelog for #1403
2024-04-05 09:40:15 +00:00
Juraj Sadel
215573a720
Runtime ISR binding and simple public API docs for assist-debug (#1395)
* Runtime ISR binding and simple public API docs for assist-debug

* changelog

* actually use runtime ISR in example

* revert MODE generic argument
2024-04-04 15:08:12 +00:00
Jesse Braham
bf2cca90be
Provide native APIs for I2C/SPI functionality currently handled by embedded-hal@0.2.x traits (#1386)
* Provide native APIs for SPI functionality currently handled by `embedded-hal` traits

* Provide APIs for I2C functionality currently handled by `embedded-hal` traits

* Rebase and update HIL test for SPI to get it building again
2024-04-04 14:09:35 +00:00
Björn Quentin
bd9808827f
Make sure to enable the GPIO interrupt (#1394)
* Make sure to enable the GPIO interrupt

* Refactor GPIO constructors
2024-04-04 11:24:38 +00:00
Jesse Braham
839a3ba62b
Use PAC instead of volatile writes in rtc_cntl::rtc for ESP32-H2 (#1387) 2024-04-04 10:41:31 +00:00
Jesse Braham
000ed9affc
Refactor the ADC driver, allow use without embedded-hal@0.2.x traits (#1391)
* Reduce duplication of code within the `analog::adc` module

* Add a public `read_oneshot` method to the ADC driver

* Do not require `embedded-hal@0.2.x` traits for ADC examples

* Add doc comments to all public methods which do not already have them
2024-04-04 10:35:25 +00:00
Scott Mabin
b8ca1323d0
Remove remaining references to embedded-hal-02 for GPIO examples (#1392) 2024-04-04 10:33:23 +00:00
Scott Mabin
969f9a15f6
Build HIL in CI prior to running them (#1388)
* xtask: allow building hil tests

* check hil tests build in CI
2024-04-03 17:07:46 +00:00
Zgarbul Andrey
13c81177c5
inherent gpio methods (#1284) 2024-04-03 16:47:47 +00:00
Björn Quentin
ba73154c36
Runtime ISR binding for TWAI (#1384)
* Runtime ISR binding for TWAI

* CHANGELOG.md

* Fix EH-0.2 TWAI implementation
2024-04-03 13:46:21 +00:00
Björn Quentin
efcf7d4074
Don't use #[interrupt} in the serial_interrupts.rs example (#1385) 2024-04-03 13:14:35 +00:00
Björn Quentin
256d7198f9
Timers runtime isr binding (#1348)
* Runtime ISR binding for TIMG/SYSTIMER

* CHANGELOG.md

* Implement `set_interrupt_handler` only for blocking

* Adapt HIL test
2024-04-03 08:14:27 +00:00
Markus Kasten
81a40703bd
Flush in spi::master::Instance::write before attemting any writes (#1381)
* Flush in `spi::master::Instancee::write` before attemting any writes

Otherwise subsequent calls to `SpiBus::write` will cause corrupted writes
and break `embedded-hal-bus`es transactions. Fixes #1369.

* Update Changelog for #1381

* Fix missing result handling when calling `flush()` in SPI `Instance::write_bytes`
2024-04-03 00:55:40 +00:00
Jesse Braham
55864b1ba7
UsbSerialJtag: async/blocking constructors, runtime interrupt binding support (#1377)
* Refactor `usb_serial_jtag` driver to take an operational mode as a generic parameter

* Update module documentation

* Update `CHANGELOG.md`
2024-04-02 23:45:14 +00:00
Jesse Braham
e4c985e8dd
Eliminate the rt and vectored features from the esp-hal package (#1380)
* Eliminate the `vectored` feature

* Eliminate the `rt` feature

* Update `CHANGELOG.md`

* Fix typo in comment
2024-04-02 23:21:39 +00:00
Björn Quentin
4aca01a7b6
I2C runtime ISR binding (#1376)
* I2C runtime ISR binding

* CHANGELOG.md
2024-04-02 18:03:36 +00:00
Scott Mabin
21d833d2a3
Refactor testing, add defmt, add async gpio test (#1363)
* Refactor testing, add defmt, add async gpio test

* Add test to ensure the some edge case pins can be used in async mode

* Add test for pin0

* clippy

* update test to use constants extracted from esp-idf's soc module

* address review comments

* simplify test to just initialize one pin as async

* changelog
2024-04-02 15:28:15 +00:00
Björn Quentin
392ae7dee6
ESP32/S2: I2S wait for TX start (#1375)
* ESP32/S2: I2S wait for TX start

* CHANGELOG.md
2024-04-02 11:44:02 +00:00
Sergio Gasquez Arcos
c8bd107218
docs: Update probe-rs version (#1374) 2024-04-02 11:58:31 +01:00
Jesse Braham
99b0c774ac
Use fewer embedded-hal@0.2.x traits in examples, build HAL without default features in CI (#1372)
* Clean up `embedded-hal-02` related imports

* Clean up some random warnings

* Update various examples to no longer depend on `embedded-hal-02` feature

* Build `esp-hal` without default features enabled in CI
2024-04-01 17:33:23 +00:00
Zgarbul Andrey
2440c240ce
Ledc clusters (#1368)
* ledc: make compile

* unpaste

* clean changelog

* Update esp-hal/CHANGELOG.md

Co-authored-by: Scott Mabin <scott@mabez.dev>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-04-01 14:07:27 +00:00
Jesse Braham
dc6f8378e2
Build esp-hal for the ESP32-P4 in CI (#1370)
* Build `esp-hal` for the ESP32-P4 in CI (but do not perform other checks, yet)

* Get CI passing again for ESP32-P4
2024-04-01 13:56:08 +00:00
Scott Mabin
32587d7569
cleans up some timg fixmes, allows for use of timers without eh02 (#1367) 2024-04-01 12:43:18 +00:00
Zgarbul Andrey
b8b041b51a
SOC_ETM cleanup (#1365)
* SOC_ETM cleanup

* changelog

* review catch

Co-authored-by: Scott Mabin <scott@mabez.dev>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-03-31 17:54:53 +00:00
Zgarbul Andrey
c2279a28d3
TIMG clusters (#1364) 2024-03-31 12:05:28 +00:00
Dániel Buga
f0d6dc4bee
Fix GPIO numbers (#1362) 2024-03-30 16:41:44 +00:00
Zgarbul Andrey
9b048f4c99
MCPWM clusters (#1360) 2024-03-30 16:19:43 +00:00
Mateusz
bd1e1fab1a
C3: Fix the number of GPIO pins (#1361)
* C3: Fix the number of GPIO pins

* update changelog
2024-03-30 16:04:34 +00:00
Björn Quentin
6f01b5aba3
Runtime ISR binding crypto accelerators (#1354)
* Runtime ISR binding for ECC,SHA,RSA

* CHANGELOG.md

* CHANGELOG.md

* Fix examples

* Remove obsolete `free` from ECC driver

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-03-29 23:13:19 +00:00
Pietro
5037447a0a
Properly disable USB pullups/pulldowns on esp32c3/esp32s3 (#1358)
* fix usb pullup/pulldown interfering with GPIO

* fix formatting

* update changelog

* fix typo in changelog
2024-03-29 22:52:17 +00:00
Zgarbul Andrey
9f035d40a9
update pac (#1357) 2024-03-29 22:51:48 +00:00
Jesse Braham
7d5372f57d
Decouple the twai driver from the embedded-hal traits (#1355)
* Decouple the TWAI driver from the `embedded-hal` and `embedded-can` packages

* No longer require `embedded-hal`/`embedded-can` for the TWAI example

* Update `CHANGELOG.md`
2024-03-28 14:44:09 +00:00
Björn Quentin
d5abc3fc85
Test open-drain-output, test GPIO interrupts (#1349)
* Test open-drain-output, test GPIO interrupts

* Make GPIO interrupt test less flaky

* Don't ignore hil-tests in CI
2024-03-27 15:21:52 +00:00
Juraj Sadel
cf143972b6
UART: Allow the change of baudrate after instantiation (#1350)
* UART: Allow the change of baudrate after instantiation

* changelog

* forgot to change LP_UART

* docs: add docs for public API
2024-03-27 15:20:46 +00:00
Zgarbul Andrey
344cc95e65
use DMA channels (#1330)
* use DMA channels & use const generics

* usize -> u8
2024-03-27 12:50:39 +00:00
dimpolo
b9ba657dc4
optimize ADC::read and add ADC::read_blocking (#1293) 2024-03-26 15:22:24 +00:00
Björn Quentin
4077734c3c
Runtime DMA interrupt binding (#1300) 2024-03-26 13:56:48 +00:00
Jesse Braham
65dca0025b
Update module documentation for UART driver, make some more methods public (#1347) 2024-03-26 13:50:47 +00:00
yanshay
f18e8ae33c
Fix LCD_CAM i8080 potentially sending garbage data to display (#1301) 2024-03-26 10:57:51 +00:00
Jesse Braham
9b64e648e5
Add async UART HIL test (#1345)
* wip

* Clean up Cargo config/manifest, update dependencies

* Remove TODO comment from test

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-03-26 10:10:17 +00:00
Jesse Braham
7792d67b47
Seal all Instance traits (#1346)
* Seal all `Instance` traits

* Update `CHANGELOG.md`
2024-03-26 03:06:15 +00:00
Jesse Braham
f060582f0b
Clear the UART's TX/RX FIFOs at initialization (#1344)
* Clear the UART's TX/RX FIFOs at initialization

* Update `CHANGELOG.md`
2024-03-25 16:54:53 +00:00
Björn Quentin
fd4f5592a4
RMT: allow driver to init as blocking or async (#1341)
* RMT: allow driver to init as blocking or async

* CHANGELOG and minor fixes
2024-03-25 13:54:03 +00:00
Jesse Braham
d761ec4def
Address clippy lint warnings from latest Xtensa toolchain (#1343) 2024-03-25 13:50:18 +00:00
Jesse Braham
ace679f13b
Make examples less dependent on embedded-hal where able (#1342)
* Add support for building a package without its default features to `xtask`

* Do not require `embedded_hal_02` traits in examples where they are not required

* Do not require `embedded_hal_02` traits for filling a buffer with random bytes
2024-03-25 13:14:22 +00:00
Jesse Braham
8da8425907
Update READMEs, housekeeping (#1339)
* Remove patches and just use git dependency for PACs instead

* Various `README.md` normalization/updates for simpler packages

* Update `README.md` for `esp-hal` and `esp-lp-hal`

* Update repo-level `README.md`
2024-03-22 17:11:20 +00:00
Sergio Gasquez Arcos
3efdbe9420
docs: Fix i2c pins (#1340) 2024-03-22 15:09:20 +00:00
Ghislain MARY
d50290e9dd
Fix I²C frequency for esp32 and esp32s2. (#1333)
Co-authored-by: Ghislain MARY <ghislain@ghislainmary.fr>
2024-03-22 09:37:32 +00:00
Anthony Grondin
1b2dab1dff
Add missing #[doc(hidden)] attributes for embassy proc macros (#1302)
Fixes https://github.com/esp-rs/esp-hal/issues/1233
2024-03-21 22:10:15 +00:00
Scott Mabin
d5e4995777
uart: allow driver to init as blocking or async (#1294)
* uart: allow driver to init as blocking or async

* adds a mode type param to Uart types
* remove #[interrupt] usage
* add constructor for blocking and async modes
* blocking constructor takes optional interrupt
* async chooses the correct handler to bind at runtime
* moves interrupt enable for uart into the driver

* changelog
2024-03-21 21:51:09 +00:00
Jesse Braham
bc74a446a4
Add dummy CI jobs to (hopefully) make our HIL testing work with merge queues (#1331) 2024-03-21 16:57:51 +00:00
Scott Mabin
93d31e76d8
Add InterruptHandler wrapper (#1299)
* Add InterruptHandler

* Which takes the handler and a prio.
* Updates the `#[handler]` macro to create this for us.

* changelog
2024-03-21 15:45:35 +00:00
Scott Mabin
25f509ce74
discard interrupt symbols from lto so that lto doesn't end up rebinding them (#1327) 2024-03-21 15:38:07 +00:00
Jesse Braham
0cb5e4e82d
Add the esp-build package, update esp-hal and esp-lp-hal to use it in their build scripts (#1325)
* Create the `esp-build` package

* Update `esp-hal` and `esp-lp-hal` to use `esp-build`
2024-03-21 15:36:33 +00:00
Björn Quentin
4e5020f83f
Enable TWAI for ESP32-C6 (#1323)
* Enable TWAI for ESP32-C6

* CHANGELOG.md

* Make Clippy happy, again

* Make Clippy happy. For real this time

* Remove debug code
2024-03-21 15:16:44 +00:00
Sergio Gasquez Arcos
baea915935
Add HIL testing (#1297)
* Create the `hil-test` package

* Add a simple integration test to verify basic GPIO functionality

* WIP

* feat: Update with esp-hal unification

* build: Update dependencies

* feat: Add a simple CI workflow test

* ci: Avoid using a gh-hosted-runner to build

* ci: Remove building bins in gh-hosted-runner

* ci: Remove HIL Gpio CI test

* ci: Test all the available tests

* test: Add spi_full_duplex test

* docs: Add documentation

* test: Add uart test

* style: Remove unused imports

* docs: Update wiring, document H2 VM

* ci: Enable H2 tests

* ci: Add rust-cache action

* docs: Document H2 vm

* test: Add timeout

* ci: Enable ESP32-C3 tests

* feat: Add timeouts

* feat: Add aes test

* ci: Avoid running CI workflow when we change hil-test stuff

* test: Remove warnings

* feat: Address feedback

* feat: Update features names and spi methods

* ci: Remove rust-cache action

* Update HIL to probe-rs#2292 (#1307)

* feat: Update probe-rs/embedded-test to probe-rs#2292

* feat: Remove lib

* ci: Use a matrix

* ci: Enable ESP32C3

* feat: Add a way to cfg away test for unsuported peripherals

* ci: Update trigger conditions

* feat: Update pins to make it work on s3

* feat: Changes enabling S3

* feat: Remove log feature

* feat: Adapt for rebase

* feat: Remove env

* feat: enable S3

* chore: Remove todo

* build: Pin dependencies

* feat: Add target alias

* docs: Update readme

* fix: Fix traits imports after rebase. Use debug

* build: Remove lto

* feat: Build tests on release mode

---------

Co-authored-by: Jesse Braham <jesse@beta7.io>
2024-03-21 14:28:27 +00:00
Scott Mabin
1444b62777
ensure we don't strongly define cpu int handlers (#1324) 2024-03-21 13:46:49 +00:00
Scott Mabin
2cc7a8ccbd
document usb port differences and recommend usb_serial_jtag example (#1321) 2024-03-21 13:41:46 +00:00
Björn Quentin
33c7c32c53
Async-TWAI (#1320)
* Apply changes from https://github.com/esp-rs/esp-hal/pull/951

Co-authored-by: Paul Paterson <ptpaterson@gmail.com>

* Fix ESP32-S3 async-twai

* Fix ESP32-C6, prepare ESP32, ESP32-S2

* Whitelist twai examples on ESP32-S2

* Fix copy+paste introduced bug

---------

Co-authored-by: Paul Paterson <ptpaterson@gmail.com>
2024-03-21 12:37:43 +00:00
Zgarbul Andrey
4a0a19e253
Delay::delay (#1298)
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-03-20 23:45:02 +00:00
Scott Mabin
e98cf71b67
Fix up docs and features; default to enabling eh1 instead of eh02 (#1313)
* Fix up docs and features; default to enabling eh1 instead of eh02

* Changelog

* Fix twai example

* Fixup from defaulting to eh1
2024-03-20 17:12:33 +00:00
Scott Mabin
a61ffef909
RISCV: remove the direct-vectoring & interrupt-preemption features and enable them by default (#1310)
* Remove the `direct-vectoring` feature

* Enables the feature by default
* renames the old direct_vectoring enable function `enable_direct`

* Make enable_direct safe, move it out of vectored module

* enable interrupt preemption by default for riscv

* remove pub from cpu intr handlers

* add enable_direct for Xtensa too

* Fix flip-link feature

* Fix up interrupt docs

* changelog

* fix clippy suggestions

* Disable P4 workflow
2024-03-20 16:19:22 +00:00
Björn Quentin
1f155cf301
ESP32: Apply Errata 3.6 fix in more places (#1315)
* ESP32: Apply Errata 3.6 fix in more places

* CHANGELOG.md entry
2024-03-20 15:46:38 +00:00
Jesse Braham
e5b393fe4d
Use task arena instead of embassy-executor's nightly feature (#1314) 2024-03-20 14:36:05 +00:00
Kirill Mikhailov
6d9048a873
Update PR Template (#1281)
* Update `PR Template`

* Minor improvements
2024-03-19 14:54:10 +00:00
sisoteuz
1846543873
Add ETM support for general purpose timers (#1287)
* Implement ETM for general purpose timers

* Revert changes to timer_interrupt example

* Add an example for ETM for general purpose timers

* Add newly introduced generic const param for Timer0

* Use id function on TimerGroupInstance instead of const parameter

* Revert const parameter on Timer1

* Specify supported chips

* Update CHANGELOG.md

* Update CHANGELOG.md

* Fix example

* Assign configured ETM channel to a variable to prevent drop

* Fix comments

* Move declaration of delay after critical section

* Use delay_millis instead of delay_ms

* Remove mut from delay

* Add documentation
2024-03-15 14:03:21 +00:00
Jesse Braham
3a9c248f11 Fix package metadata for esp-hal 2024-03-15 00:18:46 +00:00
Jesse Braham
b402692c72
Create safe wrappers for some ROM functions in the rom module (#1290)
* Create safe wrappers for some ROM functions in the `rom` module

* Replace transmute in ESP32-S3's `cpu_control` module with ROM function

* Inline *all* the things!

* Remove duplicate of `rom::regi2c_write` with ROM function
2024-03-14 16:45:06 +00:00
Jesse Braham
3079d9cc49
Feature gate embedded-hal@0.2.x implementations, rename eh1 feature to embedded-hal (#1273)
* Create an `embedded-hal-02` feature and gate implementations, rename `eh1` to `embedded-hal`

* Use native `Delay` APIs in examples where applicable

* Fix example imports, be explicit about about `embedded-hal-02` feature requirements

* Update `CHANGELOG.md`
2024-03-14 15:40:44 +00:00
Jesse Braham
1983a74cb1
Correct doc comment regarding effective measurement range of ADC for given attentuations (#1291)
#1229
2024-03-14 15:16:11 +00:00
Scott Mabin
de19bb0446
Fix core1 startup (#1286)
* Fix core1 startup

The original code tried to set the stack pointer and call the closure
_in the same stack frame_. This isn't possible, so the actual stack
being used was the 8K stack setup by ROM code. If this stack overflowed,
it could corrupt the ROM function .bss and .data which is why I was
seeing intermittent panic messages. I still don't understand all the
failure cases, but I know that now we are using the correct stack
properly.

* Improve multicore example

* Change log

* apply fix to esp32
2024-03-14 13:39:28 +00:00
Scott Mabin
7947cecd93
Reserve esp32 ROM stacks and adjust dram2 accordingly (#1289)
* reserve esp32 rom stacks and adjust dram2 accordingly

* changelog
2024-03-14 13:38:48 +00:00
Jesse Braham
7983923b16
Simplify building documentation, automatically generate documentation index (#1279) 2024-03-13 17:02:13 +00:00
Björn Quentin
1d3fa8e93b
Don't use #[interrupt] in GPIO driver (#1278) 2024-03-13 16:55:33 +00:00
Jesse Braham
6046528e0b
Remove package-level type exports (#1275)
* Remove package-level type exports

* Update imports in examples

* Update `CHANGELOG.md`
2024-03-13 15:50:00 +00:00
Björn Quentin
2b4c408333
Runtime interrupt binding (#1231)
* Interrupt runtime binding

* Add `set_interrupt_handler` for GPIO

* Fix

* Fix typo

* Make sure to produce a warning for an unused `#[handler]`

* Simplify GPIO interrupt handling

* Appease Clippy

* Make sure to patch the PACS in esp-hal

* Use latest PAC commit

* CHANGELOG.md entry
2024-03-13 15:45:34 +00:00
Jesse Braham
1f129744fd
Create the esp-metadata package, update esp-hal build script to use it (#1256) 2024-03-13 12:27:24 +00:00
Björn Quentin
c283563542
Simplify dma usage (#1238)
* Simplify SPI,I2S,AES

* Simplify PARL_IO and I8080

* Adapt docs

* Don't require `&mut` for tx-buffer

* Annotate DMA transfer structs as `#[must_use]`

* CHANGELOG.md entry
2024-03-13 10:14:56 +00:00
Kirill Mikhailov
cc9ccb3f83
Fix dead code section from IDF (#1272)
+changelog entry
2024-03-13 08:10:35 +00:00
Jesse Braham
465a87659e Begin next release cycle 2024-03-12 15:27:13 +00:00
Jesse Braham
92e3ea576b
New esp-hal release (#1268)
* New `esp-hal` release

* Update documentation index to point to new version
2024-03-12 15:22:59 +00:00
Jesse Braham
a0f3b39acc
Do not ensure randomness or implement CryptoRng for ESP32-P4/S2 (#1267)
* Do not ensure randomness or implement `CryptoRng` for ESP32-P4/S2

* Update `CHANGELOG.md`

* Make `clippy` happy
2024-03-12 15:06:49 +00:00
Jesse Braham
d3a5dcce86
Display a warning banner linking to docs.esp-rs.org when documentation is hosted on docs.rs (#1266)
* Display a warning banner linking to docs.esp-rs.org when hosted on docs.rs

* Fix a few warnings reported while building docs
2024-03-12 14:52:32 +00:00
Scott Mabin
301462a2de
use ROM memcpy over compiler builtins ROM (#1255) 2024-03-11 17:24:47 +00:00
Jesse Braham
e4ea62a53c
Un-pin the defmt package's version, bump esp-println and esp-backtrace dependency versions (#1264)
* Un-pin the `defmt` package's version for `esp-hal` and `esp-hal-smartled`

* Bump `esp-println` and `esp-backtrace` versions in the `examples` package

* Mention lack of MSRV guarantees when using `defmt` feature
2024-03-11 16:35:39 +00:00
Jesse Braham
513a063547
Create an xtask subcommand to generate eFuse fields (#1258)
* Use the `xtask` to generate eFuse fields from CSV, instead of at build time

* Rewrite the CSV parser so that it can handle the newer eFuse definitions

* Regenerate eFuse field definitions from latest ESP-IDF commit

* Include generation date and ESP-IDF commit hash in file headers
2024-03-11 14:22:31 +00:00
Jesse Braham
85ee380708 Begin next release cycle 2024-03-08 14:15:30 +00:00
Jesse Braham
e198f0eee4
New package releases (#1249)
* New package releases

* Fix the `CHANGELOG.md` check in CI

* `defmt` is annoying

* Update documentation index to point to new version, correct release date

* Remove docs.rs badge from and update docs link in `README.md`

* Silence `clippy`

* Fix documentation link in `esp-hal/README.md`
2024-03-08 14:01:07 +00:00
Jesse Braham
4bcd5cf611
Tweak the documentation URL slightly (#1250)
* Tweak the documentation URL slightly

* Ignore locally generated docs
2024-03-07 17:19:07 +00:00
Jesse Braham
518e995b2c
Add a workflow to build and deploy esp-hal documentation to GitHub Pages (#1248)
* update workflow

* Format `index.html`, update the URLs, add favicon, various other minor tweaks

* Move script into `.github/scripts`, add the package version to documentation path

* Split the building and deployment of documentation into its own workflow

---------

Co-authored-by: Kirill Mikhailov <konnor1980@yandex.ru>
2024-03-07 13:58:25 +00:00
Scott Mabin
e65951c882
Add new embassy features for esp32s2 and other systimers. Enable embassy tick rate features by default (#1247) 2024-03-06 17:04:05 +00:00
Jesse Braham
8841d82ead
Allow specifying an output directory when building documentation (#1241) 2024-03-05 16:10:46 +00:00
Juraj Sadel
0e0035c886
Update esp-hal/README (#1228)
* Remove referecnes to chip-specific HALs, briefly describe esp-hal tree and add quickstart

* Review comments

* Update esp-hal/README.md

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

* Update esp-hal/README.md

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>

* Update esp-hal/README.md

Co-authored-by: Scott Mabin <scott@mabez.dev>

* review comments 2

* link examples/README

* Mostly rewrite `esp-hal/README.md` (oops :) ) (#4)

* Mostly rewrite `esp-hal/README.md` (oops :) )

* Fix a typo

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-03-04 10:12:35 -08:00
Jesse Braham
e1c82065a5
Initial version of README.md for the examples package (#1237)
* Initial version of `README.md` for the `examples` package

* Minor grammatical nitpicks
2024-03-04 14:31:13 +00:00
Jesse Braham
3b6a3cf3a4
Fix some clippy/build warnings, clean up root Cargo manifest (#1230)
* Remove old package names from workspace exclude list

* Fix warning in `esp-hal-procmacros`

* Resolve clippy warnings
2024-03-01 05:56:02 -08:00
Jesse Braham
bfb530d3a3 Use newest published PACs 2024-02-28 19:01:37 +00:00
Kaspar Schleiser
3ec0f3b8ba
embassy: introduce InterruptExecutor::spawner() (#1211)
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-02-28 17:15:52 +00:00
Björn Quentin
e81957ee98
Make xtask work on Windows, add run-example command (#1215)
* Make xtask work on Windows, add `run-example` command

* Fix xtask for non-Windows users

* Use `find_map`
2024-02-28 17:04:29 +00:00
Timo
0c99d8bb60
Add TimerWakeupSource for the esp32-c6 deepsleep. (#1201) 2024-02-28 16:59:49 +00:00
Juraj Sadel
5b5770965e
Update README to match with unification changes (#1217)
* Remove referecnes to chip-specific HALs and briefly describe crates in ESP-HAL package

* review comments

* review comments 2
2024-02-28 16:44:35 +00:00
Jesse Braham
043baa7c4b
Remove repo-level VS Code settings, ignore settings files moving forward (#1223) 2024-02-28 16:21:01 +00:00
Björn Quentin
12176dbfff
Uart init (#1213)
* UART init for all chips

* Avoid UART reset for the console UART

* Fix comments

* CHANGELOG.md entry

* Introduce a `uart_peripheral_reset` function
2024-02-28 14:48:51 +01:00
Kirill Mikhailov
0240e2b597
Ensuring that the random number generator is TRNG. (#1200)
* Refactor `RNG` driver, ensure randomness for C6 and H2

* WIP: 3 more chips

* Finish

* Redesign

fmt

clippy

* Adjusting for review

+ changelog
2024-02-28 13:46:32 +00:00
Björn Quentin
76135cf8f9
Fix I2C read for ESP32-S2 (#1214)
* Fix I2C read for ESP32-S2

* CHANGELOG.md entry
2024-02-28 14:19:47 +01:00
Jesse Braham
6a663f8b1a
Unify: Remove the chip-specific HAL packages, adapt esp-hal for direct use [1/?] (#1196)
* Remove the chip-specific HAL packages

* Update some doc comments which were missed, fix build script for ESP32/S2

* Refactor/update `esp-hal-procmacros`

* Create the `examples` package, add back all of the previously existing examples

* Use `xtask` automation package for checking examples and documentation in CI

* Combine the `rt-riscv` and `rt-xtensa` features into a single `rt` feature

* Bump MSRV to 1.76.0 (shocking!)

* Re-document the features for the HAL

* No need to re-export the `riscv` package like this

* Make clippy happy, improve CI clippy checks

* Update `CHANGELOG.md`

* riscv: zero bss

Co-authored-by: Björn Quentin <bjoernQ@users.noreply.github.com>

* Address a number of review comments

* Correct pin number in `hello_rgb` example for ESP32-C3

* Address the remaining review comments

* More small tweaks/improvements

* Fix RMT examples (#11)

* Fix RMT examples

* Remove logger-init

* Make I2S examples work on ESP32 (#12)

* Make I2S examples work on ESP32

* Remove logger init

* Fix the direct-vectoring examples on all RISCV chips (#10)

* Update GPIOs for some examples...

* Embassy timer example fixes (#13)

* Switch to generic queue instead of integrated for all examples

* changelog

* Update GPIO in another example, make `rustfmt` happy

* Fix ESP32-S2 PSRAM

* Avoid UART0 and SPI flash pins (#15)

* Avoid UART0 and SPI flash pins

* Fix spi_eh1_device_loopback for non-ESP32

* Update examples/src/bin/gpio_interrupt.rs

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

---------

Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
Co-authored-by: Björn Quentin <bjoernQ@users.noreply.github.com>
Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de>
Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
2024-02-27 14:10:11 +00:00
Fan Jiang
9a95c0aa88
Add option to configure the device driver IRAM placement (RFC) (#1096)
* SPI RAM patch

* SPI in IRAM

* Add DMA functions to IRAM

* Try fixing the interrupt latency issue

* Revert changes

* Rename the option name to `optimize-spi-in-iram`

* Fix clippy warning

* Fix typo
2024-02-21 16:04:54 +00:00
Felix Richter
4bc1aaaefa
fix esp32c3 uart initialization (#1156)
* fix esp32c3 uart initialization

Implement uart initialization according to the [esp32c3 technical
reference manual section 26.5.2.1](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#subsubsection.26.5.2)

* add fix to changelog
2024-02-21 14:44:37 +00:00
Juraj Sadel
9378639e4c
C6: LP_I2C basic driver (#1185)
* After more analysis and coding

* More work is done, writing/reading WIP

* `write` prototype done, small fixes. Read next

* pre-rebase

* Rebased and updated

* Pre-final state of driver

* More work (near-final state) done

* WIP

* WIP

* working

* cleanup

* changelog

* address review comments

* remove Option from conjure and improve lp-i2c example description

---------

Co-authored-by: Kirill Mikhailov <konnor1980@yandex.ru>
2024-02-21 14:18:54 +00:00
Björn Quentin
bc2f1a02cc
Fix circular DMA (again) and small I2S improvements (#1189)
* Fix calculation of available buffer

* Lift requirement of circular DMA min buffer

* Have a separate set of convenience macros for circular DMA buffers

* Prefer `addr_of_mut!`

* Add `push_with` for I2S TX

* CHANGELOG.md
2024-02-21 12:20:19 +00:00
Scott Mabin
c18b5b4e78
Allow building on stable for riscv with the async feature (#1187) 2024-02-20 09:16:56 +00:00
Björn Quentin
5b3cf02153
Improve I2C NACK detection (#1184)
* Improve I2C NACK detection

* CHANGELOG.md entry
2024-02-19 16:13:39 +00:00
Björn Quentin
6712aa55f7
Wait for update before reading timer count (#1183)
* Wait for update before reading timer count

* CHANGELOG.md entry

* Wait for update before reading timer count (ESP32)

* Use latest PACs

* CHANGELOG.md fix
2024-02-19 14:51:58 +00:00
Scott Mabin
09fef6acc4
Fix get raw core and document the finer details (#1175)
* Fix and document the get_core functions

* Fix UNUSED_THREAD_ID_VALUE to allow proper operation on the esp32p4

* fix multicore cfgs

* changelog

* fixup cfgs and update comments
2024-02-19 12:00:14 +00:00
Björn Quentin
e3147b0322
Address latest Clippy lints (#1182) 2024-02-19 10:07:36 +00:00
Felix Richter
b0bb0ab1ce
wait for timer value to be latched for esp32(c3/c6) (#1178)
* wait for timer value to be latched for esp32(c3/c6)

* update changelog to include timer fix
2024-02-19 08:16:49 +00:00
Björn Quentin
172d2b8777
estimate_xtal_frequency for C6/H2 (#1174)
* `estimate_xtal_frequency` for C6/H2

* CHANGELOG.md entry
2024-02-16 12:53:24 +00:00
Jesse Braham
0483b47e77
Add build-package and bump-version subcommands to xtask package (#1172)
* Implement builder pattern for cargo command-line args, refactoring

* Add an `xtask` subcommand to build a package (not its examples)

* Add an `xtask` subcommand to bump the versions of packages
2024-02-16 11:21:31 +00:00
Björn Quentin
2a5996f408
Fix ESP32 hello_rgb example (#1173)
* Fix ESP32 hello_rgb example

* CHANGELOG.md
2024-02-16 11:18:16 +00:00
Björn Quentin
6e68da0f4d
ESP32-S3: Use 32K ICACHE (#1169)
* ESP32-S3: Use 32K ICACHE

* CHANGELOG.md entry
2024-02-14 15:35:23 +00:00
Sergio Gasquez Arcos
32824422a1
Autodetect xtal-freq (#1165)
* feat: Autodetect xtal-freq

* docs: Update changelog

* style: Clippy lints

* feat: Remove XtalClock::RtcXtalFreq24M variant

* feat: Adjust visibility of estimate_xtal_frequency

* feat: Remove xtal freq features
2024-02-14 11:09:35 +00:00
Jesse Braham
2b8db5c2c2
Add an xtask subcommand for building documentation (#1160)
* Fix a silly mistake from the initial implementation

* Improve the `build-examples` subcommand, make it usable with other packages

* Add a `build-documentation` subcommand

* Update `README.md`

* Add toolchain modifier when required
2024-02-13 22:39:01 +00:00
Jesse Braham
044b38e632
Remove clippy lint exceptions from CI workflow (#1167)
* Add `#[allow()]` attrs as needed to remove clippy exceptions in CI

* Remove clippy exceptions in CI workflow
2024-02-13 10:44:31 -08:00
Jesse Braham
ebdd59b0ae
Add the xtask package, implement automation for building examples (#1157)
* Create the `xtask` package, add command for building examples

* Do not perform changelog check for `xtask` package changes

* Fix unrelated `rustfmt` error
2024-02-12 15:38:19 +00:00
W Etheredge
c92d69cb09
esp-hal-smartled: Calculate cycles from clocks (#1154) 2024-02-12 15:36:30 +00:00
Jesse Braham
8903b1ea8b Update PACs to their latest (unpubished) versions an make required changes 2024-02-08 17:50:02 +00:00
Scott Mabin
42bfd4950a
Fix sealing for Rsa/Aes (#1149) 2024-02-08 15:14:00 +00:00
Björn Quentin
66090ac3b9
Remove (unused) heapless dependency (#1148) 2024-02-08 13:24:48 +00:00
Björn Quentin
ca58da4fa1
Fix circular DMA (#1144)
* Fix circular DMA

* CHANGELOG.md entry

* Fix CHANGELOG.md
2024-02-08 12:02:25 +00:00
Scott Mabin
f6ba8c6c53
Appease clippy (#1147)
* Fix clippy

* unify sealing

* more improvements

* fmt

* rebase

* h2adcefuse
2024-02-08 11:50:06 +00:00
Alexander Ananiev
3a456bb9dd
Add type for gpio::AnyPin (#1067)
This makes it possible to safely implement the InputPin and OutputPin
traits for AnyPin. Now you can convert any pin to AnyPin with the
appropriate type and use it in other library modules

Added:
- Peripheral implementation for AnyPin
- Implementation of Pin for AnyPin
- Implementation of OutputPin for AnyPin with type IsOutputPin
- Implementation of InputPin for AnyPin with type IsInputPin
- Upgrade types for AnyPin (for example InputOutputAnalogPinType ->
InputOutputPinType)
- Implementation of From<Gpio> for AnyPin with the appropriate type

Changed:
- The Gpio::degrage method returns AnyPin with the appropriate type
2024-02-08 07:29:30 +00:00
Kirill Mikhailov
a08b38d231
Adding clock support for ESP32-P4 (#1145)
* Begin adding clock support for ESP32-P4

* WIP

* WIP: more functionality added, minor example update

* WIP state (testing)

* Format

* Finalizing + populating reset_reason enum

* Update esp-pacs dependency

---------

Co-authored-by: Jesse Braham <jesse@beta7.io>
2024-02-07 19:35:25 +00:00
Jesse Braham
ac07f3c460
Document the features of the remaining packages (#1143)
* Document features for `esp-riscv-rt` package

* Document features for `esp-hal-smartled`

* Document features for `esp-hal-procmacros`
2024-02-06 07:12:05 -08:00
Jesse Braham
0f12654f4a
Refactor the Trace driver to be generic around its peripheral (#1140)
* Use patched version of PAC for C6/H2

* Rename `TRACE` peripheral to `TRACE0`

* Refactor `Trace` driver to be generic around its peripheral

* Update `CHANGELOG.md`
2024-02-06 09:14:15 +00:00
Jesse Braham
285cfe4c5d
"Fix" clippy checks in CI, resolve a bunch of clippy warnings (#1134)
* Fix a bunch of `clippy` warnings in the `esp-hal` build script

* Resolve most clippy warnings for ESP32 (no features)

* Do the same for ESP32-S2/S3...

* Same for C2/C3...

* CI check for clippy now actually works (and passes!) for Xtensa

* RISC-V chips (except P4) now pass clippy in CI

* Add some safety doc comments which I forgot to write

* The `PwmPeripheral` trait is no longer `unsafe`, and is instead now sealed
2024-02-02 16:00:06 +00:00
Björn Quentin
c0f9169879
Support Rust's stack-protector feature (#1135)
* Support Rust's `stack-protector` feature

* Update changelogs
2024-02-02 13:56:39 +00:00
Jesse Braham
a586cb311e
Rename the ADC constructor to new, make it infallible (#1133)
* Rename the ADC constructor to `new`, make it infallible

* Update `CHANGELOG.md`
2024-02-01 11:51:05 +00:00
Jesse Braham
f36e2e72d6 ESP32-P4: Use commit hash from upstream repo for esp-backtrace patch 2024-01-31 20:08:36 +00:00
Jesse Braham
eff8f4b222
Unify: rename the esp-hal-common package to esp-hal [0/?] (#1131)
* Rename the `esp-hal-common` package to `esp-hal`

* Update all references to `esp-hal-common`

* Update `CHANGELOG.md`
2024-01-31 16:26:20 +00:00
jneem
858fd4fb1f
Add docs.rs metadata (#1129)
* Add docs.rs metadata

* changelog

* add p4

* Fix targets for c6, h2, p4
2024-01-31 14:16:09 +00:00
jneem
6f73815043
Rmt channels 2 (#959)
* Remove RMT channel's generic parameter

* changelog
2024-01-30 15:30:35 +00:00
Jesse Braham
c42a96c987
Refactor DMA to make API more consistent across devices (#1125)
* Make the `DMA` peripheral API more consistent

* Update examples for devices with `PDMA`

* Update examples for devices with `GDMA`

* Update `CHANGELOG.md`

* Update example after rebasing
2024-01-30 14:58:48 +00:00
Dominic Fischer
b8c6dcea2e
Add LCD_CAM I8080 Driver (#1086)
* LCD_CAM I8080 POC

* Hush CI

* Apply user provided frequency

* Expose bit and byte order

* Properly support command and dummy phases

* Expose clock edge settings

* Allow background transfers

* Add support for both 8 bit and 16 bit

* Remove unnecessary interrupt usage

* Expose all config

* Add LcdCamPeripheral

* Fix up register modification

* Remove 2^13 limit on data phase

* Make example a bit more interesting

* Add DMA peripheral trait bounds

* Use raw interrupts

* Write module level docs

* Improve example doc
2024-01-30 11:21:27 +00:00
Dániel Buga
deb9f21284
Rework DMA descriptors (#1054) 2024-01-30 08:03:47 +00:00
Fan Jiang
1b0fc6b3f3
Fix get_raw_core (#1126) 2024-01-30 07:02:11 +00:00
Dániel Buga
fabb631b7d
Fix tick rates not being applied (#1124) 2024-01-29 17:53:35 +00:00
Kirill Mikhailov
be7b461ae2
RngCore trait is implemented (#1122)
* WIP

made randomness ensuring function
implemented RngCore trait (final version i guess)

* Revert part of changes and leave TODO comment

Changelog entry

Get rid of warning
2024-01-29 17:51:53 +00:00
Bryant Chandler
3eb296c892
Allow for splitting of the USB Serial JTAG peripheral into tx/rx components (continuation) (#1116)
* Allow for splitting of the USB Serial JTAG peripheral into tx/rx components

* Update `CHANGELOG.md`

* Split single waker into tx/rx wakers

* Fix interrupt bug and update embassy example

The wakers were written to trigger opposite, so the rx waker
would trigger for tx interrupts and vice versa.

Also update the embassy example to run read/write in
separate tasks.

* rustfmt

---------

Co-authored-by: Jesse Braham <jesse@beta7.io>
2024-01-26 14:09:09 +00:00
Sergio Gasquez Arcos
6ffce31250
docs: Update lp cores crates (#1119) 2024-01-26 14:02:53 +00:00
Jesse Braham
9bf70ff792
Combine the esp-ulp-riscv-hal and esp32c6-lp-hal packages (#1115)
* Combine `esp-ulp-riscv-hal` and `esp32c6-lp-hal` into a single package

* Update LP core examples

* Update CI workflow

* Fix `LP_UART` example
2024-01-26 13:46:51 +00:00
Jesse Braham
f52aa1351c
Refactor the analog module (#1100)
* Create virtual peripherals for `ADC`/`DAC`

* Refactor the `analog::dac` module

* Refactor the `analog::adc` module

* Decouple the ADC driver from the `embedded-hal` traits

* Update `CHANGELOG.md`

* Seal the `AdcCalScheme` trait, reduce visibility of `AdcCalEfuse` trait

* Remove `APB_SARADC`/`SENS` peripherals from the `Peripherals` struct
2024-01-25 16:46:27 +00:00
Björn Quentin
43f212dc72
ESP32-P4: Enable efuse (#1114)
* ESP32-P4: Enable efuse

* CHANGELOG.md entry
2024-01-25 16:45:45 +00:00
Juraj Sadel
bc96351c17
C6: Basic LP_UART driver (#1113)
* WIP

* Add basic LP_UART C6 driver

* Add lp-uart example for C6

* modify entry macro and fmt

* final cleanups

* revert lp_core_basic example and add lp_core_uart and uart examples

* changelog

* review changes

* second changelog

---------

Co-authored-by: Jesse Braham <jesse@beta7.io>
2024-01-25 16:22:14 +00:00
Björn Quentin
de54a17275
Initial support for CLIC (#1112)
* Initial support for CLIC

* CHANGELOG.md entry

* Explain MCAUSE CSR for CLIC
2024-01-25 15:29:37 +00:00
Björn Quentin
f542eb48bb
ESP32-P4: Initial GPIO support (#1109)
* ESP32-P4: Initial GPIO support

* CHANGELOG.md entry
2024-01-23 17:56:01 +00:00
Jesse Braham
c793f99e30
Update documentation/comments in soc::peripherals modules (#1108) 2024-01-23 16:09:09 +00:00
Jesse Braham
5391e68668
Use the document-features crate instead of manually writing package feature docs (#1107)
* Add `document-features` dependency to all HAL packages

* Update package-level documentation for each chip-specific HAL package

* Document package features for all chip-specific HALs
2024-01-23 15:49:06 +00:00
Remmirad
76b5d77505
Implement embedded_hal 1 pwm traits for ledc channel (#1097)
* Implement eh_1 pwm traits for ledc channel

* Add changelog entry

* Update CHANGELOG.md

---------

Co-authored-by: Remmirad <remmirad@posteo.net>
2024-01-23 14:15:50 +00:00
Jesse Braham
e5cd1bd33e
Add initial support for the ESP32-P4 (#1101)
* Add `esp32p4` feature to `esp-hal-procmacros`

* Add `esp32p4` feature to `esp-hal-common`

* Create the `esp32p4-hal` package

* Add ESP32-P4 to CI workflow

* Fix a silly typo :)

* Update `CHANGELOG.md`
2024-01-22 15:28:05 +00:00
Scott Mabin
8ac075a0aa
Add USB_EXCHG_PINS efuse workarounds for esp32c3 and esp32s3 (#1104)
* Add USB_EXCHG_PINS efuse workarounds for esp32c3 and esp32s3

* changelog
2024-01-22 10:32:56 +00:00
Jesse Braham
c448680054 Begin next release cycle 2024-01-19 15:00:11 +00:00
Jesse Braham
567a44f28c
New package releases (#1098) 2024-01-19 14:40:16 +00:00
Jesse Braham
a5a58291e3
Do not invert ADC readings when using ESP32 (#1093)
* Do not invert ADC readings when using ESP32

* Update `CHANGELOG.md`
2024-01-19 07:13:27 +00:00
Jesse Braham
99c46d6a4e Update CHANGELOG.md 2024-01-18 17:30:30 +00:00
Jesse Braham
d3674f5724 Update to latest smart-leds-trait and smart-leds packages 2024-01-18 17:30:30 +00:00
Jesse Braham
0e927d25cf
No longer depend on embassy-time (#1092)
* No longer depend on `embassy-time`

* Update `CHANGELOG.md`
2024-01-17 16:45:11 +00:00
Björn Quentin
ebe4149c39
Fix time-driver-timg timer1 (#1091)
* Fix time-driver-timg timer1

* CHANGELOG.md entry

* Fix examples

* Fix CHANGELOG.md
2024-01-17 16:20:46 +00:00
Scott Mabin
4ea4a809fd Document msrv toolchain per chip hal 2024-01-17 15:30:48 +00:00
Sycrosity
842eb7c92e
Update embassy to its embedded-* v1.0.0 versions (#1076)
* update embassy in Cargo.toml and add embassy-time-driver

* fix embassy-time for esp-hal-common

* update CHANGELOG.md

* fix clippy warning by removing manual adc implimentation for esp32

* undo change, fixing clippy error by removing unused use statement

* remove embassy crates-io patches

* remove a remaining embassy patch

* Update embassy-time version in esp-hal-common/Cargo.toml

Co-authored-by: Scott Mabin <scott@mabez.dev>

* remove the remaining embassy patches

* remove embassy-time as a dependency for esp*-hal

---------

Co-authored-by: Scott Mabin <scott@mabez.dev>
2024-01-16 20:25:22 +00:00
Björn Quentin
a23d6a05a6
Fix stack-top calculation for app-core (#1081)
* Fix stack-top calculation for app-core

* CHANGELOG.md entry
2024-01-15 14:46:34 +00:00
yanshay
0f9e2466ec
Add support for 80Mhz psram, selected using 'psram-80mhz' feature (#1073)
* Add support for 80Mhz psram, selected using 'psram-80mhz' feature

Default stays 40 MHz

* Added changelog regarding 80MHz PSRAM support

* Add 80Mhz support also to octal psram

* Add documentation for 80Mhz psram in lib.rs

* Linker script adjustments needed for wifi drivers (#1074)

* Add `embedded-io` feature to each chip-specific HAL (#1072)

* Add `embedded-io` feature to each chip-specific HAL

* Update `CHANGELOG.md`

* Update to `1.0.0` releases of `embedded-hal-*` packages (#1068)

* Update to `1.0.0` releases of `embedded-hal-*` packages

* Update `CHANGELOG.md`

* Added changelog regarding 80MHz PSRAM support

---------

Co-authored-by: Björn Quentin <bjoernQ@users.noreply.github.com>
Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-01-12 14:12:47 +00:00
Torben Hansing
944ce9a33e
Make GPIO4 an InputOutputAnalog pin on ESP32 (#1079)
* Make GPIO4 an InputOutputAnalog pin on ESP32

* Add the change to the CHANGELOG.md

* Use nightly rustfmt to format the file
2024-01-12 13:49:07 +00:00
Jesse Braham
63408cf8a3
Update to 1.0.0 releases of embedded-hal-* packages (#1068)
* Update to `1.0.0` releases of `embedded-hal-*` packages

* Update `CHANGELOG.md`
2024-01-11 14:33:23 +00:00
Jesse Braham
c53f3095ec
Add embedded-io feature to each chip-specific HAL (#1072)
* Add `embedded-io` feature to each chip-specific HAL

* Update `CHANGELOG.md`
2024-01-11 14:03:04 +00:00
Björn Quentin
df1374dd1a
Linker script adjustments needed for wifi drivers (#1074) 2024-01-11 11:04:36 +00:00
Jesse Braham
6afc988f88
Ignore changes to CHANGELOG.md files for the CI workflow (#1070) 2024-01-10 13:47:09 +00:00
Kirill Mikhailov
fdc1dbfa1d
Unify the low-power peripheral names (RTC_CNTL and LP_CLKRST to LPWR) (#1064)
* WIP

* Adjusting to changes in driver

* Adding CHANGELOG entry
2024-01-08 14:00:26 +00:00
Jesse Braham
cf66cc05fc
Move initialization functions into esp-hal-common package's soc module (#1049)
* Move initialization functions into `esp-hal-common` package's `soc` module

* Simplify module paths
2024-01-03 15:38:33 +00:00
Dániel Buga
e9d6a2157a
C6 deep sleep driver MVP (#918)
* Restructure sleep-related files

* Port most of esp-idf deep sleep code

* Add example

* Remove extra newline

* Hide RtcioWakeupSource from esp32 api

* Explain commented constants

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
2024-01-03 15:14:17 +00:00
Jesse Braham
62ae9dc05c
Add rt-riscv and rt-xtensa features to esp-hal-common (#1057)
* Add `rt-riscv` and `rt-xtensa` features to `esp-hal-common` to allow enabling/disable runtime support

* Update the CI workflow to check the chip-specific HAL packages without default features

* Update `CHANGELOG.md`
2024-01-03 14:24:05 +00:00
liebman
2e2d67f315
correct errata36() for gpio 32 and 33 (#1053)
* correct errata36() for gpio 32 and 33

* update changelog
2023-12-28 07:26:48 +00:00
Juraj Sadel
07b2b0d9ea
Check missing embassy_XX examples to the CI (#1048)
* CI: add missing examples

* H2: remove embassy-time-systick feature from embassy_i2c example
2023-12-20 14:24:15 +00:00
Kamil Koczurek
2b2c001e7a
efuse: allow overriding base mac (#1044)
ESP-IDF defines several kinds of mac addresses, but this doesn't map
well to the esp-hal design, because:
1. This isn't actually required by hardware.
2. Wifi / Ble drivers are external to esp-hal.

Hence this patch only allows overriding the base mac and does not
introduce the concept of other types of mac addresses.
2023-12-20 13:58:31 +00:00
Juraj Sadel
244c74776a
Don't enable async interrupts without async feature (#1042)
* only enable interrupts if the async feature is present

* remove warnings and fmt

* changelog
2023-12-19 16:34:17 +00:00
Björn Quentin
8b01421c8e
Fix/c6 h2 interrupt disabling (#1040)
* Remove debug print

* C6/H2: Fix interrupt disabling

* CHANGELOG.md entry
2023-12-19 13:39:25 +00:00
Björn Quentin
36954e740d
Merge .text_init into .text on RISC-V (#1038)
* Merge `.text_init` into `.text`

* Only merge `init.*` into `.text` for RISC-V
2023-12-18 15:15:59 +00:00
Dániel Buga
260c882b08
C6 PMU startup configuration (#974)
* Implement a bunch of missing startup code

* Extract peripheral address retrieval

* Clean up manual register manipulation

* Add missing PMU related setup

* Changelog

* Clean up revision check

* Fix build

* Add note about PMU setup code source

* Use macros to deduplicate hp/lp system setup

* Clean up a bit

* Initialize the correct register in modem_clock_hal_select_wifi_lpclk_source
2023-12-15 16:18:37 +00:00
ripytide
9084d1eeaf
remove double &mut for SetDutyCycle impl on PwmPin (#1033)
* remove double &mut for SetDutyCycle impl on PwmPin

* add entry to changelog
2023-12-15 14:39:56 +00:00
Jesse Braham
82c579eb14
Clean up example imports (#1027)
* Don't import directly from `esp-hal-common` in examples

* Do no alias the HAL packages in examples
2023-12-14 15:56:04 +00:00
Jesse Braham
58baecc0d2
Assert that the hardware and software digests match for SHA examples (#1026) 2023-12-14 15:04:46 +00:00
Jesse Braham
1e875c9e9e Begin next release cycle 2023-12-13 18:38:13 +00:00
1185 changed files with 142220 additions and 84523 deletions

4
.cargo/config.toml Normal file
View File

@ -0,0 +1,4 @@
[alias]
xtask = "run --package xtask --"
xfmt = "xtask fmt-packages"
qa = "xtask run-example qa-test"

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ["bug", "status:needs-attention"]
assignees: ''
---
## Bug description
<!-- A clear and concise description of what the bug is. -->
## To Reproduce
<!-- Steps to reproduce the behavior. -->
1. ...
2. ...
<!-- Please share the minimal repro of the issue where the bug can be reproduced. -->
<!-- Make sure you are able to reproduce the bug in the `main` branch, too. -->
## Expected behavior
<!-- A clear and concise description of what you expected to happen. Attach screenshots if needed. -->
## Environment
- Target device: [e.g. ESP32-S3] <!-- Use `espflash board-info` to get the target device iformation. -->
- Crate name and version: [e.g. esp-hal 0.20.0]

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: Ask questions in Matrix channel (Recommended)
url: https://matrix.to/#/#esp-rs:matrix.org
about: Ask any questions directly in our Matrix channel.
- name: Ask questions in GitHub Discussions
url: https://github.com/esp-rs/esp-hal/discussions/new
about: Post your questions and engage in discussions via GitHub.

View File

@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ["enhancement", "status:needs-attention"]
assignees: ''
---
## Motivations
<!-- If your feature request is related to a problem, please describe it. -->
## Solution
<!-- Describe the solution you'd like. -->
## Alternatives
<!-- Describe any alternative solutions or features you've considered. -->
## Additional context
<!-- Add any other context or screenshots about the feature request here. -->

View File

@ -1,18 +1,22 @@
## Thank you!
## Thank you for your contribution!
Thank you for your contribution.
Please make sure that your submission includes the following:
We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:
### Must
### Submission Checklist 📝
- [ ] I have updated existing examples or added new ones (if applicable).
- [ ] I have used `cargo xtask fmt-packages` command to ensure that all changed code is formatted correctly.
- [ ] My changes were added to the [`CHANGELOG.md`](https://github.com/esp-rs/esp-hal/blob/main/esp-hal/CHANGELOG.md) in the **_proper_** section.
- [ ] I have added necessary changes to user code to the [Migration Guide](https://github.com/esp-rs/esp-hal/blob/main/esp-hal/MIGRATING-0.21.md).
- [ ] My changes are in accordance to the [esp-rs API guidelines](https://github.com/esp-rs/esp-hal/blob/main/documentation/API-GUIDELINES.md)
- [ ] The code compiles without `errors` or `warnings`.
- [ ] All examples work.
- [ ] `cargo fmt` was run.
- [ ] Your changes were added to the `CHANGELOG.md` in the proper section.
- [ ] You updated existing examples or added examples (if applicable).
- [ ] Added examples are checked in CI
#### Extra:
- [ ] I have read the [CONTRIBUTING.md guide](https://github.com/esp-rs/esp-hal/blob/main/documentation/CONTRIBUTING.md) and followed its instructions.
### Nice to have
### Pull Request Details 📖
- [ ] You add a description of your work to this PR.
- [ ] You added proper docs for your newly added features and code.
#### Description
Please provide a clear and concise description of your changes, including the motivation behind these changes. The context is crucial for the reviewers.
#### Testing
Describe how you tested your changes.

View File

@ -0,0 +1,68 @@
name: Build and Check
description: Build and check the esp-hal and esp-lp-hal pacakges for a specified device
inputs:
device:
description: "Device SOC"
required: true
target:
description: "Target"
required: true
toolchain:
description: "Toolchain channel"
required: true
runs:
using: "composite"
steps:
- name: Set up cargo environment
shell: bash
run: |
# Convert the target triple from kebab-case to SCREAMING_SNAKE_CASE:
big_target=$(echo "${{ matrix.device.target }}" | tr [:lower:] [:upper:] | tr '-' '_')
# Set the *target specific* RUSTFLAGS for the current device:
echo "CARGO_TARGET_${big_target}_RUSTFLAGS=-Dwarnings" >> $GITHUB_ENV
# Linting toolchain (stable cant build documentation)
if [ "${{ inputs.toolchain }}" == "nightly" ]; then
echo "LINTING_TOOLCHAIN=+nightly" >> $GITHUB_ENV
else
echo "LINTING_TOOLCHAIN=+esp" >> $GITHUB_ENV
fi
# Clippy and docs checks
- name: Clippy
shell: bash
run: cargo $LINTING_TOOLCHAIN xtask lint-packages --chips ${{ inputs.device }}
- name: Check doc-tests
shell: bash
run: cargo $LINTING_TOOLCHAIN xtask run-doc-test esp-hal ${{ inputs.device }}
- name: Check documentation
shell: bash
run: cargo $LINTING_TOOLCHAIN xtask build-documentation --packages esp-hal --chips ${{ inputs.device }}
# Build all supported examples for the low-power core first (if present):
- name: Build prerequisite examples (esp-lp-hal)
shell: bash
if: contains(fromJson('["esp32c6", "esp32s2", "esp32s3"]'), inputs.device)
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-lp-hal ${{ inputs.device }}
- name: Check esp-lp-hal documentation
shell: bash
if: contains(fromJson('["esp32c6", "esp32s2", "esp32s3"]'), inputs.device)
run: cargo $LINTING_TOOLCHAIN xtask build-documentation --packages esp-lp-hal --chips ${{ inputs.device }}
# Make sure we're able to build the HAL without the default features
# enabled:
- name: Build (no features)
shell: bash
run: |
cargo xtask build-package \
--no-default-features \
--toolchain=${{ inputs.toolchain }} \
--features=${{ inputs.device }} \
--target=${{ inputs.target }} \
esp-hal
- name: Build (examples)
env:
CI: 1
shell: bash
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }} --debug
- name: Build (qa-test)
env:
CI: 1
shell: bash
run: cargo +${{ inputs.toolchain }} xtask build-examples qa-test ${{ inputs.device }} --debug

View File

@ -1,7 +1,14 @@
name: Change log check
name: Changelog check
on:
pull_request:
# We will not track changes for the following packages/directories.
paths-ignore:
- "/examples/"
- "/extras/"
- "/hil-tests/"
- "/resources/"
- "/xtask/"
# Run on labeled/unlabeled in addition to defaults to detect
# adding/removing skip-changelog labels.
types: [opened, reopened, labeled, unlabeled, synchronize]
@ -12,10 +19,162 @@ jobs:
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- uses: dangoslen/changelog-enforcer@v3
- name: Check which package is modified
uses: dorny/paths-filter@v3
id: changes
with:
changeLogPath: CHANGELOG.md
filters: |
esp-alloc:
- 'esp-alloc/**'
esp-backtrace:
- 'esp-backtrace/**'
esp-build:
- 'esp-build/**'
esp-config:
- 'esp-config/**'
esp-hal:
- 'esp-hal/**'
esp-hal-embassy:
- 'esp-hal-embassy/**'
esp-hal-procmacros:
- 'esp-hal-procmacros/**'
esp-ieee802154:
- 'esp-ieee802154/**'
esp-lp-hal:
- 'esp-lp-hal/**'
esp-metadata:
- 'esp-metadata/**'
esp-println:
- 'esp-println/**'
esp-riscv-rt:
- 'esp-riscv-rt/**'
esp-storage:
- 'esp-storage/**'
esp-wifi:
- 'esp-wifi/**'
xtensa-lx:
- 'xtensa-lx/**'
xtensa-lx-rt:
- 'xtensa-lx-rt/**'
- name: Check that changelog updated (esp-alloc)
if: steps.changes.outputs.esp-alloc == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-alloc/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the CHANGELOG.md file."
missingUpdateErrorMessage: "Please add a changelog entry in the esp-alloc/CHANGELOG.md file."
- name: Check that changelog updated (esp-backtrace)
if: steps.changes.outputs.esp-backtrace == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-backtrace/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-backtrace/CHANGELOG.md file."
- name: Check that changelog updated (esp-build)
if: steps.changes.outputs.esp-build == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-build/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-build/CHANGELOG.md file."
- name: Check that changelog updated (esp-config)
if: steps.changes.outputs.esp-config == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-config/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-config/CHANGELOG.md file."
- name: Check that changelog updated (esp-hal)
if: steps.changes.outputs.esp-hal == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-hal/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-hal/CHANGELOG.md file."
- name: Check that changelog updated (esp-hal-embassy)
if: steps.changes.outputs.esp-hal-embassy == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-hal-embassy/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-hal-embassy/CHANGELOG.md file."
- name: Check that changelog updated (esp-hal-procmacros)
if: steps.changes.outputs.esp-hal-procmacros == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-hal-procmacros/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-hal-procmacros/CHANGELOG.md file."
- name: Check that changelog updated (esp-ieee802154)
if: steps.changes.outputs.esp-ieee802154 == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-ieee802154/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-ieee802154/CHANGELOG.md file."
- name: Check that changelog updated (esp-lp-hal)
if: steps.changes.outputs.esp-lp-hal == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-lp-hal/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-lp-hal/CHANGELOG.md file."
- name: Check that changelog updated (esp-println)
if: steps.changes.outputs.esp-println == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-println/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-println/CHANGELOG.md file."
- name: Check that changelog updated (esp-riscv-rt)
if: steps.changes.outputs.esp-riscv-rt == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-riscv-rt/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-riscv-rt/CHANGELOG.md file."
- name: Check that changelog updated (esp-storage)
if: steps.changes.outputs.esp-storage == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-storage/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-storage/CHANGELOG.md file."
- name: Check that changelog updated (esp-wifi)
if: steps.changes.outputs.esp-wifi == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: esp-wifi/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the esp-wifi/CHANGELOG.md file."
- name: Check that changelog updated (xtensa-lx)
if: steps.changes.outputs.xtensa-lx == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: xtensa-lx/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the xtensa-lx/CHANGELOG.md file."
- name: Check that changelog updated (xtensa-lx-rt)
if: steps.changes.outputs.xtensa-lx-rt == 'true'
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: xtensa-lx-rt/CHANGELOG.md
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the xtensa-lx-rt/CHANGELOG.md file."

View File

@ -1,21 +1,31 @@
# NOTE:
#
# When adding support for a new chip to `esp-hal`, there are a number of
# updates which must be made to the CI workflow in order to reflect this; the
# changes are:
#
# 1.) In the 'esp-hal' job, add the name of the chip to the `matrix.soc` array.
# 1a.) If the device has a low-power core (which is supported in
# `esp-lp-hal`), then update the `if` condition to build prerequisites.
# 2.) In the 'msrv' job, add checks as needed for the new chip.
name: CI
on:
pull_request:
paths-ignore:
- "**/README.md"
push:
branches-ignore:
- "gh-readonly-queue/**"
paths-ignore:
- "**/README.md"
- "main"
merge_group:
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MSRV: "1.67.0"
MSRV: "1.83.0"
RUSTDOCFLAGS: -Dwarnings
DEFMT_LOG: trace
# Cancel any currently running workflows from the same PR, branch, or
# tag when a new workflow is triggered.
@ -27,543 +37,90 @@ concurrency:
jobs:
# --------------------------------------------------------------------------
# Check Packages
# Build Packages
esp-hal-smartled:
esp-hal:
name: esp-hal (${{ matrix.device.soc }})
runs-on: ubuntu-latest
env:
SSID: SSID
PASSWORD: PASSWORD
STATIC_IP: 1.1.1.1
GATEWAY_IP: 1.1.1.1
HOST_IP: 1.1.1.1
strategy:
fail-fast: false
matrix:
device: [
# RISC-V devices:
{ soc: "esp32c2", target: "riscv32imc-unknown-none-elf", toolchain: "stable" },
{ soc: "esp32c3", target: "riscv32imc-unknown-none-elf", toolchain: "stable" },
{ soc: "esp32c6", target: "riscv32imac-unknown-none-elf", toolchain: "stable" },
{ soc: "esp32h2", target: "riscv32imac-unknown-none-elf", toolchain: "stable" },
# Xtensa devices:
{ soc: "esp32", target: "xtensa-esp32-none-elf", toolchain: "esp" },
{ soc: "esp32s2", target: "xtensa-esp32s2-none-elf", toolchain: "esp" },
{ soc: "esp32s3", target: "xtensa-esp32s3-none-elf", toolchain: "esp" },
]
steps:
- uses: actions/checkout@v4
# Install the Rust toolchain for Xtensa devices:
- uses: esp-rs/xtensa-toolchain@v1.5
with:
ldproxy: false
version: 1.83.0.1
# Install the Rust stable toolchain for RISC-V devices:
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
toolchain: nightly
toolchain: stable
components: rust-src
- uses: esp-rs/xtensa-toolchain@v1.5
with:
ldproxy: false
override: false
- uses: Swatinem/rust-cache@v2
# Build all RISC-V targets:
- name: build (esp32c3)
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=esp32c3
- name: build (esp32c6)
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=esp32c6
- name: build (esp32h2)
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=esp32h2
# Build all Xtensa targets:
- name: build (esp32)
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32-none-elf --features=esp32,xtal-40mhz
- name: build (esp32s2)
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32s2-none-elf --features=esp32s2
- name: build (esp32s3)
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32s3-none-elf --features=esp32s3
# Ensure documentation can be built (requires a chip feature!)
- name: rustdoc
run: cd esp-hal-smartled/ && cargo doc -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=esp32c3
- name: Build and Check
uses: ./.github/actions/check-esp-hal
with:
device: ${{ matrix.device.soc }}
target: ${{ matrix.device.target }}
toolchain: ${{ matrix.device.toolchain }}
esp-riscv-rt:
extras:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
toolchain: nightly
components: rust-src
toolchain: stable
- uses: Swatinem/rust-cache@v2
- name: Build esp-riscv-rt (riscv32imc, no features)
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imc-unknown-none-elf
- name: Build esp-riscv-rt (riscv32imac, no features)
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imac-unknown-none-elf
- name: Build esp-riscv-rt (riscv32imc, all features)
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=ci
- name: Build esp-riscv-rt (riscv32imac, all features)
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=ci
# Ensure documentation can be built
- name: rustdoc
run: cd esp-riscv-rt/ && cargo doc
esp-ulp-riscv-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
- name: build esp-ulp-riscv-hal (esp32s2)
run: cd esp-ulp-riscv-hal/ && cargo build --release --features=esp32s2 --examples
- name: build esp-ulp-riscv-hal (esp32s3)
run: cd esp-ulp-riscv-hal/ && cargo build --release --features=esp32s3 --examples
# Ensure documentation can be built
- name: rustdoc
run: cd esp-ulp-riscv-hal/ && cargo doc --features=esp32s3
esp32-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
default: true
buildtargets: esp32
ldproxy: false
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
- name: build esp32-hal (no features)
run: cd esp32-hal/ && cargo build --examples
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32-hal (common features)
run: |
cd esp32-hal/
cargo build --examples --features=eh1,ufmt,log
cargo build --examples --features=eh1,ufmt,defmt
- name: check esp32-hal (embassy)
run: |
cd esp32-hal/
cargo check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
cargo check --example=embassy_multicore --features=embassy,embassy-time-timg0,embassy-executor-thread
cargo check --example=embassy_multicore_interrupt --features=embassy,embassy-time-timg0,embassy-executor-interrupt
cargo check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32-hal (embassy, async)
run: |
cd esp32-hal/
cargo check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
cargo check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
- name: check esp32-hal (embassy, log/defmt)
run: |
cd esp32-hal/
cargo check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
cargo check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
- name: check esp32-hal (psram)
run: cd esp32-hal/ && cargo check --example=psram --features=psram-2m --release # This example requires release!
# Ensure documentation can be built
- name: rustdoc
run: cd esp32-hal/ && cargo doc --features=eh1
esp32c2-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
# We also use this as an opportunity to verify that the examples link
# for each supported image format.
- name: build esp32c2-hal (no features)
run: cd esp32c2-hal/ && cargo build --examples
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32c2-hal (common features)
run: |
cd esp32c2-hal/
cargo +nightly build --examples --features=eh1,ufmt,log
cargo +nightly build --examples --features=eh1,ufmt,defmt
- name: check esp32c2-hal (async, systick)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
- name: check esp32c2-hal (async, timg0)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
- name: check esp32c2-hal (async, gpio)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c2-hal (async, multiprio)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32c2-hal (async, spi)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c2-hal (async, serial)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c2-hal (async, i2c)
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c2-hal (interrupt-preemption)
run: cd esp32c2-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
- name: check esp32c2-hal (direct-vectoring)
run: cd esp32c2-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
- name: check esp32c2-hal (embassy, log/defmt)
run: |
cd esp32c2-hal/
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
# Ensure documentation can be built
- name: rustdoc
run: cd esp32c2-hal/ && cargo doc --features=eh1
esp32c3-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
- name: build esp32c3-hal (no features)
run: cd esp32c3-hal/ && cargo +nightly build --examples
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32c3-hal (common features)
run: |
cd esp32c3-hal/
cargo +nightly build --examples --features=eh1,ufmt,log
cargo +nightly build --examples --features=eh1,ufmt,defmt
- name: check esp32c3-hal (async, systick)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
- name: check esp32c3-hal (async, timg0)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
- name: check esp32c3-hal (async, gpio)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c3-hal (async, multiprio)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32c3-hal (async, spi)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c3-hal (async, serial)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c3-hal (async, i2c)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c3-hal (async, usb_serial_jtag)
run: cd esp32c3-hal/ && cargo +nightly check --example=embassy_usb_serial_jtag --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c3-hal (interrupt-preemption)
run: cd esp32c3-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
- name: check esp32c3-hal (direct-vectoring)
run: cd esp32c3-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
- name: check esp32c3-hal (embassy, log/defmt)
run: |
cd esp32c3-hal/
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
# Ensure documentation can be built
- name: rustdoc
run: cd esp32c3-hal/ && cargo doc --features=eh1
esp32c6-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imac-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# build the lp-hal examples first to make sure the examples which expect
# the ELF files to be present will compile
- name: build esp32c6-lp-hal prerequisites
run: cd esp32c6-lp-hal/ && cargo +nightly build --release --examples
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
# We also use this as an opportunity to verify that the examples link
# for each supported image format.
- name: build esp32c6-hal (no features)
run: cd esp32c6-hal/ && cargo +nightly build --examples
- name: build esp32c6-hal (flip-link feature)
run: cd esp32c6-hal/ && cargo +nightly build --examples --features=flip-link
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32c6-hal (common features)
run: |
cd esp32c6-hal/
cargo +nightly build --examples --features=eh1,ufmt,log
cargo +nightly build --examples --features=eh1,ufmt,defmt
- name: check esp32c6-hal (async, systick)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
- name: check esp32c6-hal (async, timg0)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
- name: check esp32c6-hal (async, gpio)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c6-hal (async, multiprio)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32c6-hal (async, spi)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c6-hal (async, serial)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c6-hal (async, i2c)
run: cd esp32c6-hal/ && cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32c6-hal (interrupt-preemption)
run: cd esp32c6-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
- name: check esp32c6-hal (direct-vectoring)
run: cd esp32c6-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
- name: check esp32c6-hal (embassy, log/defmt)
run: |
cd esp32c6-hal/
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
# Ensure documentation can be built
- name: rustdoc
run: cd esp32c6-hal/ && cargo doc --features=eh1
esp32c6-lp-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imac-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
- name: build esp32c6-lp-hal (no features)
run: cd esp32c6-lp-hal/ && cargo +nightly build --release --examples
# Ensure documentation can be built
- name: rustdoc
run: cd esp32c6-lp-hal/ && cargo doc
esp32h2-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imac-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
# We also use this as an opportunity to verify that the examples link
# for each supported image format.
- name: build esp32h2-hal (no features)
run: cd esp32h2-hal/ && cargo +nightly build --examples
- name: build esp32h2-hal (flip-link feature)
run: cd esp32h2-hal/ && cargo +nightly build --examples --features=flip-link
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32h2-hal (common features)
run: |
cd esp32h2-hal/
cargo +nightly build --examples --features=eh1,ufmt,log
cargo +nightly build --examples --features=eh1,ufmt,defmt
- name: check esp32h2-hal (async, systick)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
- name: check esp32h2-hal (async, timg0)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
- name: check esp32h2-hal (async, gpio)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32h2-hal (async, multiprio)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32h2-hal (async, spi)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32h2-hal (async, serial)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32h2-hal (async, i2c)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-systick,embassy-executor-thread,async
- name: check esp32h2-hal (interrupt-preemption)
run: cd esp32h2-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
- name: check esp32h2-hal (direct-vectoring)
run: cd esp32h2-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
- name: check esp32h2-hal (embassy, log/defmt)
run: |
cd esp32h2-hal/
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
# Ensure documentation can be built
- name: rustdoc
run: cd esp32h2-hal/ && cargo doc --features=eh1
esp32s2-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
default: true
buildtargets: esp32s2
ldproxy: false
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# build the esp-ulp-riscv-hal examples first to make sure the examples which expect
# the ELF files to be present will compile
- name: build esp-ulp-riscv-hal prerequisites
run: cd esp-ulp-riscv-hal/ && cargo +nightly build --release --features=esp32s2 --examples
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
- name: check esp32s2-hal (no features)
run: cd esp32s2-hal/ && cargo +esp build --examples
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32s2-hal (common features)
run: |
cd esp32s2-hal/
cargo +esp build --examples --features=eh1,ufmt,log
cargo +esp build --examples --features=eh1,ufmt,defmt
# FIXME: `time-systick` feature disabled for now, see 'esp32s2-hal/Cargo.toml'.
# - name: check esp32s2-hal (async, systick)
# run: cd esp32s2-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-systick,executor
- name: check esp32s2-hal (embassy, timg0)
run: |
cd esp32s2-hal/
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32s2-hal (embassy, systick)
run: |
cd esp32s2-hal/
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32s2-hal (embassy, timg0, async)
run: |
cd esp32s2-hal/
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
cargo +esp check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
- name: check esp32s2-hal (embassy, systick, async)
run: |
cd esp32s2-hal/
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-systick,async,embassy-executor-thread
- name: check esp32s2-hal (embassy, log/defmt)
run: |
cd esp32s2-hal/
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
- name: check esp32s2-hal (psram)
run: cd esp32s2-hal/ && cargo +esp check --example=psram --features=psram-2m --release # This example requires release!
# Ensure documentation can be built
- name: rustdoc
run: cd esp32s2-hal/ && cargo +esp doc --features=eh1
esp32s3-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
default: true
buildtargets: esp32s3
ldproxy: false
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
# build the esp-ulp-riscv-hal examples first to make sure the examples which expect
# the ELF files to be present will compile
- name: build esp-ulp-riscv-hal prerequisites
run: cd esp-ulp-riscv-hal/ && cargo +nightly build --release --features=esp32s3 --examples
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
# We also use this as an opportunity to verify that the examples link
# for each supported image format.
- name: build esp32s3-hal (no features)
run: cd esp32s3-hal/ && cargo +esp build --examples
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32s3-hal (common features)
run: |
cd esp32s3-hal/
cargo +esp build --examples --features=eh1,ufmt,log
cargo +esp build --examples --features=eh1,ufmt,defmt
- name: check esp32s3-hal (embassy, timg0)
run: |
cd esp32s3-hal/
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
cargo +esp check --example=embassy_multicore --features=embassy,embassy-time-timg0,embassy-executor-thread
cargo +esp check --example=embassy_multicore_interrupt --features=embassy,embassy-time-timg0,embassy-executor-interrupt
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32s3-hal (embassy, systick)
run: |
cd esp32s3-hal/
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
cargo +esp check --example=embassy_multicore --features=embassy,embassy-time-systick,embassy-executor-thread
cargo +esp check --example=embassy_multicore_interrupt --features=embassy,embassy-time-systick,embassy-executor-interrupt
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
- name: check esp32s3-hal (embassy, timg0, async)
run: |
cd esp32s3-hal/
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
cargo +esp check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
- name: check esp32s3-hal (embassy, systick, async)
run: |
cd esp32s3-hal/
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-systick,async,embassy-executor-thread
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-systick,async,embassy-executor-thread
- name: check esp32s3-hal (octal psram and psram)
run: | # This examples require release!
cd esp32s3-hal/
cargo +esp check --example=octal_psram --features=opsram-2m --release
cargo +esp check --example=psram --features=psram-2m --release
- name: check esp32s3-hal (embassy, log/defmt)
run: |
cd esp32s3-hal/
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
# Ensure documentation can be built
- name: rustdoc
run: cd esp32s3-hal/ && cargo doc --features=eh1
- name: Install dependencies
run: sudo apt-get update && sudo apt-get -y install musl-tools libudev-dev pkg-config
# Build the extra crates
- name: Build the bench-server
run: cd extras/bench-server && cargo build
- name: Build esp-wifishark
run: cd extras/esp-wifishark && cargo build
- name: Build ieee802154-sniffer
run: cd extras/ieee802154-sniffer && cargo build
# --------------------------------------------------------------------------
# MSRV
msrv-riscv:
msrv:
runs-on: ubuntu-latest
env:
RUSTC_BOOTSTRAP: 1
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
ldproxy: false
version: ${{ env.MSRV }}
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
@ -571,127 +128,42 @@ jobs:
components: rust-src
- uses: Swatinem/rust-cache@v2
# Build the esp32c6-lp-hal examples first. This is done to ensure the
# examples which expect the ELF files to be present will compile:
- name: build esp32c6-lp-hal prerequisites
run: cd esp32c6-lp-hal && cargo build --release --examples
# Verify the MSRV for all RISC-V chips.
- name: msrv (esp32c2-hal)
- name: msrv RISCV (esp-hal)
run: |
cd esp32c2-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
- name: msrv (esp32c3-hal)
run: |
cd esp32c3-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
- name: msrv (esp32c6-hal)
run: |
cd esp32c6-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
- name: msrv (esp32c6-lp-hal)
run: |
cd esp32c6-lp-hal/
cargo build
- name: msrv (esp32h2-hal)
run: |
cd esp32h2-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
cargo xtask build-package --features=esp32c2,ci --target=riscv32imc-unknown-none-elf esp-hal
cargo xtask build-package --features=esp32c3,ci --target=riscv32imc-unknown-none-elf esp-hal
cargo xtask build-package --features=esp32c6,ci --target=riscv32imac-unknown-none-elf esp-hal
cargo xtask build-package --features=esp32h2,ci --target=riscv32imac-unknown-none-elf esp-hal
msrv-xtensa:
runs-on: ubuntu-latest
env:
RUSTC_BOOTSTRAP: 1
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: ${{ env.MSRV }}
components: rust-src
- uses: esp-rs/xtensa-toolchain@v1.5
with:
ldproxy: false
version: ${{ env.MSRV }}
- uses: Swatinem/rust-cache@v2
# Build the `esp-ulp-riscv-hal` examples first. This is done to ensure
# the examples which expect the ELF files to be present will compile:
- name: build esp-ulp-riscv-hal prerequisites
run: cd esp-ulp-riscv-hal && cargo build --release --features=esp32s3 --examples
# Verify the MSRV for all Xtensa chips:
- name: msrv (esp32-hal)
- name: msrv RISCV (esp-wifi)
run: |
cd esp32-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
- name: msrv (esp32s2-hal)
cargo xtask build-package --features=esp32c2,wifi,ble,esp-hal/unstable --target=riscv32imc-unknown-none-elf esp-wifi
cargo xtask build-package --features=esp32c3,wifi,ble,esp-hal/unstable --target=riscv32imc-unknown-none-elf esp-wifi
cargo xtask build-package --features=esp32c6,wifi,ble,esp-hal/unstable --target=riscv32imac-unknown-none-elf esp-wifi
cargo xtask build-package --features=esp32h2,ble,esp-hal/unstable --target=riscv32imac-unknown-none-elf esp-wifi
# Verify the MSRV for all Xtensa chips:
- name: msrv Xtensa (esp-hal)
run: |
cd esp32s2-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
- name: msrv (esp32s3-hal)
cargo xtask build-package --toolchain=esp --features=esp32,ci --target=xtensa-esp32-none-elf esp-hal
cargo xtask build-package --toolchain=esp --features=esp32s2,ci --target=xtensa-esp32s2-none-elf esp-hal
cargo xtask build-package --toolchain=esp --features=esp32s3,ci --target=xtensa-esp32s3-none-elf esp-hal
- name: msrv Xtensa (esp-wifi)
run: |
cd esp32s3-hal/
cargo build --features=eh1,ufmt,log
cargo build --features=defmt
cargo xtask build-package --toolchain=esp --features=esp32,wifi,ble,esp-hal/unstable --target=xtensa-esp32-none-elf esp-wifi
cargo xtask build-package --toolchain=esp --features=esp32s2,wifi,esp-hal/unstable --target=xtensa-esp32s2-none-elf esp-wifi
cargo xtask build-package --toolchain=esp --features=esp32s3,wifi,ble,esp-hal/unstable --target=xtensa-esp32s3-none-elf esp-wifi
- name: msrv (esp-lp-hal)
run: |
cargo xtask build-package --features=esp32c6 --target=riscv32imac-unknown-none-elf esp-lp-hal
cargo xtask build-package --features=esp32s2 --target=riscv32imc-unknown-none-elf esp-lp-hal
cargo xtask build-package --features=esp32s3 --target=riscv32imc-unknown-none-elf esp-lp-hal
# --------------------------------------------------------------------------
# Lint
clippy-riscv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: nightly
targets: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
components: clippy,rust-src
- uses: Swatinem/rust-cache@v2
# Run 'cargo clippy' on all packages targeting RISC-V:
- name: clippy (esp-riscv-rt)
run: cd esp-riscv-rt && cargo clippy --target=riscv32imc-unknown-none-elf -- -D warnings
- name: clippy (esp-ulp-riscv-hal, esp32s2)
run: cd esp-ulp-riscv-hal && cargo clippy --features=esp32s2 -- -D warnings
- name: clippy (esp-ulp-riscv-hal, esp32s3)
run: cd esp-ulp-riscv-hal && cargo clippy --features=esp32s3 -- -D warnings
- name: clippy (esp32c2-hal)
run: cd esp32c2-hal && cargo clippy -- -D warnings
- name: clippy (esp32c3-hal)
run: cd esp32c3-hal && cargo clippy -- -D warnings
- name: clippy (esp32c6-hal)
run: cd esp32c6-hal && cargo clippy -- -D warnings
- name: clippy (esp32c6-lp-hal)
run: cd esp32c6-lp-hal && cargo clippy -- -D warnings
- name: clippy (esp32h2-hal)
run: cd esp32h2-hal && cargo clippy -- -D warnings
clippy-xtensa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
ldproxy: false
- uses: Swatinem/rust-cache@v2
# Run 'cargo clippy' on all packages targeting Xtensa:
- name: clippy (esp32-hal)
run: cd esp32-hal && cargo clippy -- -D warnings
- name: clippy (esp32s2-hal)
run: cd esp32s2-hal && cargo clippy -- -D warnings
- name: clippy (esp32s3-hal)
run: cd esp32s3-hal && cargo clippy -- -D warnings
# Format
rustfmt:
runs-on: ubuntu-latest
@ -707,29 +179,20 @@ jobs:
- uses: Swatinem/rust-cache@v2
# Check the formatting of all packages:
- name: rustfmt (esp-hal-common)
run: cargo fmt --all --manifest-path=esp-hal-common/Cargo.toml -- --check
- name: rustfmt (esp-hal-procmacros)
run: cargo fmt --all --manifest-path=esp-hal-procmacros/Cargo.toml -- --check
- name: rustfmt (esp-hal-smartled)
run: cargo fmt --all --manifest-path=esp-hal-smartled/Cargo.toml -- --check
- name: rustfmt (esp-riscv-rt)
run: cargo fmt --all --manifest-path=esp-riscv-rt/Cargo.toml -- --check
- name: rustfmt (esp-ulp-riscv-hal)
run: cargo fmt --all --manifest-path=esp-ulp-riscv-hal/Cargo.toml -- --check
- name: rustfmt (esp32-hal)
run: cargo fmt --all --manifest-path=esp32-hal/Cargo.toml -- --check
- name: rustfmt (esp32c2-hal)
run: cargo fmt --all --manifest-path=esp32c2-hal/Cargo.toml -- --check
- name: rustfmt (esp32c3-hal)
run: cargo fmt --all --manifest-path=esp32c3-hal/Cargo.toml -- --check
- name: rustfmt (esp32c6-hal)
run: cargo fmt --all --manifest-path=esp32c6-hal/Cargo.toml -- --check
- name: rustfmt (esp32c6-lp-hal)
run: cargo fmt --all --manifest-path=esp32c6-lp-hal/Cargo.toml -- --check
- name: rustfmt (esp32h2-hal)
run: cargo fmt --all --manifest-path=esp32h2-hal/Cargo.toml -- --check
- name: rustfmt (esp32s2-hal)
run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check
- name: rustfmt (esp32s3-hal)
run: cargo fmt --all --manifest-path=esp32s3-hal/Cargo.toml -- --check
- run: cargo xtask fmt-packages --check
# --------------------------------------------------------------------------
# host tests
host-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
- uses: Swatinem/rust-cache@v2
# Check the formatting of all packages:
- run: cd esp-config && cargo test --features build

53
.github/workflows/ci_nightly.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: CI - nightly
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
env:
CARGO_TERM_COLOR: always
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUSTDOCFLAGS: -Dwarnings
DEFMT_LOG: trace
jobs:
esp-hal-nightly:
name: esp-hal | nightly (${{ matrix.device.soc }})
runs-on: ubuntu-latest
env:
SSID: SSID
PASSWORD: PASSWORD
STATIC_IP: 1.1.1.1
GATEWAY_IP: 1.1.1.1
HOST_IP: 1.1.1.1
strategy:
fail-fast: false
matrix:
device: [
# RISC-V devices:
{ soc: "esp32c2", target: "riscv32imc-unknown-none-elf" },
{ soc: "esp32c3", target: "riscv32imc-unknown-none-elf" },
{ soc: "esp32c6", target: "riscv32imac-unknown-none-elf" },
{ soc: "esp32h2", target: "riscv32imac-unknown-none-elf" },
]
steps:
- uses: actions/checkout@v4
# Install the Rust nightly toolchain for RISC-V devices:
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
toolchain: nightly
components: rust-src, clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- name: Build and Check
uses: ./.github/actions/check-esp-hal
with:
device: ${{ matrix.device.soc }}
target: ${{ matrix.device.target }}
toolchain: nightly

99
.github/workflows/documentation.yml vendored Normal file
View File

@ -0,0 +1,99 @@
name: Documentation
on:
workflow_dispatch:
inputs:
esp-hal:
description: "esp-hal tag"
required: true
esp-wifi:
description: "esp-wifi tag"
required: true
env:
CARGO_TERM_COLOR: always
jobs:
setup:
runs-on: ubuntu-latest
outputs:
packages: '[
{ "name": "esp-hal", "tag": "${{ github.event.inputs.esp-hal }}" },
{ "name": "esp-wifi", "tag": "esp-wifi-${{ github.event.inputs.esp-wifi }}" }
]'
steps:
- run: echo "Setup complete!"
build:
needs: setup
strategy:
fail-fast: true
matrix:
packages: ${{ fromJson(needs.setup.outputs.packages) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: esp-rs/xtensa-toolchain@v1.5
with:
default: true
ldproxy: false
version: 1.83.0.1
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: esp-rs/esp-hal
ref: ${{ matrix.packages.tag }}
- name: Build documentation
run: cargo xtask build-documentation --packages=${{ matrix.packages.name }}
# https://github.com/actions/deploy-pages/issues/303#issuecomment-1951207879
- name: Remove problematic '.lock' files
run: find docs -name ".lock" -exec rm -f {} \;
- name: Upload docs for ${{ matrix.packages.name }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.packages.name }}
path: "docs/${{ matrix.packages.name }}"
assemble:
needs: [setup, build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Prepare
run: mkdir docs
- name: Download all docs
uses: actions/download-artifact@v4
with:
path: "docs/"
- name: Create index.html
run: "cargo xtask build-documentation-index --packages=$(echo '${{ needs.setup.outputs.packages }}' | jq -r '[.[].name] | join(\",\")')"
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: "docs/"
deploy:
# Add a dependency to the assemble job:
needs: assemble
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment:
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
# Deploy to the github-pages environment:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
# Specify runner + deployment step:
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

186
.github/workflows/hil.yml vendored Normal file
View File

@ -0,0 +1,186 @@
name: HIL
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
merge_group:
workflow_dispatch:
inputs:
repository:
description: "Owner and repository to test"
required: true
default: 'esp-rs/esp-hal'
branch:
description: "Branch, tag or SHA to checkout."
required: true
default: "main"
# Cancel any currently running workflows from the same PR, branch, or
# tag when a new workflow is triggered.
#
# https://stackoverflow.com/a/66336834
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
env:
CARGO_TERM_COLOR: always
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build-xtasks:
name: Build xtasks | ${{ matrix.host.arch }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
host:
- arch: armv7
rust-target: armv7-unknown-linux-gnueabihf
- arch: aarch64
rust-target: aarch64-unknown-linux-gnu
steps:
- uses: actions/checkout@v4
if: github.event_name != 'workflow_dispatch'
- uses: actions/checkout@v4
if: github.event_name == 'workflow_dispatch'
with:
repository: ${{ github.event.inputs.repository }}
ref: ${{ github.event.inputs.branch }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
components: rust-src
- name: Install cross
run: cargo install cross
- name: Build xtasks
run: cross build --release --target ${{ matrix.host.rust-target }} -p xtask
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: xtask-${{ matrix.host.arch }}
path: target/${{ matrix.host.rust-target }}/release/xtask
build-tests:
name: Build HIL Tests | ${{ matrix.target.soc }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
# RISC-V devices:
- soc: esp32c2
rust-target: riscv32imc-unknown-none-elf
- soc: esp32c3
rust-target: riscv32imc-unknown-none-elf
- soc: esp32c6
rust-target: riscv32imac-unknown-none-elf
- soc: esp32h2
rust-target: riscv32imac-unknown-none-elf
# # Xtensa devices:
- soc: esp32
rust-target: xtensa-esp32-none-elf
- soc: esp32s2
rust-target: xtensa-esp32s2-none-elf
- soc: esp32s3
rust-target: xtensa-esp32s3-none-elf
steps:
- uses: actions/checkout@v4
if: github.event_name != 'workflow_dispatch'
- uses: actions/checkout@v4
if: github.event_name == 'workflow_dispatch'
with:
repository: ${{ github.event.inputs.repository }}
ref: ${{ github.event.inputs.branch }}
# Install the Rust toolchain for RISC-V devices:
- if: ${{ !contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.target.soc) }}
uses: dtolnay/rust-toolchain@v1
with:
target: ${{ matrix.target.rust-target }}
toolchain: stable
components: rust-src
# Install the Rust toolchain for Xtensa devices:
- if: contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.target.soc)
uses: esp-rs/xtensa-toolchain@v1.5
with:
buildtargets: ${{ matrix.target.soc }}
default: true
ldproxy: false
version: 1.83.0.1
- name: Build tests
run: cargo xtask build-tests ${{ matrix.target.soc }}
- uses: actions/upload-artifact@v4
with:
name: tests-${{ matrix.target.soc }}
path: /home/runner/work/esp-hal/esp-hal/target/tests/${{ matrix.target.soc }}
if-no-files-found: error
overwrite: true
hil:
name: Run HIL Tests | ${{ matrix.target.soc }}
needs: [build-tests, build-xtasks]
runs-on:
labels: [self-hosted, "${{ matrix.target.runner }}"]
strategy:
fail-fast: false
matrix:
target:
# RISC-V devices:
- soc: esp32c2
runner: esp32c2-jtag
host: aarch64
- soc: esp32c3
runner: esp32c3-usb
host: armv7
- soc: esp32c6
runner: esp32c6-usb
host: armv7
- soc: esp32h2
runner: esp32h2-usb
host: armv7
# Xtensa devices:
- soc: esp32
runner: esp32-jtag
host: aarch64
- soc: esp32s2
runner: esp32s2-jtag
host: armv7
- soc: esp32s3
runner: esp32s3-usb
host: armv7
steps:
- uses: actions/download-artifact@v4
with:
name: tests-${{ matrix.target.soc }}
path: tests-${{ matrix.target.soc }}
- uses: actions/download-artifact@v4
with:
name: xtask-${{ matrix.target.host }}
- name: Run Tests
id: run-tests
run: |
[ -f ~/setup.sh ] && source ~/setup.sh
export PATH=$PATH:/home/espressif/.cargo/bin
chmod +x xtask
./xtask run-elfs ${{ matrix.target.soc }} tests-${{ matrix.target.soc }}
- name: Clean up
if: always()
run: |
rm -rf tests-${{ matrix.target.soc }}
rm -f xtask

View File

@ -13,4 +13,4 @@ jobs:
- uses: actions/add-to-project@v0.5.0
with:
project-url: https://github.com/orgs/esp-rs/projects/2
github-token: ${{ secrets.PAT }}
github-token: ${{ secrets.PAT }}

6
.gitignore vendored
View File

@ -16,3 +16,9 @@ Cargo.lock
# Wokwi related files
diagram.json
wokwi.toml
# We'll ignore VS Code settings (at least for now...)
**/.vscode/settings.json
# Ignore generated documentation
docs/

View File

@ -1,3 +0,0 @@
{
"recommendations": ["rust-lang.rust-analyzer", "tamasfe.even-better-toml"]
}

34
.vscode/settings.json vendored
View File

@ -1,34 +0,0 @@
{
"editor.formatOnSave": true,
"rust-analyzer.cargo.buildScripts.enable": true,
"rust-analyzer.check.allTargets": false,
"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "crate",
"rust-analyzer.procMacro.attributes.enable": true,
"rust-analyzer.procMacro.enable": true,
"rust-analyzer.showUnlinkedFileNotification": false,
// Uncomment ONE line for the chip you want to work on.
// This makes rust-analyzer work on the HAL crate and all its dependencies.
"rust-analyzer.linkedProjects": [
"esp32-hal/Cargo.toml"
// "esp32c2-hal/Cargo.toml",
// "esp32c3-hal/Cargo.toml",
// "esp32c6-hal/Cargo.toml",
// "esp32c6-lp-hal/Cargo.toml",
// "esp32h2-hal/Cargo.toml",
// "esp32s2-hal/Cargo.toml",
// "esp32s3-hal/Cargo.toml",
],
"[toml]": {
"editor.formatOnSave": false,
},
"[markdown]": {
"editor.formatOnSave": false,
},
"[jsonc]": {
"editor.formatOnSave": false,
}
}

View File

@ -1,365 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
Please note that only changes to the `esp-hal-common` package are tracked in this CHANGELOG.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.14.1] - 2023-12-13
### Fixed
- Fix SHA for all targets (#1021)
## [0.14.0] - 2023-12-12
### Added
- ESP32-C6: LP core clock is configurable (#907)
- Derive `Clone` and `Copy` for `EspTwaiFrame` (#914)
- A way to configure inverted pins (#912)
- Added API to check a GPIO-pin's interrupt status bit (#929)
- A `embedded_io_async::Read` implementation for `UsbSerialJtag` (#889)
- `RtcClock::get_xtal_freq`, `RtcClock::get_slow_freq` (#957)
- Added Rx Timeout functionality to async Uart (#911)
- RISC-V: Thread-mode and interrupt-mode executors, `#[main]` macro (#947)
- A macro to make it easier to create DMA buffers and descriptors (#935)
- I2C timeout is configurable (#1011)
- ESP32-C6/ESP32-H2: `flip-link` feature gives zero-cost stack overflow protection (#1008)
### Changed
- Improve DMA documentation & clean up module (#915)
- Only allow a single version of `esp-hal-common` to be present in an application (#934)
- ESP32-C3/C6 and ESP32-H2 can now use the `zero-rtc-bss` feature to enable `esp-hal-common/rv-zero-rtc-bss` (#867)
- Reuse `ieee802154_clock_enable/disable()` functions for BLE and rename `ble_ieee802154_clock_enable()` (#953)
- The `embedded-io` trait implementations are now gated behind the `embedded-io` feature (#964)
- Simplifed RMT channels and channel creators (#958)
- Reworked construction of I2S driver instances (#983)
- ESP32-S2/S3: Don't require GPIO 18 to create a USB peripheral driver instance (#990)
- Updated to latest release candidate (`1.0.0-rc.2`) for `embedded-hal{-async,-nb}` (#994)
- Explicit panic when hitting the `DefaultHandler` (#1005)
- Relevant interrupts are now auto enabled in `embassy::init` (#1014).
### Fixed
- ESP32-C2/C3 examples: fix build error (#899)
- ESP32-S3: Fix GPIO interrupt handler crashing when using GPIO48. (#898)
- Fixed short wait times in embassy causing hangs (#906)
- Make sure to clear LP/RTC RAM before loading code (#916)
- Async RMT channels can be used concurrently (#925)
- Xtensa: Allow using `embassy-executor`'s thread-mode executor if neither `embassy-executor-thread`, nor `embassy-executor-interrupt` is enabled. (#937)
- Uart Async: Improve interrupt handling and irq <--> future communication (#977)
- RISC-V: Fix stack allocation (#988)
- ESP32-C6: Fix used RAM (#997)
- ESP32-H2: Fix used RAM (#1003)
- Fix SPI slave DMA dma\_read and dma\_write (#1013)
### Removed
- Direct boot support has been removed (#903).
- Removed the `mcu-boot` feature from `esp32c3-hal` (#938)
- Removed SpiBusController and SpiBusDevice in favour of embedded-hal-bus and embassy-embedded-hal implementataions. (#978)
### Breaking
- `Spi::new`/`Spi::new_half_duplex` takes no gpio pin now, instead you need to call `with_pins` to setup those (#901).
- ESP32-C2, ESP32-C3, ESP32-S2: atomic emulation trap has been removed. (#904) (#985)
- When upgrading you must either remove [these lines](https://github.com/esp-rs/riscv-atomic-emulation-trap#usage) from your `.cargo/config.toml`.
- Usage of `core::sync::atomic::*` in dependent crates should be replaced with [portable-atomic](https://github.com/taiki-e/portable-atomic).
- RSA driver now takes `u32` words instead of `u8` bytes. The expected slice length is now 4 times shorter. (#981)
## [0.13.1] - 2023-11-02
### Fixed
- ESP32-C3: Make sure BLE and WiFi are not powered down when esp-wifi needs them (#891)
- ESP32-C6/H2: Fix setting UART baud rate (#893)
## [0.13.0] - 2023-10-31
### Added
- Implement SetFrequencyCycle and PwmPin from embedded_hal for PwmPin of MCPWM. (#880)
- Added `embassy-time-systick` to ESP32-S2 (#827)
- Implement enabling/disabling BLE clock on ESP32-C6 (#784)
- Async support for RMT (#787)
- Implement `defmt::Format` for more types (#786)
- Add new_no_miso to Spi FullDuplexMode (#794)
- Add UART support for splitting into TX and RX (#754)
- Async support for I2S (#801)
- Async support for PARL_IO (#807)
- ETM driver, GPIO ETM (#819)
- (G)DMA AES support (#821)
- SYSTIMER ETM functionality (#828)
- Adding async support for RSA peripheral(doesn't work properly for `esp32` chip - issue will be created)(#790)
- Added sleep support for ESP32-C3 with timer and GPIO wakeups (#795)
- Support for ULP-RISCV including Delay and GPIO (#840, #845)
- Add bare-bones SPI slave support, DMA only (#580, #843)
- Embassy `#[main]` convenience macro (#841)
- Add a `defmt` feature to the `esp-hal-smartled` package (#846)
- Support 16MB octal PS-RAM for ESP32-S3 (#858)
- RISCV TRACE Encoder driver for ESP32-C6 / ESP32-H2 (#864)
- `embedded_hal` 1 `InputPin` and `embedded_hal_async` `Wait` impls for open drain outputs (#905)
### Changed
- Bumped MSRV to 1.67 (#798)
- Optimised multi-core critical section implementation (#797)
- Changed linear- and curve-calibrated ADC to provide readings in mV (#836)
### Fixed
- S3: Allow powering down RC_FAST_CLK (#796)
- UART/ESP32: fix calculating FIFO counter with `get_rx_fifo_count()` (#804)
- Xtensa targets: Use ESP32Reset - not Reset (#823)
- Examples should now work with the `defmt` feature (#810)
- Fixed a race condition causing SpiDma to stop working unexpectedly (#869)
- Fixed async uart serial, and updated the embassy_serial examples (#871).
- Fix ESP32-S3 direct-boot (#873)
- Fix ESP32-C6 ADC (#876)
- Fix ADC Calibration not being used on ESP32-S2 and ESP32-S3 (#1000)
### Removed
- `Pin::is_pcore_interrupt_set` (#793)
- `Pin::is_pcore_non_maskable_interrupt_set` (#793)
- `Pin::is_acore_interrupt_set` (#793)
- `Pin::is_acore_non_maskable_interrupt_set` (#793)
- `Pin::enable_hold` (#793)
- Removed the generic return type for ADC reads (#792)
### Breaking
- `Uart::new` now takes the `&Clocks` struct to ensure baudrate is correct for CPU/APB speed. (#808)
- `Uart::new_with_config` takes an `Config` instead of `Option<Config>`. (#808)
- `Alarm::set_period` takes a period (duration) instead of a frequency (#812)
- `Alarm::interrupt_clear` is now `Alarm::clear_interrupt` to be consistent (#812)
- The `PeripheralClockControl` struct is no longer public, drivers no longer take this as a parameter (#817)
- Unify the system peripheral, `SYSTEM`, `DPORT` and `PCR` are now all exposed as `SYSTEM` (#832).
- Unified the ESP32's and ESP32-C2's xtal frequency features (#831)
- Replace any underscores in feature names with dashes (#833)
- The `spi` and `spi_slave` modules have been refactored into the `spi`, `spi::master`, and `spi::slave` modules (#843)
- The `WithDmaSpi2`/`WithDmaSpi3` structs are no longer generic around the inner peripheral type (#853)
- The `SarAdcExt`/`SensExt` traits are now collectively named `AnalogExt` instead (#857)
- Replace the `radio` module with peripheral singleton structs (#852)
- The SPI traits are no longer re-exported in the main prelude, but from preludes in `spi::master`/`spi::slave` instead (#860)
- The `embedded-hal-1` and `embedded-hal-async` traits are no longer re-exported in the prelude (#860)
## [0.12.0] - 2023-09-05
### Added
- Implement RTCIO pullup, pulldown and hold control for Xtensa MCUs (#684)
- S3: Implement RTCIO wakeup source (#690)
- Add PARL_IO driver for ESP32-C6 / ESP32-H2 (#733, #760)
- Implement `ufmt_write::uWrite` trait for USB Serial JTAG (#751)
- Add HMAC peripheral support (#755)
- Add multicore-aware embassy executor for Xtensa MCUs (#723, #756).
- Add interrupt-executor for Xtensa MCUs (#723, #756).
- Add missing `Into<Gpio<Analog, GPIONUN>>` conversion (#764)
- Updated `clock` module documentation (#774)
- Add `log` feature to enable log output (#773)
- Add `defmt` feature to enable log output (#773)
- A new macro to load LP core code on ESP32-C6 (#779)
- Add `ECC`` peripheral driver (#785)
- Initial LLD support for Xtensa chips (#861).
### Changed
- Update the `embedded-hal-*` packages to `1.0.0-rc.1` and implement traits from `embedded-io` and `embedded-io-async` (#747)
- Moved AlignmentHelper to its own module (#753)
- Disable all watchdog timers by default at startup (#763)
- `log` crate is now opt-in (#773)
### Fixed
- Fix `psram` availability lookup in `esp-hal-common` build script (#718)
- Fix wrong `dram_seg` length in `esp32s2-hal` linker script (#732)
- Fix setting alarm when a timer group is used as the alarm source. (#730)
- Fix `Instant::now()` not counting in some cases when using TIMG0 as the timebase (#737)
- Fix number of ADC attenuations for ESP32-C6 (#771)
- Fix SHA registers access (#805)
### Breaking
- `CpuControl::start_app_core()` now takes an `FnOnce` closure (#739)
## [0.11.0] - 2023-08-10
### Added
- Add initial LP-IO support for ESP32-C6 (#639)
- Implement sleep with some wakeup methods for `esp32` (#574)
- Add a new RMT driver (#653, #667, #695)
- Implemented calibrated ADC API for ESP32-S3 (#641)
- Add MCPWM DeadTime configuration (#406)
- Implement sleep with some wakeup methods for `esp32-s3` (#660, #689, #696)
- Add feature enabling directly hooking the interrupt vector table (#621)
- Add `ClockControl::max` helper for all chips (#701)
- Added module-level documentation for all peripherals (#680)
- Implement sleep with some wakeup methods for `esp32-s3` (#660)
- Add `FlashSafeDma` wrapper for eh traits which ensure correct DMA transfer from source data in flash (ROM) (#678)
### Changed
- Update `embedded-hal-*` alpha packages to their latest versions (#640)
- Implement the `Clone` and `Copy` traits for the `Rng` driver (#650)
- Use all remaining memory as core-0's stack (#716)
### Fixed
- Fixed Async Uart `read` when `set_at_cmd` is not used (#652)
- USB device support is working again (#656)
- Add missing interrupt status read for esp32s3, which fixes USB-SERIAL-JTAG interrupts (#664)
- GPIO interrupt status bits are now properly cleared (#670)
- Increase frequency resolution in `set_periodic` (#686)
- Fixed ESP32-S2, ESP32-S3, ESP32-C2, ESP32-C3 radio clock gating (#679, #681)
- Partially fix ESP32 radio clocks (#709)
- Fixed "ESP32/ESP32-S2 RMT transmission with with data.len() > RMT_CHANNEL_RAM_SIZE results in TransmissionError" #707 (#710)
### Removed
- Remove the `allow-opt-level-z` feature from `esp32c3-hal` (#654)
- Remove the old `pulse_control` driver (#694)
### Breaking
- `DmaTransfer::wait` and `I2sReadDmaTransfer::wait_receive` now return `Result` (#665)
- `gpio::Pin` is now object-safe (#687)
## [0.10.0] - 2023-06-04
### Added
- Add `WithDmaSpi3` to prelude for ESP32S3 (#623)
- Add bare-bones PSRAM support for ESP32 (#506)
- Add initial support for the ESP32-H2 (#513, #526, #527, #528, #530, #538, #544, #548, #551, #556, #560, #566, #549, #564, #569, #576, #577, #589, #591, #597)
- Add bare-bones PSRAM support for ESP32-S3 (#517)
- Add async support to the I2C driver (#519)
- Implement Copy and Eq for EspTwaiError (#540)
- Add LEDC hardware fade support (#475)
- Added support for multicore async GPIO (#542)
- Add a fn to poll DMA transfers (#559)
- Add unified field-based efuse access (#567)
- Move `esp-riscv-rt` into esp-hal (#578)
- Add CRC functions from ESP ROM (#587)
- Add a `debug` feature to enable the PACs' `impl-register-debug` feature (#596)
- Add initial support for `I2S` in ESP32-H2 (#597)
- Add octal PSRAM support for ESP32-S3 (#610)
- Add MD5 functions from ESP ROM (#618)
- Add embassy async `read` support for `uart` (#620)
- Add bare-bones support to run code on ULP-RISCV / LP core (#631)
- Add ADC calibration implementation for a riscv chips (#555)
- Add `async` implementation for `USB Serial/JTAG`(#632)
### Changed
- Simplify the `Delay` driver, derive `Clone` and `Copy` (#568)
- DMA types can no longer be constructed by the user (#625)
- Move core interrupt handling from Flash to RAM for RISC-V chips (ESP32-H2, ESP32-C2, ESP32-C3, ESP32-C6) (#541)
- Change LED pin to GPIO2 in ESP32 blinky example (#581)
- Update ESP32-H2 and ESP32-C6 clocks and remove `i2c_clock` for all chips but ESP32 (#592)
- Use both timers in `TIMG0` for embassy time driver when able (#609)
- Re-work `RadioExt` implementations, add support for ESP32-H2 (#627)
- Improve examples documentation (#533)
- esp32h2-hal: added README (#585)
- Update `esp-hal-procmacros` package dependencies and features (#628)
### Fixed
- Corrected the expected DMA descriptor counts (#622, #625)
- DMA is supported for SPI3 on ESP32-S3 (#507)
- `change_bus_frequency` is now available on `SpiDma` (#529)
- Fixed a bug where a GPIO interrupt could erroneously fire again causing the next `await` on that pin to instantly return `Poll::Ok` (#537)
- Set `vecbase` on core 1 (ESP32, ESP32-S3) (#536)
- ESP32-S3: Move PSRAM related function to RAM (#546)
- ADC driver will now apply attenuation values to the correct ADC's channels. (#554)
- Sometimes half-duplex non-DMA SPI reads were reading garbage in non-release mode (#552)
- ESP32-C3: Fix GPIO5 ADC channel id (#562)
- ESP32-H2: Fix direct-boot feature (#570)
- Fix Async GPIO not disabling interupts on chips with multiple banks (#572)
- ESP32-C6: Support FOSC CLK calibration for ECO1+ chip revisions (#593)
- Fixed CI by pinning the log crate to 0.4.18 (#600)
- ESP32-S3: Fix calculation of PSRAM start address (#601)
- Fixed wrong variable access (FOSC CLK calibration for ESP32-C6 #593)
- Fixed [trap location in ram](https://github.com/esp-rs/esp-hal/pull/605#issuecomment-1604039683) (#605)
- Fix rom::crc docs (#611)
- Fixed a possible overlap of `.data` and `.rwtext` (#616)
- Avoid SDA/SCL being low while configuring pins for I2C (#619)
### Breaking
- Simplified user-facing SpiDma and I2s types (#626)
- Significantly simplified user-facing GPIO pin types. (#553)
- No longer re-export the `soc` module and the contents of the `interrupt` module at the package level (#607)
## [0.9.0] - 2023-05-02
### Added
- Add bare-bones PSRAM support for ESP32-S2 (#493)
- Add `DEBUG_ASSIST` functionality (#484)
- Add RSA peripheral support (#467)
- Add PeripheralClockControl argument to `timg`, `wdt`, `sha`, `usb-serial-jtag` and `uart` constructors (#463)
- Added API to raise and reset software interrupts (#426)
- Implement `embedded_hal_nb::serial::*` traits for `UsbSerialJtag` (#498)
### Fixed
- Fix `get_wakeup_cause` comparison error (#472)
- Use 192 as mclk_multiple for 24-bit I2S (#471)
- Fix `CpuControl::start_app_core` signature (#466)
- Move `rwtext` after other RAM data sections (#464)
- ESP32-C3: Disable `usb_pad_enable` when setting GPIO18/19 to input/output (#461)
- Fix 802.15.4 clock enabling (ESP32-C6) (#458)
- ESP32-S3: Disable usb_pad_enable when setting GPIO19/20 to input/output (#645)
### Changed
- Update `embedded-hal-async` and `embassy-*` dependencies (#488)
- Update to `embedded-hal@1.0.0-alpha.10` and `embedded-hal-nb@1.0.0-alpha.2` (#487)
- Let users configure the LEDC output pin as open-drain (#474)
- Use bitflags to decode wakeup cause (#473)
- Minor linker script additions (#470)
- Minor documentation improvements (#460)
### Removed
- Remove unnecessary generic from `UsbSerialJtag` driver (#492)
- Remove `#[doc(inline)]` from esp-hal-common re-exports (#490)
## [0.8.0] - 2023-03-27
## [0.7.1] - 2023-02-22
## [0.7.0] - 2023-02-21
## [0.5.0] - 2023-01-26
## [0.4.0] - 2022-12-12
## [0.3.0] - 2022-11-17
## [0.2.0] - 2022-09-13
## [0.1.0] - 2022-08-05
[0.14.1]: https://github.com/esp-rs/esp-hal/compare/v0.14.0...v0.14.1
[0.14.0]: https://github.com/esp-rs/esp-hal/compare/v0.13.1...v0.14.0
[0.13.1]: https://github.com/esp-rs/esp-hal/compare/v0.13.0...v0.13.1
[0.13.0]: https://github.com/esp-rs/esp-hal/compare/v0.12.0...v0.13.0
[0.12.0]: https://github.com/esp-rs/esp-hal/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/esp-rs/esp-hal/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/esp-rs/esp-hal/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/esp-rs/esp-hal/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/esp-rs/esp-hal/compare/v0.7.1...v0.8.0
[0.7.1]: https://github.com/esp-rs/esp-hal/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/esp-rs/esp-hal/compare/v0.5.0...v0.7.0
[0.5.0]: https://github.com/esp-rs/esp-hal/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/esp-rs/esp-hal/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/esp-rs/esp-hal/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/esp-rs/esp-hal/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/esp-rs/esp-hal/releases/tag/v0.1.0

View File

@ -1,101 +0,0 @@
# Welcome to the `esp-hal` contributing guide
Thank you for investing your time in contributing to our project!
In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
Use the table of contents icon (<img src="resources/table-of-contents.png" width="24" height="24" />) in the top right corner of this document to get to a specific section of this guide quickly.
## New Contributor Guide
To get an overview of the project, please read the [README]. Here are some resources to help you get started with open source contributions:
- [Finding ways to contribute to open source on GitHub]
- [Set up Git]
- [GitHub flow]
- [Collaborating with pull requests]
[README]: README.md
[Finding ways to contribute to open source on GitHub]: https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github
[Set up Git]: https://docs.github.com/en/get-started/quickstart/set-up-git
[GitHub flow]: https://docs.github.com/en/get-started/quickstart/github-flow
[Collaborating with pull requests]: https://docs.github.com/en/github/collaborating-with-pull-requests
## Getting Started
### Issues
#### Create a New Issue
If you spot a problem with the docs, [search if an issue already exists]. If a related issue doesn't exist, you can open a new issue using the [issue form].
[search if an issue already exists]: https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments
[issue form]: https://github.com/esp-rs/esp-hal/issues/new/
#### Solve an Issue
Scan through our [existing issues] to find one that interests you. You can narrow down the search using labels as filters. If you find an issue to work on, you are welcome to open a PR with a fix.
It's recommended that you comment in the relevant issue, mentioning that you are actively working on it, however this is not a requirement.
If somebody is already assigned to an issue, this does not necessarily mean they are actively working on it; don't be afraid to comment in these issues asking if you can take over the work if you're interested.
[existing issues]: https://github.com/esp-rs/esp-hal/issues
### Make Changes
1. Fork the repository.
- Using GitHub Desktop:
- [Getting started with GitHub Desktop] will guide you through setting up Desktop.
- Once Desktop is set up, you can use it to [fork the repo!]
- Using the command line:
- [Fork the repo] so that you can make your changes without affecting the original project until you're ready to merge them.
2. Install or update to the latest version of Rust. See [rustup.rs] for more information.
3. Create a working branch and start with your changes!
[Getting started with GitHub Desktop]: https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop
[fork the repo!]: https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop
[Fork the repo]: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository
[rustup.rs]: https://rustup.rs/
### Commit Your Update
Commit the changes once you are happy with them. Don't forget to self-review to speed up the review process.
We ask that you ensure all source code files has been properly formatted with `rustfmt`, and that you have linted your changes by running `cargo clippy`. These tools can be installed by running the following commands:
```shell
rustup component add rustfmt
rustup component add clippy
```
We _strongly_ recommend that you use the supplied `pre-commit` Git hook, which will ensure that all source code has been formatted correctly prior to committing. See the [Git documentation] for more information on hooks.
The `pre-commit` hook can be installed by running the following command in a terminal, from the root of the repository:
```shell
cp pre-commit .git/hooks/pre-commit
```
[Git documentation]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
### Pull Request
When you're finished with the changes, create a pull request, also known as a PR.
- Fill the pull request template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
- Don't forget to [link PR to issue] if you are solving one.
- Enable the checkbox to [allow maintainer edits] so the branch can be updated for a merge. Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request additional information.
- We may ask for changes to be made before a PR can be merged, either using [suggested changes] or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
- As you update your PR and apply changes, mark each conversation as [resolved].
- If you run into any merge issues, checkout this [git tutorial] to help you resolve merge conflicts and other issues.
[link PR to issue]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
[allow maintainer edits]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork
[suggested changes]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request
[resolved]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations
[git tutorial]: https://github.com/skills/resolve-merge-conflicts
### Your PR is Merged!
Congratulations! The esp-rs team thanks you for your contributions!

28
Cargo.toml Normal file
View File

@ -0,0 +1,28 @@
[workspace]
resolver = "2"
members = ["xtask"]
exclude = [
"esp-alloc",
"esp-backtrace",
"esp-build",
"esp-config",
"esp-hal",
"esp-hal-embassy",
"esp-hal-procmacros",
"esp-ieee802154",
"esp-lp-hal",
"esp-metadata",
"esp-println",
"esp-riscv-rt",
"esp-wifi",
"esp-storage",
"examples",
"extras/bench-server",
"extras/esp-wifishark",
"extras/ieee802154-sniffer",
"hil-test",
"qa-test",
"xtensa-lx",
"xtensa-lx-rt",
"xtensa-lx-rt/procmacros",
]

123
README.md
View File

@ -1,20 +1,29 @@
# esp-hal
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/esp-rs/esp-hal/ci.yml?label=CI&logo=github&style=flat-square)
![MIT/Apache-2.0 licensed](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/esp-rs/esp-hal/ci.yml?labelColor=1C2C2E&label=CI&logo=github&style=flat-square)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/esp-rs/esp-hal/hil.yml?labelColor=1C2C2E&label=HIL&logo=github&style=flat-square&event=merge_group)
![MIT/Apache-2.0 licensed](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?labelColor=1C2C2E&label=join%20matrix&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
**H**ardware **A**bstraction **L**ayer crates for the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, and **ESP32-S2/S3** from Espressif. Additionally provides support for programming the low-power RISC-V cores found on the **ESP32-C6** and **ESP32-S2/S3**.
Bare-metal (`no_std`) hardware abstraction layer for Espressif devices. Currently supports, to varying degrees, the following devices:
These HALs are `no_std`; if you are looking for `std` support, please use [esp-idf-hal] instead.
- ESP32 Series: _ESP32_
- ESP32-C Series: _ESP32-C2, ESP32-C3, ESP32-C6_
- ESP32-H Series: _ESP32-H2_
- ESP32-S Series: _ESP32-S2, ESP32-S3_
Additionally provides limited support for programming the low-power RISC-V cores found on the _ESP32-C6_, _ESP32-S2_, and _ESP32-S3_ via the [esp-lp-hal] package.
These packages are all `no_std`; if you are looking for `std` support, please use [esp-idf-svc] instead.
If you have any questions, comments, or concerns, please [open an issue], [start a new discussion], or join us on [Matrix]. For additional information regarding any of the crates in this repository, please refer to the relevant crate's README.
> [!NOTE]
>
> This project is still in the relatively early stages of development, and as such there should be no expectation of API stability. A significant number of peripherals currently have drivers implemented but have varying levels of functionality. For most basic tasks, this should be usable already, however some more advanced or uncommon features may not yet be implemented.
> This repository includes crates that are at various stages of maturity and stability. While many functionalities have already been implemented and are usable for most tasks, certain advanced or less common features may still be under development. Each crate may offer different levels of functionality and guarantees.
[esp-idf-hal]: https://github.com/esp-rs/esp-idf-hal
[esp-lp-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp-lp-hal
[esp-idf-svc]: https://github.com/esp-rs/esp-idf-svc
[open an issue]: https://github.com/esp-rs/esp-hal/issues/new
[start a new discussion]: https://github.com/esp-rs/esp-hal/discussions/new
[matrix]: https://matrix.to/#/#esp-rs:matrix.org
@ -23,10 +32,10 @@ If you have any questions, comments, or concerns, please [open an issue], [start
For information relating to the development of Rust applications on ESP devices, please first read [The Rust on ESP Book].
For information about the HAL and how to use it in your own projects, please refer to the documentation on [docs.rs] for the relevant chip.
For information about the HAL and how to use it in your own projects, please refer to the [documentation].
[The Rust on ESP Book]: https://esp-rs.github.io/book/
[docs.rs]: https://docs.rs
[documentation]: https://docs.esp-rs.org/esp-hal/
## Resources
@ -36,98 +45,16 @@ For information about the HAL and how to use it in your own projects, please ref
- [The Rust on ESP Book](https://esp-rs.github.io/book/)
- [Embedded Rust (no_std) on Espressif](https://esp-rs.github.io/no_std-training/)
## HAL Crates
## Crates
### High-Power Cores
This repository is home to a number of different packages; for more information regarding a particular package, please refer to its `README.md` and/or documentation.
| Crate | Documentation | Technical Reference Manual | Target |
| :-----------: | :------------------------------------------------: | :------------------------: | :----------------------------: |
| [esp32-hal] | [![esp32-hal-docs]](https://docs.rs/esp32-hal) | [ESP32] | `xtensa-esp32-none-elf` |
| [esp32c2-hal] | [![esp32c2-hal-docs]](https://docs.rs/esp32c2-hal) | [ESP32-C2] | `riscv32imc-unknown-none-elf` |
| [esp32c3-hal] | [![esp32c3-hal-docs]](https://docs.rs/esp32c3-hal) | [ESP32-C3] | `riscv32imc-unknown-none-elf` |
| [esp32c6-hal] | [![esp32c6-hal-docs]](https://docs.rs/esp32c6-hal) | [ESP32-C6] | `riscv32imac-unknown-none-elf` |
| [esp32h2-hal] | [![esp32h2-hal-docs]](https://docs.rs/esp32h2-hal) | [ESP32-H2] | `riscv32imac-unknown-none-elf` |
| [esp32s2-hal] | [![esp32s2-hal-docs]](https://docs.rs/esp32s2-hal) | [ESP32-S2] | `xtensa-esp32s2-none-elf` |
| [esp32s3-hal] | [![esp32s3-hal-docs]](https://docs.rs/esp32s3-hal) | [ESP32-S3] | `xtensa-esp32s3-none-elf` |
## Contributing
[esp32-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32-hal
[esp32c2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c2-hal
[esp32c3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c3-hal
[esp32c6-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-hal
[esp32h2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32h2-hal
[esp32s2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s2-hal
[esp32s3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s3-hal
[esp32-hal-docs]: https://img.shields.io/docsrs/esp32-hal?color=C96329&logo=rust&style=flat-square
[esp32c2-hal-docs]: https://img.shields.io/docsrs/esp32c2-hal?color=C96329&logo=rust&style=flat-square
[esp32c3-hal-docs]: https://img.shields.io/docsrs/esp32c3-hal?color=C96329&logo=rust&style=flat-square
[esp32c6-hal-docs]: https://img.shields.io/docsrs/esp32c6-hal?color=C96329&logo=rust&style=flat-square
[esp32h2-hal-docs]: https://img.shields.io/docsrs/esp32h2-hal?color=C96329&logo=rust&style=flat-square
[esp32s2-hal-docs]: https://img.shields.io/docsrs/esp32s2-hal?color=C96329&logo=rust&style=flat-square
[esp32s3-hal-docs]: https://img.shields.io/docsrs/esp32s3-hal?color=C96329&logo=rust&style=flat-square
[esp32]: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
[esp32-c2]: https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf
[esp32-c3]: https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf
[esp32-c6]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf
[esp32-h2]: https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf
[esp32-s2]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf
[esp32-s3]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf
We have a number of living documents to aid contributing to the project, please give these a read before modifying code:
### Low-Power Cores
| Crate | Documentation | Target |
| :-----------------: | :------------------------: | :----------------------------: |
| [esp-ulp-riscv-hal] | N/A (_Not yet published_) | `riscv32imc-unknown-none-elf` |
| [esp32c6-lp-hal] | N/A (_Not yet published_) | `riscv32imac-unknown-none-elf` |
[esp-ulp-riscv-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp-ulp-riscv-hal
[esp32c6-lp-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-lp-hal
## Ancillary Crates
There are a number of other crates within the [esp-rs organization] which can be used in conjunction with `esp-hal`:
| Crate | Description |
| :--------------: | :----------------------------------------------------------------------------: |
| [esp-alloc] | A simple `no_std` heap allocator |
| [esp-backtrace] | Backtrace support for bare-metal applications |
| [esp-ieee802154] | Low-level IEEE802.15.4 driver for the ESP32-C6 and ESP32-H2 |
| [esp-openthread] | A bare-metal Thread implementation using `esp-ieee802154` |
| [esp-println] | Provides `print!` and `println!` implementations |
| [esp-storage] | Implementation of [embedded-storage] traits to access unencrypted flash memory |
| [esp-wifi] | `no_std` Wi-Fi/BLE/ESP-NOW support |
[esp-rs organization]: https://github.com/esp-rs
[esp-alloc]: https://github.com/esp-rs/esp-alloc
[esp-backtrace]: https://github.com/esp-rs/esp-backtrace
[esp-ieee802154]: https://github.com/esp-rs/esp-ieee802154
[esp-openthread]: https://github.com/esp-rs/esp-openthread
[esp-println]: https://github.com/esp-rs/esp-println
[esp-storage]: https://github.com/esp-rs/esp-storage
[embedded-storage]: https://github.com/rust-embedded-community/embedded-storage
[esp-wifi]: https://github.com/esp-rs/esp-wifi
## Git Hooks
We provide a simple `pre-commit` hook to verify the formatting of each package prior to committing changes. We _strongly_ encourage use of this git hook.
The hook can be enabled by copying it in to the `.git/hooks/` directory:
```bash
cp pre-commit .git/hooks/pre-commit
```
When using this hook, you can choose to ignore its failure on a per-commit basis by committing with the `--no-verify` flag; however, you will need to be sure that all packages are formatted when submitting a pull request.
## MSRV
The **M**inimum **S**upported **R**ust **V**ersion is `1.67.0` for all packages.
RISC-V is officially supported by the official Rust compiler, however, it should be noted that targeting the Xtensa ISA currently requires the use of the [esp-rs/rust] compiler fork. Our recommend method of installation is [espup].
When targetting the RISC-V architecture _and_ using a `stable` Rust release, it is necessary to set `RUSTC_BOOTSTRAP=1` in order to build successfully; this is not required when using a `nightly` release or when targeting Xtensa.
[esp-rs/rust]: https://github.com/esp-rs/rust
[espup]: https://github.com/esp-rs/espup
- [API-GUIDELINES](https://github.com/esp-rs/esp-hal/blob/main/documentation/API-GUIDELINES.md)
- [CONTRIBUTING-GUIDE](https://github.com/esp-rs/esp-hal/blob/main/documentation/CONTRIBUTING.md)
## License
@ -138,7 +65,7 @@ Licensed under either of:
at your option.
### Contribution
### Contribution notice
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without

View File

@ -0,0 +1,144 @@
# `esp-rs` API Guidelines
## About
This is a living document - make sure to check the latest version of this document.
> [!NOTE]
> Not all of the currently existing code follows this guideline, yet.
In general, the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines) apply to all projects in the ESP-RS GitHub organization where possible.
- Especially for public API but if possible also for internal APIs.
## Amendments to the Rust API Guidelines
- `C-RW-VALUE` and `C-SERDE` do not apply.
- `C-COMMON-TRAITS`:
The set of traits to implement depend on the type and use case. In esp-hal, we can highlight a few such use cases and provide recommendations what should be implemented. If nothing here applies, use your best judgement.
- Driver structures: `Debug`
- Driver configuration: `Default`, `Debug`, `PartialEq/Eq`, `Clone/Copy`, `Hash`
- `Clone/Copy` depends on the size and contents of the structure. They should generally be implemented, unless there is a good reason not to.
- The `Default` configuration needs to make sense for a particular driver, and applying the default configuration must not fail.
- Error types: `Debug`, `PartialEq/Eq`, `Clone/Copy`, `Hash`, `Error`, `Display`
## Construction and Destruction of Drivers
- Drivers must take peripherals via the `PeripheralRef` pattern - they don't consume peripherals directly.
- If a driver requires pins, those pins should be configured using `fn with_signal_name(self, pin: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self` or `fn with_signal_name(self, pin: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self`
- If a driver supports multiple peripheral instances (for example, I2C0 is one such instance):
- The driver should not be generic over the peripheral instance.
- The author must to use `crate::any_peripheral` to define the "any" peripheral instance type.
- The driver must implement a `new` constructor that automatically converts the peripheral instance into the any type.
- If a driver is configurable, configuration options should be implemented as a `Config` struct in the same module where the driver is located.
- The driver's constructor should take the config struct by value, and it should return `Result<Self, ConfigError>`.
- The `ConfigError` enum should be separate from other `Error` enums used by the driver.
- The driver should implement `fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError>`.
- In case the driver's configuration is infallible (all possible combinations of options are supported by the hardware), the `ConfigError` should be implemented as an empty `enum`.
- Configuration structs should derive `procmacros::BuilderLite` in order to automatically implement the Builder Lite pattern for them.
- If a driver implements both blocking and async operations, or only implements blocking operations, but may support asynchronous ones in the future, the driver's type signature must include a `crate::Mode` type parameter.
- By default, constructors must configure the driver for blocking mode. The driver must implement `into_async` (and a matching `into_blocking`) function that reconfigures the driver.
- `into_async` must configure the driver and/or the associated DMA channels. This most often means enabling an interrupt handler.
- `into_blocking` must undo the configuration done by `into_async`.
- The asynchronous driver implementation must also expose the blocking methods (except for interrupt related functions).
- Drivers must have a `Drop` implementation resetting the peripheral to idle state. There are some exceptions to this:
- GPIO where common usage is to "set and drop" so they can't be changed
- Where we don't want to disable the peripheral as it's used internally, for example SYSTIMER is used by `time::now()` API. See `KEEP_ENABLED` in src/system.rs
- A driver doesn't need to do anything special for deinitialization and has a `PeripheralGuard` field which implements the disabling and resetting of the peripheral.
- Consider using a builder-like pattern for driver construction.
## Interoperability
- Don't use `log::XXX!` macros directly - use the wrappers in `fmt.rs` (e.g. just `info!` instead of `log::info!` or importing `log::*`)!
- Consider implementing common ecosystem traits, like the ones in `embedded-hal` or `embassy-embedded-hal`.
- Where the guidelines suggest implementing `Debug`, `defmt::Format` should also be implemented.
- The `defmt::Format` implementation needs to be gated behind the `defmt` feature.
- see [this example](https://github.com/esp-rs/esp-hal/blob/df2b7bd8472cc1d18db0d9441156575570f59bb3/esp-hal/src/spi/mod.rs#L15)
- e.g. `#[cfg_attr(feature = "defmt", derive(defmt::Format))]`
- Implementations of common, but unstable traits (e.g. `embassy_embedded_hal::SetConfig`) need to be gated with the `unstable` feature.
## API Surface
- API documentation must be provided for every new driver and API.
- Private details should not leak into the public API, and should be made private where technically possible.
- Implementation details that _need_ to be public should be marked with `#[doc(hidden)]` and a comment as to why it needs to be public.
- For the time being, this includes any `Instance` traits, and `State` or `Info` structs as well.
- Functions which technically need to be public but shouldn't be callable by the user need to be sealed.
- see [this example in Rust's core library](https://github.com/rust-lang/rust/blob/044a28a4091f2e1a5883f7fa990223f8b200a2cd/library/core/src/error.rs#L89-L100)
- Any public traits, that **must not** be implemented downstream need to be `Sealed`.
- Prefer compile-time checks over runtime checks where possible, prefer a fallible API over panics.
- Follow naming conventions in order to be consistent across drivers - take inspiration from existing drivers.
- Design APIs in a way that they are easy to use.
- Driver API decisions should be assessed individually, don't _not_ just follow embedded-hal or other ecosystem trait crates. Expose the capabilities of the hardware. (Ecosystem traits are implemented on top of the inherent API)
- Avoid type states and extraneous generics whenever possible
- These often lead to usability problems, and tend to just complicate things needlessly - sometimes it can be a good tradeoff to make a type not ZST
- Common cases of useless type info is storing pin information - this is usually not required after configuring the pins and will bloat the complexity of the type massively. When following the `PeripheralRef` pattern it's not needed in order to keep users from re-using the pin while in use
- Avoiding `&mut self` when `&self` is safe to use. `&self` is generally easier to use as an API. Typical applications of this are where the methods just do writes to registers which don't have side effects.
- Maintain order consistency in the API, such as in the case of pairs like RX/TX.
- If your driver provides a way to listen for interrupts, the interrupts should be listed in a `derive(EnumSetType)` enum as opposed to one function per interrupt flag.
- If a driver only implements a subset of a peripheral's capabilities, it should be placed in the `peripheral::subcategory` module.
- For example, if a driver implements the slave-mode I2C driver, it should be placed into `i2c::slave`.
- This helps us reducing the need of introducing breaking changes if we implement additional functionalities.
- Avoid abbreviations and contractions in the API, where possible.
- Saving a few characters may introduce ambiguity, e.g `SpiTransDone`, is it `Transmit` or `Transfer`?
- Common abbreviations, that are well understood such as `Dma` are perfectly fine.
## Maintainability
- Avoid excessive use of macros unless there is no other option; modification of the PAC crates should be considered before resorting to macros.
- Every line of code is a liability. Take some time to see if your implementation can be simplified before opening a PR.
- If you are porting code from ESP-IDF (or anything else), please include a link WITH the commit hash in it, and please highlight the relevant line(s) of code
- If necessary provide further context as comments (consider linking to code, PRs, TRM - make sure to use permanent links, e.g. include the hash when linking to a Git repository, include the revision, page number etc. when linking to TRMs)
- Prefer line comments (//) to block comments (/* ... */)
- Generally, follow common "good practices" and idiomatic Rust style
- All `Future` objects (public or private) must be marked with ``#[must_use = "futures do nothing unless you `.await` or poll them"]``.
- Prefer `cfg_if!` (or, if the branches just pick between separate values of the same variable, `cfg!()`) over multiple exclusive `#[cfg]` attributes. `cfg_if!`/`cfg!()` visually divide the options, often results in simpler conditions and simplifies adding new branches in the future.
## Driver implementation
- If a common `Instance` trait is used for multiple peripherals, those traits should not have any logic implemented in them.
- The `Instance` traits should only be used to access information about a peripheral instance.
- The internal implementation of the driver should be non-generic over the peripheral instance. This helps the compiler produce smaller code.
- The author is encouraged to return a static shared reference to an `Info` and a `State` structure from the `Instance` trait.
- The `Info` struct should describe the peripheral. Do not use any interior mutability.
- The `State` struct should contain counters, wakers and other, mutable state. As this is accessed via a shared reference, interior mutability and atomic variables are preferred.
## Modules Documentation
Modules should have the following documentation format:
```rust
//! # Peripheral Name (Peripheral Acronym)
//!
//! ## Overview
//! Small description of the peripheral, see ESP-IDF docs or TRM
//!
//! ## Configuration
//! Explain how can the peripheral be configured, and which parameters can be configured
//!
//! ## Usage
//! Explain if we implement any external traits
//!
//! ## Examples
//!
//! ### Name of the Example
//! Small description of the example if needed
//! ```rust, no_run
//! ...
//! ```
//!
//! ## Implementation State
//! List unsupported features
```
- If any of the headers is empty, remove it
- When possible, use ESP-IDF docs and TRM as references and include links if possible.
- In case of referencing an ESP-IDF link make it chip-specific, for example:
```
#![doc = concat!("[ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/", crate::soc::chip!(), "/api-reference/peripherals/etm.html)")]
```
- In case of referencing a TRM chapter, use the `crate::trm_markdown_link!()` macro. If you are referring to a particular chapter, you may use `crate::trm_markdown_link!("#chapter_anchor")`.
- Documentation examples must be short
- But must also provide value beyond what the rustdoc generated docs show
- Showing a snippet of a slightly more complex interaction, for example inverting the signals for a driver
- Showing construction if it is more complex, or requires some non-obvious precursor steps. Think about this for drivers that take a generic instance to construct, rustdoc doesn't do a good job of showing what concrete things can be passed into a constructor.
- For more complex scenarios, create an example.
- Use rustdoc syntax for linking to other documentation items instead of markdown links where possible
- https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html

View File

@ -0,0 +1,143 @@
# Welcome to the `esp-hal` Contributing Guide
Thank you for considering contributing to our project! Your efforts help make `esp-hal` a better ecosystem for everyone.
This guide outlines the contribution workflow, from reporting issues and submitting pull requests, to the review process and eventual merger of contributions.
## Quick Navigation
* [New Contributor Guide]
* [Getting Started]
* [Issues: Reporting and Resolving]
* [Making Changes: Fork, Edit, and Pull Request]
* [Testing Your Contributions]
* [Commit Your Updates]
* [Pull Request: From Submission to Merge]
* [Your PR is merged!]
[New Contributor Guide]: #new-contributor-guide
[Getting Started]: #getting-started
[Issues: Reporting and Resolving]: #issues-reporting-and-resolving
[Making Changes: Fork, Edit, and Pull Request]: #making-changes-fork-edit-and-pull-request
[Testing Your Contributions]: #testing-your-contributions
[Commit your updates]: #commit-your-updates
[Pull Request: From Submission to Merge]: #pull-request-from-submission-to-merge
[Your PR is merged!]: #your-pr-is-merged
## New Contributor Guide
Welcome aboard! If you're new to `esp-hal` or open-source contribution, here are some resources to get you started:
* [Understanding the Project]: A high-level overview of `esp-hal`.
* Intro to Open Source Contribution: [GitHub's Guide]
* [Setting Up Git]
* Workflow Insights: [GitHub Flow]
* Collaborating via [Pull Requests]
Before adding or changing code, review the [esp-rs API guidelines].
[Understanding the Project]: README.md
[GitHub's Guide]: https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github
[Setting Up Git]: https://docs.github.com/en/get-started/quickstart/set-up-git
[GitHub Flow]: https://docs.github.com/en/get-started/quickstart/github-flow
[Pull Requests]: https://docs.github.com/en/github/collaborating-with-pull-requests
[esp-rs API guidelines]: ./documentation/API-GUIDELINES.md
## Getting Started
### Issues: Reporting and Resolving
#### Reporting a New Issue
Encountered a problem or have an idea? First, [check existing issues] to avoid duplicates. If your concern is new, use our [issue form] to submit it.
[check existing issues]: https://github.com/esp-rs/esp-hal/issues
[issue form]: https://github.com/esp-rs/esp-hal/issues/new/
#### Working on an Issue
Browse [existing issues] to find one that resonates with you. Use labels for easier filtering. If you decide to tackle an issue, it's courteous (but not mandatory) to let others know by commenting.
[existing issues]: https://github.com/esp-rs/esp-hal/issues
#### Making Changes: Fork, Edit, and Pull Request
1. **Fork**: Start by [forking the repository]. This keeps the main project safe while you make your changes.
2. **Setup**: Ensure you have the latest Rust toolchain via [rustup.rs].
3. **Branch**: Create a branch in your fork for your changes. Keep your changes focused and limited to a single issue or feature.
[forking the repository]: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo
[rustup.rs]: https://rustup.rs/
#### What You Should Do:
* **API changes**: If your contribution changes the API, please adapt the driver (including module level documentation) and examples accordingly and update the [HIL] (Hardware-in-the-Loop) tests.
* **Run Related Examples**: After making changes, run any affected examples to ensure they build successfully and perform as expected.
* **Manual Testing**: For hardware-related changes, manually test your changes on the actual devices when possible. If not, please note it in the corresponding issue, and someone from our team will assist with testing. This is crucial because hardware behavior can sometimes differ from what's simulated or expected.
* **HIL Tests**: Ensure that any changes to the API or hardware interaction logic are reflected in the HIL tests located in the `hil-test` directory. This helps verify the real-world applicability of your changes.
By taking these extra steps to test your contributions, you help maintain the high quality and reliability of `esp-hal`, ensuring it remains a robust platform for everyone.
[HIL]: https://github.com/esp-rs/esp-hal/tree/main/hil-test
### Testing Your Contributions
Ensuring the quality and reliability of `esp-hal` is a shared responsibility, and testing plays a critical role in this process. Our GitHub CI automatically checks the buildability of all examples and drivers within the project. However, automated tests can't catch everything, especially when it comes to the nuanced behavior of hardware interactions. So make sure that the example affected by your change works as expected.
Further steps that can (or should) be taken in testing:
* Using [xtask], build examples for the specified chip.
* Build the documentation and run the doctests if they have been modified using the `build-documentation` and `run-doc-test` commands in [xtask].
* Run the [HIL] tests locally if changes have been made to them.
[xtask]: https://github.com/esp-rs/esp-hal/tree/main/xtask
### Commit Your Updates
Commit your changes once you're satisfied. Review your own work to streamline the review process later. Use `rustfmt` and `cargo clippy` to ensure your code adheres to Rust's conventions.
```shell
rustup component add rustfmt
rustup component add clippy
```
We _strongly_ recommend that you format your code before committing to ensure consistency throughout the project.
To format all packages in the workspace, run the following command in a terminal from the root of the repository:
```shell
cargo xtask fmt-packages
```
We also recommend using the `lint-packages` subcommand, which uses `cargo clippy` and will lint the entire driver in order to catch common mistakes in the code.
```shell
cargo xtask lint-packages
```
This will use `rustfmt` to ensure that all source code is formatted correctly prior to committing.
## Pull Request: From Submission to Merge
* Fill the pull request template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
* [Link your PR] to any relevant issues it addresses.
* [Allow edits from maintainers] so the branch can be updated for a merge. Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request additional information.
* Make sure you add an entry with your changes to the [Changelog]. Also make sure that it is in the appropriate section of the document.
* Make sure you add your changes to the current [migration guide].
* We may ask for changes to be made before a PR can be merged, either using [suggested changes] or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
* As you update your PR and apply changes, mark each conversation as [resolved].
* Resolve merge conflicts if they arise, using resources like [this git tutorial] for help.
[Link your PR]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
[Allow edits from maintainers]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-forkmember
[Changelog]: esp-hal/CHANGELOG.md
[migration guide]: esp-hal/MIGRATING-0.20.md
[suggested changes]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request
[resolved]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request#resolving-conversations
[this git tutorial]: https://github.com/skills/resolve-merge-conflicts
## Your PR is Merged!
Congratulations! The `esp-rs` team thanks you for your contributions!
Contributing to open source extends beyond just code! Each contribution, regardless of size, plays a significant role. We appreciate your involvement in this collective endeavor.

1
esp-alloc/.clippy.toml Normal file
View File

@ -0,0 +1 @@
avoid-breaking-exported-api = false

36
esp-alloc/CHANGELOG.md Normal file
View File

@ -0,0 +1,36 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- `esp_alloc::HEAP.stats()` can now be used to get heap usage informations (#2137)
### Changed
### Fixed
### Removed
## 0.5.0 - 2024-10-10
### Changed
- a global allocator is created in esp-alloc, now you need to add individual memory regions (up to 3) to the allocator (#2099)
## 0.4.0 - 2024-06-04
## 0.3.0 - 2023-04-25
## 0.2.1 - 2023-04-21
## 0.2.0 - 2023-02-22
## 0.1.0 - 2022-07-25
[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-alloc?since=2024-10-10

37
esp-alloc/Cargo.toml Normal file
View File

@ -0,0 +1,37 @@
[package]
name = "esp-alloc"
version = "0.5.0"
edition = "2021"
rust-version = "1.68"
description = "A heap allocator for Espressif devices"
keywords = ["allocator", "embedded", "embedded-hal", "esp32", "espressif", "memory"]
categories = ["embedded", "memory-management", "no-std"]
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
[package.metadata.docs.rs]
default-target = "riscv32imc-unknown-none-elf"
features = ["nightly"]
[dependencies]
defmt = { version = "0.3.8", optional = true }
cfg-if = "1.0.0"
critical-section = "1.1.3"
enumset = "1.1.5"
linked_list_allocator = { version = "0.10.5", default-features = false, features = ["const_mut_refs"] }
document-features = "0.2.10"
[features]
default = []
nightly = []
## Implement `defmt::Format` on certain types.
defmt = ["dep:defmt"]
## Enable this feature if you want to keep stats about the internal heap usage such as:
## - Max memory usage since initialization of the heap
## - Total allocated memory since initialization of the heap
## - Total freed memory since initialization of the heap
##
## ⚠️ Note: Enabling this feature will require extra computation every time alloc/dealloc is called.
internal-heap-stats = []

26
esp-alloc/README.md Normal file
View File

@ -0,0 +1,26 @@
# esp-alloc
[![Crates.io](https://img.shields.io/crates/v/esp-alloc?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-alloc)
[![docs.rs](https://img.shields.io/docsrs/esp-alloc?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-alloc)
![MSRV](https://img.shields.io/badge/MSRV-1.68-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-alloc?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
A simple `no_std` heap allocator for RISC-V and Xtensa processors from Espressif. Supports all currently available ESP32 devices.
**NOTE:** using this as your global allocator requires using Rust 1.68 or greater, or the `nightly` release channel.
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.

589
esp-alloc/src/lib.rs Normal file
View File

@ -0,0 +1,589 @@
//! A `no_std` heap allocator for RISC-V and Xtensa processors from
//! Espressif. Supports all currently available ESP32 devices.
//!
//! **NOTE:** using this as your global allocator requires using Rust 1.68 or
//! greater, or the `nightly` release channel.
//!
//! # Using this as your Global Allocator
//!
//! ```rust
//! use esp_alloc as _;
//!
//! fn init_heap() {
//! const HEAP_SIZE: usize = 32 * 1024;
//! static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();
//!
//! unsafe {
//! esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
//! HEAP.as_mut_ptr() as *mut u8,
//! HEAP_SIZE,
//! esp_alloc::MemoryCapability::Internal.into(),
//! ));
//! }
//! }
//! ```
//!
//! # Using this with the nightly `allocator_api`-feature
//! Sometimes you want to have more control over allocations.
//!
//! For that, it's convenient to use the nightly `allocator_api`-feature,
//! which allows you to specify an allocator for single allocations.
//!
//! **NOTE:** To use this, you have to enable the crate's `nightly` feature
//! flag.
//!
//! Create and initialize an allocator to use in single allocations:
//! ```rust
//! static PSRAM_ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
//!
//! fn init_psram_heap() {
//! unsafe {
//! PSRAM_ALLOCATOR.add_region(esp_alloc::HeapRegion::new(
//! psram::psram_vaddr_start() as *mut u8,
//! psram::PSRAM_BYTES,
//! esp_alloc::MemoryCapability::Internal.into(),
//! ));
//! }
//! }
//! ```
//!
//! And then use it in an allocation:
//! ```rust
//! let large_buffer: Vec<u8, _> = Vec::with_capacity_in(1048576, &PSRAM_ALLOCATOR);
//! ```
//!
//! You can also get stats about the heap usage at anytime with:
//! ```rust
//! let stats: HeapStats = esp_alloc::HEAP.stats();
//! // HeapStats implements the Display and defmt::Format traits, so you can pretty-print the heap stats.
//! println!("{}", stats);
//! ```
//!
//! ```txt
//! HEAP INFO
//! Size: 131068
//! Current usage: 46148
//! Max usage: 46148
//! Total freed: 0
//! Total allocated: 46148
//! Memory Layout:
//! Internal | ████████████░░░░░░░░░░░░░░░░░░░░░░░ | Used: 35% (Used 46148 of 131068, free: 84920)
//! Unused | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ |
//! Unused | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ |
//! ```
//! ## Feature Flags
#![doc = document_features::document_features!()]
#![no_std]
#![cfg_attr(feature = "nightly", feature(allocator_api))]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
mod macros;
#[cfg(feature = "nightly")]
use core::alloc::{AllocError, Allocator};
use core::{
alloc::{GlobalAlloc, Layout},
cell::RefCell,
fmt::Display,
ptr::{self, NonNull},
};
use critical_section::Mutex;
use enumset::{EnumSet, EnumSetType};
use linked_list_allocator::Heap;
/// The global allocator instance
#[global_allocator]
pub static HEAP: EspHeap = EspHeap::empty();
const NON_REGION: Option<HeapRegion> = None;
const BAR_WIDTH: usize = 35;
fn write_bar(f: &mut core::fmt::Formatter<'_>, usage_percent: usize) -> core::fmt::Result {
let used_blocks = BAR_WIDTH * usage_percent / 100;
(0..used_blocks).try_for_each(|_| write!(f, ""))?;
(used_blocks..BAR_WIDTH).try_for_each(|_| write!(f, ""))
}
#[cfg(feature = "defmt")]
fn write_bar_defmt(fmt: defmt::Formatter, usage_percent: usize) {
let used_blocks = BAR_WIDTH * usage_percent / 100;
(0..used_blocks).for_each(|_| defmt::write!(fmt, ""));
(used_blocks..BAR_WIDTH).for_each(|_| defmt::write!(fmt, ""));
}
#[derive(EnumSetType, Debug)]
/// Describes the properties of a memory region
pub enum MemoryCapability {
/// Memory must be internal; specifically it should not disappear when
/// flash/spiram cache is switched off
Internal,
/// Memory must be in SPI RAM
External,
}
/// Stats for a heap region
#[derive(Debug)]
pub struct RegionStats {
/// Total usable size of the heap region in bytes.
size: usize,
/// Currently used size of the heap region in bytes.
used: usize,
/// Free size of the heap region in bytes.
free: usize,
/// Capabilities of the memory region.
capabilities: EnumSet<MemoryCapability>,
}
impl Display for RegionStats {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let usage_percent = self.used * 100 / self.size;
// Display Memory type
if self.capabilities.contains(MemoryCapability::Internal) {
write!(f, "Internal")?;
} else if self.capabilities.contains(MemoryCapability::External) {
write!(f, "External")?;
} else {
write!(f, "Unknown")?;
}
write!(f, " | ")?;
write_bar(f, usage_percent)?;
write!(
f,
" | Used: {}% (Used {} of {}, free: {})",
usage_percent, self.used, self.size, self.free
)
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for RegionStats {
fn format(&self, fmt: defmt::Formatter) {
let usage_percent = self.used * 100 / self.size;
if self.capabilities.contains(MemoryCapability::Internal) {
defmt::write!(fmt, "Internal");
} else if self.capabilities.contains(MemoryCapability::External) {
defmt::write!(fmt, "External");
} else {
defmt::write!(fmt, "Unknown");
}
defmt::write!(fmt, " | ");
write_bar_defmt(fmt, usage_percent);
defmt::write!(
fmt,
" | Used: {}% (Used {} of {}, free: {})",
usage_percent,
self.used,
self.size,
self.free
);
}
}
/// A memory region to be used as heap memory
pub struct HeapRegion {
heap: Heap,
capabilities: EnumSet<MemoryCapability>,
}
impl HeapRegion {
/// Create a new [HeapRegion] with the given capabilities
///
/// # Safety
///
/// - The supplied memory region must be available for the entire program
/// (`'static`).
/// - The supplied memory region must be exclusively available to the heap
/// only, no aliasing.
/// - `size > 0`.
pub unsafe fn new(
heap_bottom: *mut u8,
size: usize,
capabilities: EnumSet<MemoryCapability>,
) -> Self {
let mut heap = Heap::empty();
heap.init(heap_bottom, size);
Self { heap, capabilities }
}
/// Return stats for the current memory region
pub fn stats(&self) -> RegionStats {
RegionStats {
size: self.heap.size(),
used: self.heap.used(),
free: self.heap.free(),
capabilities: self.capabilities,
}
}
}
/// Stats for a heap allocator
///
/// Enable the "internal-heap-stats" feature if you want collect additional heap
/// informations at the cost of extra cpu time during every alloc/dealloc.
#[derive(Debug)]
pub struct HeapStats {
/// Granular stats for all the configured memory regions.
region_stats: [Option<RegionStats>; 3],
/// Total size of all combined heap regions in bytes.
size: usize,
/// Current usage of the heap across all configured regions in bytes.
current_usage: usize,
/// Estimation of the max used heap in bytes.
#[cfg(feature = "internal-heap-stats")]
max_usage: usize,
/// Estimation of the total allocated bytes since initialization.
#[cfg(feature = "internal-heap-stats")]
total_allocated: usize,
/// Estimation of the total freed bytes since initialization.
#[cfg(feature = "internal-heap-stats")]
total_freed: usize,
}
impl Display for HeapStats {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "HEAP INFO")?;
writeln!(f, "Size: {}", self.size)?;
writeln!(f, "Current usage: {}", self.current_usage)?;
#[cfg(feature = "internal-heap-stats")]
{
writeln!(f, "Max usage: {}", self.max_usage)?;
writeln!(f, "Total freed: {}", self.total_freed)?;
writeln!(f, "Total allocated: {}", self.total_allocated)?;
}
writeln!(f, "Memory Layout: ")?;
for region in self.region_stats.iter() {
if let Some(region) = region.as_ref() {
region.fmt(f)?;
writeln!(f)?;
} else {
// Display unused memory regions
write!(f, "Unused | ")?;
write_bar(f, 0)?;
writeln!(f, " |")?;
}
}
Ok(())
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for HeapStats {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "HEAP INFO\n");
defmt::write!(fmt, "Size: {}\n", self.size);
defmt::write!(fmt, "Current usage: {}\n", self.current_usage);
#[cfg(feature = "internal-heap-stats")]
{
defmt::write!(fmt, "Max usage: {}\n", self.max_usage);
defmt::write!(fmt, "Total freed: {}\n", self.total_freed);
defmt::write!(fmt, "Total allocated: {}\n", self.total_allocated);
}
defmt::write!(fmt, "Memory Layout:\n");
for region in self.region_stats.iter() {
if let Some(region) = region.as_ref() {
defmt::write!(fmt, "{}\n", region);
} else {
defmt::write!(fmt, "Unused | ");
write_bar_defmt(fmt, 0);
defmt::write!(fmt, " |\n");
}
}
}
}
/// Internal stats to keep track across multiple regions.
#[cfg(feature = "internal-heap-stats")]
struct InternalHeapStats {
max_usage: usize,
total_allocated: usize,
total_freed: usize,
}
/// A memory allocator
///
/// In addition to what Rust's memory allocator can do it allows to allocate
/// memory in regions satisfying specific needs.
pub struct EspHeap {
heap: Mutex<RefCell<[Option<HeapRegion>; 3]>>,
#[cfg(feature = "internal-heap-stats")]
internal_heap_stats: Mutex<RefCell<InternalHeapStats>>,
}
impl EspHeap {
/// Crate a new UNINITIALIZED heap allocator
pub const fn empty() -> Self {
EspHeap {
heap: Mutex::new(RefCell::new([NON_REGION; 3])),
#[cfg(feature = "internal-heap-stats")]
internal_heap_stats: Mutex::new(RefCell::new(InternalHeapStats {
max_usage: 0,
total_allocated: 0,
total_freed: 0,
})),
}
}
/// Add a memory region to the heap
///
/// `heap_bottom` is a pointer to the location of the bottom of the heap.
///
/// `size` is the size of the heap in bytes.
///
/// You can add up to three regions per allocator.
///
/// Note that:
///
/// - Memory is allocated from the first suitable memory region first
///
/// - The heap grows "upwards", towards larger addresses. Thus `end_addr`
/// must be larger than `start_addr`
///
/// - The size of the heap is `(end_addr as usize) - (start_addr as usize)`.
/// The allocator won't use the byte at `end_addr`.
///
/// # Safety
///
/// - The supplied memory region must be available for the entire program (a
/// `'static` lifetime).
/// - The supplied memory region must be exclusively available to the heap
/// only, no aliasing.
/// - `size > 0`.
pub unsafe fn add_region(&self, region: HeapRegion) {
critical_section::with(|cs| {
let mut regions = self.heap.borrow_ref_mut(cs);
let free = regions
.iter()
.enumerate()
.find(|v| v.1.is_none())
.map(|v| v.0);
if let Some(free) = free {
regions[free] = Some(region);
} else {
panic!(
"Exceeded the maximum of {} heap memory regions",
regions.len()
);
}
});
}
/// Returns an estimate of the amount of bytes in use in all memory regions.
pub fn used(&self) -> usize {
critical_section::with(|cs| {
let regions = self.heap.borrow_ref(cs);
let mut used = 0;
for region in regions.iter() {
if let Some(region) = region.as_ref() {
used += region.heap.used();
}
}
used
})
}
/// Return usage stats for the [Heap].
///
/// Note:
/// [HeapStats] directly implements [Display], so this function can be
/// called from within `println!()` to pretty-print the usage of the
/// heap.
pub fn stats(&self) -> HeapStats {
const EMPTY_REGION_STAT: Option<RegionStats> = None;
let mut region_stats: [Option<RegionStats>; 3] = [EMPTY_REGION_STAT; 3];
critical_section::with(|cs| {
let mut used = 0;
let mut free = 0;
let regions = self.heap.borrow_ref(cs);
for (id, region) in regions.iter().enumerate() {
if let Some(region) = region.as_ref() {
let stats = region.stats();
free += stats.free;
used += stats.used;
region_stats[id] = Some(region.stats());
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "internal-heap-stats")] {
let internal_heap_stats = self.internal_heap_stats.borrow_ref(cs);
HeapStats {
region_stats,
size: free + used,
current_usage: used,
max_usage: internal_heap_stats.max_usage,
total_allocated: internal_heap_stats.total_allocated,
total_freed: internal_heap_stats.total_freed,
}
} else {
HeapStats {
region_stats,
size: free + used,
current_usage: used,
}
}
}
})
}
/// Returns an estimate of the amount of bytes available.
pub fn free(&self) -> usize {
self.free_caps(EnumSet::empty())
}
/// The free heap satisfying the given requirements
pub fn free_caps(&self, capabilities: EnumSet<MemoryCapability>) -> usize {
critical_section::with(|cs| {
let regions = self.heap.borrow_ref(cs);
let mut free = 0;
for region in regions.iter().filter(|region| {
if region.is_some() {
region
.as_ref()
.unwrap()
.capabilities
.is_superset(capabilities)
} else {
false
}
}) {
if let Some(region) = region.as_ref() {
free += region.heap.free();
}
}
free
})
}
/// Allocate memory in a region satisfying the given requirements.
///
/// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure that `layout` has non-zero size.
///
/// The allocated block of memory may or may not be initialized.
pub unsafe fn alloc_caps(
&self,
capabilities: EnumSet<MemoryCapability>,
layout: Layout,
) -> *mut u8 {
critical_section::with(|cs| {
#[cfg(feature = "internal-heap-stats")]
let before = self.used();
let mut regions = self.heap.borrow_ref_mut(cs);
let mut iter = (*regions).iter_mut().filter(|region| {
if region.is_some() {
region
.as_ref()
.unwrap()
.capabilities
.is_superset(capabilities)
} else {
false
}
});
let res = loop {
if let Some(Some(region)) = iter.next() {
let res = region.heap.allocate_first_fit(layout);
if let Ok(res) = res {
break Some(res);
}
} else {
break None;
}
};
res.map_or(ptr::null_mut(), |allocation| {
#[cfg(feature = "internal-heap-stats")]
{
let mut internal_heap_stats = self.internal_heap_stats.borrow_ref_mut(cs);
drop(regions);
// We need to call used because [linked_list_allocator::Heap] does internal size
// alignment so we cannot use the size provided by the layout.
let used = self.used();
internal_heap_stats.total_allocated += used - before;
internal_heap_stats.max_usage =
core::cmp::max(internal_heap_stats.max_usage, used);
}
allocation.as_ptr()
})
})
}
}
unsafe impl GlobalAlloc for EspHeap {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
self.alloc_caps(EnumSet::empty(), layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if ptr.is_null() {
return;
}
critical_section::with(|cs| {
#[cfg(feature = "internal-heap-stats")]
let before = self.used();
let mut regions = self.heap.borrow_ref_mut(cs);
let mut iter = (*regions).iter_mut();
while let Some(Some(region)) = iter.next() {
if region.heap.bottom() <= ptr && region.heap.top() >= ptr {
region.heap.deallocate(NonNull::new_unchecked(ptr), layout);
}
}
#[cfg(feature = "internal-heap-stats")]
{
let mut internal_heap_stats = self.internal_heap_stats.borrow_ref_mut(cs);
drop(regions);
// We need to call `used()` because [linked_list_allocator::Heap] does internal
// size alignment so we cannot use the size provided by the
// layout.
internal_heap_stats.total_freed += before - self.used();
}
})
}
}
#[cfg(feature = "nightly")]
unsafe impl Allocator for EspHeap {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let raw_ptr = unsafe { self.alloc(layout) };
if raw_ptr.is_null() {
return Err(AllocError);
}
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.dealloc(ptr.as_ptr(), layout);
}
}

43
esp-alloc/src/macros.rs Normal file
View File

@ -0,0 +1,43 @@
//! Macros provided for convenience
/// Initialize a global heap allocator providing a heap of the given size in
/// bytes
#[macro_export]
macro_rules! heap_allocator {
($size:expr) => {{
static mut HEAP: core::mem::MaybeUninit<[u8; $size]> = core::mem::MaybeUninit::uninit();
unsafe {
$crate::HEAP.add_region($crate::HeapRegion::new(
HEAP.as_mut_ptr() as *mut u8,
$size,
$crate::MemoryCapability::Internal.into(),
));
}
}};
}
/// Initialize a global heap allocator backed by PSRAM
///
/// You need a SoC which supports PSRAM
/// and activate the feature to enable it. You need to pass the PSRAM peripheral
/// and the psram module path.
///
/// # Usage
/// ```rust, no_run
/// esp_alloc::psram_allocator!(peripherals.PSRAM, hal::psram);
/// ```
#[macro_export]
macro_rules! psram_allocator {
($peripheral:expr, $psram_module:path) => {{
use $psram_module as _psram;
let (start, size) = _psram::psram_raw_parts(&$peripheral);
unsafe {
$crate::HEAP.add_region($crate::HeapRegion::new(
start,
size,
$crate::MemoryCapability::External.into(),
));
}
}};
}

View File

@ -0,0 +1,63 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
### Changed
### Fixed
### Removed
## 0.14.2 - 2024-10-10
### Fixed
- Fix build when not using `panic-handler` (#2257)
## 0.14.1 - 2024-09-06
### Added
### Changed
- Print a more helpful message in case of a `Cp0Disabled` exception (#2061)
### Fixed
### Removed
## 0.14.0 - 2024-08-29
### Added
- Add custom-pre-backtrace feature (#1822)
### Changed
- Improve panic message printing (#1823)
## 0.13.0 - 2024-07-16
No changes - published to avoid conflicts with `esp-println`
## 0.12.2 - 2024-07-15
### Changed
- Remove build script check for `nightly-2024-06-12` (#1788)
## 0.12.1 - 2024-06-19
### Fixed
- Fix compilation for nightly after 2024-06-12. (#1681)
- Only prints float registers on targets which have them. (#1690)
[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-backtrace?since=2024-10-10

55
esp-backtrace/Cargo.toml Normal file
View File

@ -0,0 +1,55 @@
[package]
name = "esp-backtrace"
version = "0.14.2"
edition = "2021"
rust-version = "1.76.0"
description = "Bare-metal backtrace support for Espressif devices"
keywords = ["backtrace", "embedded", "esp32", "espressif"]
categories = ["embedded", "hardware-support", "no-std"]
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
[package.metadata.docs.rs]
default-target = "riscv32imc-unknown-none-elf"
features = ["esp32c3", "panic-handler", "exception-handler", "println", "esp-println/uart"]
[dependencies]
defmt = { version = "0.3.8", optional = true }
esp-println = { version = "0.12.0", optional = true, default-features = false, path = "../esp-println" }
semihosting = { version = "0.1.15", optional = true }
[build-dependencies]
esp-build = { version = "0.1.0", path = "../esp-build" }
[features]
default = ["colors"]
# You must enable exactly one of the below features to support the correct chip:
esp32 = ["esp-println?/esp32", "semihosting?/openocd-semihosting", "print-float-registers"]
esp32c2 = ["esp-println?/esp32c2"]
esp32c3 = ["esp-println?/esp32c3"]
esp32c6 = ["esp-println?/esp32c6"]
esp32h2 = ["esp-println?/esp32h2"]
esp32p4 = ["esp-println?/esp32p4"]
esp32s2 = ["esp-println?/esp32s2", "semihosting?/openocd-semihosting"]
esp32s3 = ["esp-println?/esp32s3", "semihosting?/openocd-semihosting", "print-float-registers"]
# Use esp-println
println = ["dep:esp-println"]
# Use defmt
defmt = ["dep:defmt"]
print-float-registers = [] # TODO support esp32p4
# You may optionally enable one or more of the below features to provide
# additional functionality:
colors = []
custom-halt = []
custom-pre-backtrace = []
exception-handler = []
halt-cores = []
panic-handler = []
[lints.rust]
unexpected_cfgs = "allow"

60
esp-backtrace/README.md Normal file
View File

@ -0,0 +1,60 @@
# esp-backtrace - backtrace for ESP32 bare-metal
[![Crates.io](https://img.shields.io/crates/v/esp-backtrace?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-backtrace)
[![docs.rs](https://img.shields.io/docsrs/esp-backtrace?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-backtrace)
![MSRV](https://img.shields.io/badge/MSRV-1.76-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-backtrace?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
Supports the ESP32, ESP32-C2/C3/C6, ESP32-H2, ESP32-P4, and ESP32-S2/S3. Optional exception and panic handlers are included, both of which can be enabled via their respective features.
Please note that when targeting a RISC-V device, you **need** to force frame pointers (i.e. `"-C", "force-frame-pointers",` in your `.cargo/config.toml`); this is **not** required for Xtensa.
You can get an array of backtrace addresses (currently limited to 10) via `arch::backtrace()` if
you want to create a backtrace yourself (i.e. not using the panic or exception handler).
When using the panic and/or exception handler make sure to include `use esp_backtrace as _;`.
## Features
| Feature | Description |
|----------------------|--------------------------------------------------------------------------------------------------------------------|
| esp32 | Target ESP32 |
| esp32c2 | Target ESP32-C2 |
| esp32c3 | Target ESP32-C3 |
| esp32c6 | Target ESP32-C6 |
| esp32h2 | Target ESP32-H2 |
| esp32p4 | Target ESP32-P4 |
| esp32s2 | Target ESP32-S2 |
| esp32s3 | Target ESP32-S3 |
| panic-handler | Include a panic handler, will add `esp-println` as a dependency |
| exception-handler | Include an exception handler, will add `esp-println` as a dependency |
| println | Use `esp-println` to print messages |
| defmt | Use `defmt` logging to print messages\* (check [example](https://github.com/playfulFence/backtrace-defmt-example)) |
| colors | Print messages in red\* |
| halt-cores | Halt both CPUs on ESP32 / ESP32-S3 instead of doing a `loop {}` in case of a panic or exception |
| semihosting | Call `semihosting::process::abort()` on panic. |
| custom-halt | Invoke the extern function `custom_halt()` instead of doing a `loop {}` in case of a panic or exception |
| custom-pre-backtrace | Invoke the extern function `custom_pre_backtrace()` before handling a panic or exception |
\* _only used for panic and exception handlers_
### `defmt` Feature
Please note that `defmt` does _not_ provide MSRV guarantees with releases, and as such we are not able to make any MSRV guarantees when this feature is enabled. For more information refer to the MSRV section of `defmt`'s README:
https://github.com/knurling-rs/defmt?tab=readme-ov-file#msrv
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.

15
esp-backtrace/build.rs Normal file
View File

@ -0,0 +1,15 @@
use esp_build::assert_unique_used_features;
fn main() {
// Ensure that only a single chip is specified:
assert_unique_used_features!(
"esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4", "esp32s2", "esp32s3"
);
// Ensure that exactly a backend is selected:
assert_unique_used_features!("defmt", "println");
if cfg!(feature = "custom-halt") && cfg!(feature = "halt-cores") {
panic!("Only one of `custom-halt` and `halt-cores` can be enabled");
}
}

341
esp-backtrace/src/lib.rs Normal file
View File

@ -0,0 +1,341 @@
#![allow(rustdoc::bare_urls, unused_macros)]
#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))]
#![doc = include_str!("../README.md")]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
#![no_std]
#[cfg(feature = "defmt")]
use defmt as _;
#[cfg(feature = "println")]
use esp_println as _;
const MAX_BACKTRACE_ADDRESSES: usize = 10;
#[cfg(feature = "colors")]
const RESET: &str = "\u{001B}[0m";
#[cfg(feature = "colors")]
const RED: &str = "\u{001B}[31m";
#[cfg(feature = "defmt")]
macro_rules! println {
("") => {
// Do nothing if the string is just a space
};
($($arg:tt)*) => {
defmt::error!($($arg)*);
};
}
#[cfg(all(feature = "println", not(feature = "defmt")))]
macro_rules! println {
($($arg:tt)*) => {
esp_println::println!($($arg)*);
};
}
#[allow(unused, unused_variables)]
fn set_color_code(code: &str) {
#[cfg(feature = "println")]
{
println!("{}", code);
}
}
#[cfg_attr(target_arch = "riscv32", path = "riscv.rs")]
#[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")]
pub mod arch;
#[cfg(feature = "panic-handler")]
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
pre_backtrace();
#[cfg(feature = "colors")]
set_color_code(RED);
println!("");
println!("====================== PANIC ======================");
#[cfg(not(feature = "defmt"))]
println!("{}", info);
#[cfg(feature = "defmt")]
println!("{}", defmt::Display2Format(info));
println!("");
println!("Backtrace:");
println!("");
let backtrace = crate::arch::backtrace();
#[cfg(target_arch = "riscv32")]
if backtrace.iter().filter(|e| e.is_some()).count() == 0 {
println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)");
}
for addr in backtrace.into_iter().flatten() {
#[cfg(all(feature = "colors", feature = "println"))]
println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET);
#[cfg(not(all(feature = "colors", feature = "println")))]
println!("0x{:x}", addr - crate::arch::RA_OFFSET);
}
#[cfg(feature = "colors")]
set_color_code(RESET);
#[cfg(feature = "semihosting")]
semihosting::process::abort();
#[cfg(not(feature = "semihosting"))]
halt();
}
#[cfg(all(feature = "exception-handler", target_arch = "xtensa"))]
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __user_exception(cause: arch::ExceptionCause, context: arch::Context) {
pre_backtrace();
#[cfg(feature = "colors")]
set_color_code(RED);
// Unfortunately, a different formatter string is used
#[cfg(not(feature = "defmt"))]
esp_println::println!("\n\nException occurred '{}'", cause);
#[cfg(feature = "defmt")]
defmt::error!("\n\nException occurred '{}'", cause);
println!("{:?}", context);
let backtrace = crate::arch::backtrace_internal(context.A1, 0);
for e in backtrace {
if let Some(addr) = e {
println!("0x{:x}", addr);
}
}
println!("");
println!("");
println!("");
#[cfg(feature = "colors")]
set_color_code(RESET);
#[cfg(feature = "semihosting")]
semihosting::process::abort();
#[cfg(not(feature = "semihosting"))]
halt();
}
#[cfg(all(feature = "exception-handler", target_arch = "riscv32"))]
#[export_name = "ExceptionHandler"]
fn exception_handler(context: &arch::TrapFrame) -> ! {
pre_backtrace();
let mepc = context.pc;
let code = context.mcause & 0xff;
let mtval = context.mtval;
#[cfg(feature = "colors")]
set_color_code(RED);
if code == 14 {
println!("");
println!(
"Stack overflow detected at 0x{:x} called by 0x{:x}",
mepc, context.ra
);
println!("");
} else {
let code = match code {
0 => "Instruction address misaligned",
1 => "Instruction access fault",
2 => "Illegal instruction",
3 => "Breakpoint",
4 => "Load address misaligned",
5 => "Load access fault",
6 => "Store/AMO address misaligned",
7 => "Store/AMO access fault",
8 => "Environment call from U-mode",
9 => "Environment call from S-mode",
10 => "Reserved",
11 => "Environment call from M-mode",
12 => "Instruction page fault",
13 => "Load page fault",
14 => "Reserved",
15 => "Store/AMO page fault",
_ => "UNKNOWN",
};
println!(
"Exception '{}' mepc=0x{:08x}, mtval=0x{:08x}",
code, mepc, mtval
);
#[cfg(not(feature = "defmt"))]
println!("{:x?}", context);
#[cfg(feature = "defmt")]
println!("{:?}", context);
let backtrace = crate::arch::backtrace_internal(context.s0 as u32, 0);
if backtrace.iter().filter(|e| e.is_some()).count() == 0 {
println!("No backtrace available - make sure to force frame-pointers. (see https://crates.io/crates/esp-backtrace)");
}
for addr in backtrace.into_iter().flatten() {
#[cfg(all(feature = "colors", feature = "println"))]
println!("{}0x{:x}", RED, addr - crate::arch::RA_OFFSET);
#[cfg(not(all(feature = "colors", feature = "println")))]
println!("0x{:x}", addr - crate::arch::RA_OFFSET);
}
}
println!("");
println!("");
println!("");
#[cfg(feature = "colors")]
set_color_code(RESET);
#[cfg(feature = "semihosting")]
semihosting::process::abort();
#[cfg(not(feature = "semihosting"))]
halt();
}
// Ensure that the address is in DRAM and that it is 16-byte aligned.
//
// Based loosely on the `esp_stack_ptr_in_dram` function from
// `components/esp_hw_support/include/esp_memory_utils.h` in ESP-IDF.
//
// Address ranges can be found in `components/soc/$CHIP/include/soc/soc.h` as
// `SOC_DRAM_LOW` and `SOC_DRAM_HIGH`.
fn is_valid_ram_address(address: u32) -> bool {
if (address & 0xF) != 0 {
return false;
}
#[cfg(feature = "esp32")]
if !(0x3FFA_E000..=0x4000_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32c2")]
if !(0x3FCA_0000..=0x3FCE_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32c3")]
if !(0x3FC8_0000..=0x3FCE_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32c6")]
if !(0x4080_0000..=0x4088_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32h2")]
if !(0x4080_0000..=0x4085_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32p4")]
if !(0x4FF0_0000..=0x4FFC_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32s2")]
if !(0x3FFB_0000..=0x4000_0000).contains(&address) {
return false;
}
#[cfg(feature = "esp32s3")]
if !(0x3FC8_8000..=0x3FD0_0000).contains(&address) {
return false;
}
true
}
#[cfg(all(
any(
not(any(feature = "esp32", feature = "esp32p4", feature = "esp32s3")),
not(feature = "halt-cores")
),
not(feature = "custom-halt")
))]
#[allow(unused)]
fn halt() -> ! {
loop {
continue;
}
}
#[cfg(feature = "custom-halt")]
fn halt() -> ! {
extern "Rust" {
fn custom_halt() -> !;
}
unsafe { custom_halt() }
}
// TODO: Enable `halt` function for `esp32p4` feature once implemented
#[cfg(all(any(feature = "esp32", feature = "esp32s3"), feature = "halt-cores"))]
#[allow(unused)]
fn halt() -> ! {
#[cfg(feature = "esp32")]
mod registers {
pub(crate) const OPTIONS0: u32 = 0x3ff48000;
pub(crate) const SW_CPU_STALL: u32 = 0x3ff480ac;
}
#[cfg(feature = "esp32p4")]
mod registers {
pub(crate) const SW_CPU_STALL: u32 = 0x50115200;
}
#[cfg(feature = "esp32s3")]
mod registers {
pub(crate) const OPTIONS0: u32 = 0x60008000;
pub(crate) const SW_CPU_STALL: u32 = 0x600080bc;
}
let sw_cpu_stall = registers::SW_CPU_STALL as *mut u32;
#[cfg(feature = "esp32p4")]
unsafe {}
#[cfg(not(feature = "esp32p4"))]
unsafe {
// We need to write the value "0x86" to stall a particular core. The write
// location is split into two separate bit fields named "c0" and "c1", and the
// two fields are located in different registers. Each core has its own pair of
// "c0" and "c1" bit fields.
let options0 = registers::OPTIONS0 as *mut u32;
options0.write_volatile(options0.read_volatile() & !(0b1111) | 0b1010);
sw_cpu_stall.write_volatile(
sw_cpu_stall.read_volatile() & !(0b111111 << 20) & !(0b111111 << 26)
| (0x21 << 20)
| (0x21 << 26),
);
}
loop {}
}
#[cfg(not(feature = "custom-pre-backtrace"))]
#[allow(unused)]
fn pre_backtrace() {}
#[cfg(feature = "custom-pre-backtrace")]
fn pre_backtrace() {
extern "Rust" {
fn custom_pre_backtrace();
}
unsafe { custom_pre_backtrace() }
}

219
esp-backtrace/src/riscv.rs Normal file
View File

@ -0,0 +1,219 @@
use core::arch::asm;
use crate::MAX_BACKTRACE_ADDRESSES;
// subtract 4 from the return address
// the return address is the address following the JALR
// we get better results (especially if the caller was the last instruction in
// the calling function) if we report the address of the JALR itself
// even if it was a C.JALR we should get good results using RA - 4
#[allow(unused)]
pub(super) const RA_OFFSET: usize = 4;
/// Registers saved in trap handler
#[doc(hidden)]
#[derive(Default, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)]
#[cfg(feature = "exception-handler")]
pub(crate) struct TrapFrame {
/// Return address, stores the address to return to after a function call or
/// interrupt.
pub ra: usize,
/// Temporary register t0, used for intermediate values.
pub t0: usize,
/// Temporary register t1, used for intermediate values.
pub t1: usize,
/// Temporary register t2, used for intermediate values.
pub t2: usize,
/// Temporary register t3, used for intermediate values.
pub t3: usize,
/// Temporary register t4, used for intermediate values.
pub t4: usize,
/// Temporary register t5, used for intermediate values.
pub t5: usize,
/// Temporary register t6, used for intermediate values.
pub t6: usize,
/// Argument register a0, typically used to pass the first argument to a
/// function.
pub a0: usize,
/// Argument register a1, typically used to pass the second argument to a
/// function.
pub a1: usize,
/// Argument register a2, typically used to pass the third argument to a
/// function.
pub a2: usize,
/// Argument register a3, typically used to pass the fourth argument to a
/// function.
pub a3: usize,
/// Argument register a4, typically used to pass the fifth argument to a
/// function.
pub a4: usize,
/// Argument register a5, typically used to pass the sixth argument to a
/// function.
pub a5: usize,
/// Argument register a6, typically used to pass the seventh argument to a
/// function.
pub a6: usize,
/// Argument register a7, typically used to pass the eighth argument to a
/// function.
pub a7: usize,
/// Saved register s0, used to hold values across function calls.
pub s0: usize,
/// Saved register s1, used to hold values across function calls.
pub s1: usize,
/// Saved register s2, used to hold values across function calls.
pub s2: usize,
/// Saved register s3, used to hold values across function calls.
pub s3: usize,
/// Saved register s4, used to hold values across function calls.
pub s4: usize,
/// Saved register s5, used to hold values across function calls.
pub s5: usize,
/// Saved register s6, used to hold values across function calls.
pub s6: usize,
/// Saved register s7, used to hold values across function calls.
pub s7: usize,
/// Saved register s8, used to hold values across function calls.
pub s8: usize,
/// Saved register s9, used to hold values across function calls.
pub s9: usize,
/// Saved register s10, used to hold values across function calls.
pub s10: usize,
/// Saved register s11, used to hold values across function calls.
pub s11: usize,
/// Global pointer register, holds the address of the global data area.
pub gp: usize,
/// Thread pointer register, holds the address of the thread-local storage
/// area.
pub tp: usize,
/// Stack pointer register, holds the address of the top of the stack.
pub sp: usize,
/// Program counter, stores the address of the next instruction to be
/// executed.
pub pc: usize,
/// Machine status register, holds the current status of the processor,
/// including interrupt enable bits and privilege mode.
pub mstatus: usize,
/// Machine cause register, contains the reason for the trap (e.g.,
/// exception or interrupt number).
pub mcause: usize,
/// Machine trap value register, contains additional information about the
/// trap (e.g., faulting address).
pub mtval: usize,
}
#[cfg(feature = "exception-handler")]
impl core::fmt::Debug for TrapFrame {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
fmt,
"TrapFrame
PC=0x{:08x} RA/x1=0x{:08x} SP/x2=0x{:08x} GP/x3=0x{:08x} TP/x4=0x{:08x}
T0/x5=0x{:08x} T1/x6=0x{:08x} T2/x7=0x{:08x} S0/FP/x8=0x{:08x} S1/x9=0x{:08x}
A0/x10=0x{:08x} A1/x11=0x{:08x} A2/x12=0x{:08x} A3/x13=0x{:08x} A4/x14=0x{:08x}
A5/x15=0x{:08x} A6/x16=0x{:08x} A7/x17=0x{:08x} S2/x18=0x{:08x} S3/x19=0x{:08x}
S4/x20=0x{:08x} S5/x21=0x{:08x} S6/x22=0x{:08x} S7/x23=0x{:08x} S8/x24=0x{:08x}
S9/x25=0x{:08x} S10/x26=0x{:08x} S11/x27=0x{:08x} T3/x28=0x{:08x} T4/x29=0x{:08x}
T5/x30=0x{:08x} T6/x31=0x{:08x}
MSTATUS=0x{:08x}
MCAUSE=0x{:08x}
MTVAL=0x{:08x}
",
self.pc,
self.ra,
self.gp,
self.sp,
self.tp,
self.t0,
self.t1,
self.t2,
self.s0,
self.s1,
self.a0,
self.a1,
self.a2,
self.a3,
self.a4,
self.a5,
self.a6,
self.a7,
self.s2,
self.s3,
self.s4,
self.s5,
self.s6,
self.s7,
self.s8,
self.s9,
self.s10,
self.s11,
self.t3,
self.t4,
self.t5,
self.t6,
self.mstatus,
self.mcause,
self.mtval,
)
}
}
/// Get an array of backtrace addresses.
///
/// This needs `force-frame-pointers` enabled.
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let fp = unsafe {
let mut _tmp: u32;
asm!("mv {0}, x8", out(reg) _tmp);
_tmp
};
backtrace_internal(fp, 2)
}
pub(crate) fn backtrace_internal(
fp: u32,
suppress: i32,
) -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let mut result = [None; 10];
let mut index = 0;
let mut fp = fp;
let mut suppress = suppress;
let mut old_address = 0;
loop {
unsafe {
let address = (fp as *const u32).offset(-1).read_volatile(); // RA/PC
fp = (fp as *const u32).offset(-2).read_volatile(); // next FP
if old_address == address {
break;
}
old_address = address;
if address == 0 {
break;
}
if !crate::is_valid_ram_address(fp) {
break;
}
if suppress == 0 {
result[index] = Some(address as usize);
index += 1;
if index >= MAX_BACKTRACE_ADDRESSES {
break;
}
} else {
suppress -= 1;
}
}
}
result
}

424
esp-backtrace/src/xtensa.rs Normal file
View File

@ -0,0 +1,424 @@
use core::{arch::asm, fmt::Display};
use crate::MAX_BACKTRACE_ADDRESSES;
// subtract 3 from the return address
// the return address is the address following the callxN
// we get better results (especially if the caller was the last function in the
// calling function) if we report the address of callxN itself
#[allow(unused)]
pub(super) const RA_OFFSET: usize = 3;
/// Exception Cause
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)]
pub enum ExceptionCause {
/// Illegal Instruction
IllegalInstruction = 0,
/// System Call (Syscall Instruction)
Syscall = 1,
/// Instruction Fetch Error
InstrFetchError = 2,
/// Load Store Error
LoadStoreError = 3,
/// Level 1 Interrupt
LevelOneInterrupt = 4,
/// Stack Extension Assist (movsp Instruction) For Alloca
Alloca = 5,
/// Integer Divide By Zero
DivideByZero = 6,
/// Use Of Failed Speculative Access (Not Implemented)
NextPCValueIllegal = 7,
/// Privileged Instruction
PrivilegedInstruction = 8,
/// Unaligned Load Or Store
UnalignedLoadOrStore = 9,
/// Reserved
ExternalRegisterPrivilegeError = 10,
/// Reserved
ExclusiveError = 11,
/// Pif Data Error On Instruction Fetch (Rb-200x And Later)
InstrDataError = 12,
/// Pif Data Error On Load Or Store (Rb-200x And Later)
LoadStoreDataError = 13,
/// Pif Address Error On Instruction Fetch (Rb-200x And Later)
InstrAddrError = 14,
/// Pif Address Error On Load Or Store (Rb-200x And Later)
LoadStoreAddrError = 15,
/// Itlb Miss (No Itlb Entry Matches, Hw Refill Also Missed)
ItlbMiss = 16,
/// Itlb Multihit (Multiple Itlb Entries Match)
ItlbMultiHit = 17,
/// Ring Privilege Violation On Instruction Fetch
InstrRing = 18,
/// Size Restriction On Ifetch (Not Implemented)
Reserved19 = 19,
/// Cache Attribute Does Not Allow Instruction Fetch
InstrProhibited = 20,
/// Reserved
Reserved21 = 21,
/// Reserved
Reserved22 = 22,
/// Reserved
Reserved23 = 23,
/// Dtlb Miss (No Dtlb Entry Matches, Hw Refill Also Missed)
DtlbMiss = 24,
/// Dtlb Multihit (Multiple Dtlb Entries Match)
DtlbMultiHit = 25,
/// Ring Privilege Violation On Load Or Store
LoadStoreRing = 26,
/// Size Restriction On Load/Store (Not Implemented)
Reserved27 = 27,
/// Cache Attribute Does Not Allow Load
LoadProhibited = 28,
/// Cache Attribute Does Not Allow Store
StoreProhibited = 29,
/// Reserved
Reserved30 = 30,
/// Reserved
Reserved31 = 31,
/// Access To Coprocessor 0 When Disabled
Cp0Disabled = 32,
/// Access To Coprocessor 1 When Disabled
Cp1Disabled = 33,
/// Access To Coprocessor 2 When Disabled
Cp2Disabled = 34,
/// Access To Coprocessor 3 When Disabled
Cp3Disabled = 35,
/// Access To Coprocessor 4 When Disabled
Cp4Disabled = 36,
/// Access To Coprocessor 5 When Disabled
Cp5Disabled = 37,
/// Access To Coprocessor 6 When Disabled
Cp6Disabled = 38,
/// Access To Coprocessor 7 When Disabled
Cp7Disabled = 39,
/// None
None = 255,
}
impl Display for ExceptionCause {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if *self == Self::Cp0Disabled {
write!(f, "Cp0Disabled (Access to the floating point coprocessor is not allowed. You may want to enable the `float-save-restore` feature of the `xtensa-lx-rt` crate.)")
} else {
write!(f, "{:?}", self)
}
}
}
#[doc(hidden)]
#[allow(non_snake_case)]
#[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)]
pub struct Context {
/// Program counter, stores the address of the next instruction to be
/// executed.
pub PC: u32,
/// Processor status, holds various status flags for the CPU.
pub PS: u32,
/// General-purpose register A0 used for data storage and manipulation.
pub A0: u32,
/// General-purpose register A1 used for data storage and manipulation.
pub A1: u32,
/// General-purpose register A2 used for data storage and manipulation.
pub A2: u32,
/// General-purpose register A3 used for data storage and manipulation.
pub A3: u32,
/// General-purpose register A4 used for data storage and manipulation.
pub A4: u32,
/// General-purpose register A5 used for data storage and manipulation.
pub A5: u32,
/// General-purpose register A6 used for data storage and manipulation.
pub A6: u32,
/// General-purpose register A7 used for data storage and manipulation.
pub A7: u32,
/// General-purpose register A8 used for data storage and manipulation.
pub A8: u32,
/// General-purpose register A9 used for data storage and manipulation.
pub A9: u32,
/// General-purpose register A10 used for data storage and manipulation.
pub A10: u32,
/// General-purpose register A11 used for data storage and manipulation.
pub A11: u32,
/// General-purpose register A12 used for data storage and manipulation.
pub A12: u32,
/// General-purpose register A13 used for data storage and manipulation.
pub A13: u32,
/// General-purpose register A14 used for data storage and manipulation.
pub A14: u32,
/// General-purpose register A15 used for data storage and manipulation.
pub A15: u32,
/// Shift amount register, used for shift and rotate instructions.
pub SAR: u32,
/// Exception cause, indicates the reason for the last exception.
pub EXCCAUSE: u32,
/// Exception address, holds the address related to the exception.
pub EXCVADDR: u32,
/// Loop start address, used in loop instructions.
pub LBEG: u32,
/// Loop end address, used in loop instructions.
pub LEND: u32,
/// Loop counter, used to count iterations in loop instructions.
pub LCOUNT: u32,
/// Thread pointer, used for thread-local storage.
pub THREADPTR: u32,
/// Compare register, used for certain compare instructions.
pub SCOMPARE1: u32,
/// Break register, used for breakpoint-related operations.
pub BR: u32,
/// Accumulator low register, used for extended arithmetic operations.
pub ACCLO: u32,
/// Accumulator high register, used for extended arithmetic operations.
pub ACCHI: u32,
/// Additional register M0 used for special operations.
pub M0: u32,
/// Additional register M1 used for special operations.
pub M1: u32,
/// Additional register M2 used for special operations.
pub M2: u32,
/// Additional register M3 used for special operations.
pub M3: u32,
/// 64-bit floating-point register (low part), available if the
/// `print-float-registers` feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F64R_LO: u32,
/// 64-bit floating-point register (high part), available if the
/// `print-float-registers` feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F64R_HI: u32,
/// Floating-point status register, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F64S: u32,
/// Floating-point control register, available if the
/// `print-float-registers` feature is enabled.
#[cfg(feature = "print-float-registers")]
pub FCR: u32,
/// Floating-point status register, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub FSR: u32,
/// Floating-point register F0, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F0: u32,
/// Floating-point register F1, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F1: u32,
/// Floating-point register F2, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F2: u32,
/// Floating-point register F3, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F3: u32,
/// Floating-point register F4, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F4: u32,
/// Floating-point register F5, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F5: u32,
/// Floating-point register F6, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F6: u32,
/// Floating-point register F7, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F7: u32,
/// Floating-point register F8, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F8: u32,
/// Floating-point register F9, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F9: u32,
/// Floating-point register F10, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F10: u32,
/// Floating-point register F11, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F11: u32,
/// Floating-point register F12, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F12: u32,
/// Floating-point register F13, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F13: u32,
/// Floating-point register F14, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F14: u32,
/// Floating-point register F15, available if the `print-float-registers`
/// feature is enabled.
#[cfg(feature = "print-float-registers")]
pub F15: u32,
}
impl core::fmt::Debug for Context {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
fmt,
"Context
PC=0x{:08x} PS=0x{:08x}
A0=0x{:08x} A1=0x{:08x} A2=0x{:08x} A3=0x{:08x} A4=0x{:08x}
A5=0x{:08x} A6=0x{:08x} A7=0x{:08x} A8=0x{:08x} A9=0x{:08x}
A10=0x{:08x} A11=0x{:08x} A12=0x{:08x} A13=0x{:08x} A14=0x{:08x}
A15=0x{:08x}
SAR={:08x}
EXCCAUSE=0x{:08x} EXCVADDR=0x{:08x}
LBEG=0x{:08x} LEND=0x{:08x} LCOUNT=0x{:08x}
THREADPTR=0x{:08x}
SCOMPARE1=0x{:08x}
BR=0x{:08x}
ACCLO=0x{:08x} ACCHI=0x{:08x}
M0=0x{:08x} M1=0x{:08x} M2=0x{:08x} M3=0x{:08x}
",
self.PC,
self.PS,
self.A0,
self.A1,
self.A2,
self.A3,
self.A4,
self.A5,
self.A6,
self.A7,
self.A8,
self.A9,
self.A10,
self.A11,
self.A12,
self.A13,
self.A14,
self.A15,
self.SAR,
self.EXCCAUSE,
self.EXCVADDR,
self.LBEG,
self.LEND,
self.LCOUNT,
self.THREADPTR,
self.SCOMPARE1,
self.BR,
self.ACCLO,
self.ACCHI,
self.M0,
self.M1,
self.M2,
self.M3,
)?;
#[cfg(feature = "print-float-registers")]
write!(
fmt,
"F64R_LO=0x{:08x} F64R_HI=0x{:08x} F64S=0x{:08x}
FCR=0x{:08x} FSR=0x{:08x}
F0=0x{:08x} F1=0x{:08x} F2=0x{:08x} F3=0x{:08x} F4=0x{:08x}
F5=0x{:08x} F6=0x{:08x} F7=0x{:08x} F8=0x{:08x} F9=0x{:08x}
F10=0x{:08x} F11=0x{:08x} F12=0x{:08x} F13=0x{:08x} F14=0x{:08x}
F15=0x{:08x}",
self.F64R_LO,
self.F64R_HI,
self.F64S,
self.FCR,
self.FSR,
self.F0,
self.F1,
self.F2,
self.F3,
self.F4,
self.F5,
self.F6,
self.F7,
self.F8,
self.F9,
self.F10,
self.F11,
self.F12,
self.F13,
self.F14,
self.F15,
)?;
Ok(())
}
}
/// Get an array of backtrace addresses.
pub fn backtrace() -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let sp = unsafe {
let mut _tmp: u32;
asm!("mov {0}, a1", out(reg) _tmp);
_tmp
};
backtrace_internal(sp, 1)
}
pub(crate) fn sanitize_address(address: u32) -> u32 {
(address & 0x3fff_ffff) | 0x4000_0000
}
pub(crate) fn backtrace_internal(
sp: u32,
suppress: i32,
) -> [Option<usize>; MAX_BACKTRACE_ADDRESSES] {
let mut result = [None; 10];
let mut index = 0;
let mut fp = sp;
let mut suppress = suppress;
let mut old_address = 0;
loop {
unsafe {
let address = sanitize_address((fp as *const u32).offset(-4).read_volatile()); // RA/PC
fp = (fp as *const u32).offset(-3).read_volatile(); // next FP
if old_address == address {
break;
}
old_address = address;
// the address is 0 but we sanitized the address - then 0 becomes 0x40000000
if address == 0x40000000 {
break;
}
if !crate::is_valid_ram_address(fp) {
break;
}
if fp == 0 {
break;
}
if suppress == 0 {
result[index] = Some(address as usize);
index += 1;
if index >= MAX_BACKTRACE_ADDRESSES {
break;
}
} else {
suppress -= 1;
}
}
}
result
}

View File

@ -2,21 +2,23 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Add the `ulp-riscv-hal` package (#840)
### Fixed
### Changed
- Renamed to `esp-ulp-riscv-hal` (#916)
### Fixed
- Use `panic` instead of `process::exit` in esp-build (#2402 )
### Removed
[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-ulp-riscv-hal
## [0.1.0] - 2024-04-17
- Initial release
[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-build?since=2024-04-17

16
esp-build/Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "esp-build"
version = "0.1.0"
edition = "2021"
rust-version = "1.60.0"
description = "Build utilities for esp-hal"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.37"
syn = { version = "2.0.79", features = ["fold", "full"] }
termcolor = "1.4.1"

33
esp-build/README.md Normal file
View File

@ -0,0 +1,33 @@
# esp-build
[![Crates.io](https://img.shields.io/crates/v/esp-build?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-build)
[![docs.rs](https://img.shields.io/docsrs/esp-build?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-build)
![MSRV](https://img.shields.io/badge/MSRV-1.60-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-build?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
Build utilities for use with `esp-hal` and other related packages, intended for use in [build scripts]. This package is still quite minimal, but provides:
[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
## [Documentation](https://docs.rs/crate/esp-build)
## Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile on stable Rust 1.60 and up. It _might_
compile with older versions but that may change in any new patch release.
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.

229
esp-build/src/lib.rs Normal file
View File

@ -0,0 +1,229 @@
//! Build utilities for esp-hal.
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
use std::io::Write as _;
use proc_macro::TokenStream;
use quote::ToTokens;
use syn::{parse_macro_input, punctuated::Punctuated, LitStr, Token};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
/// Print a build error and terminate the process.
///
/// It should be noted that the error will be printed BEFORE the main function
/// is called, and as such this should NOT be thought analogous to `println!` or
/// similar utilities.
///
/// ## Example
///
/// ```rust
/// esp_build::error! {"
/// ERROR: something really bad has happened!
/// "}
/// // Process exits with exit code 1
/// ```
#[proc_macro]
pub fn error(input: TokenStream) -> TokenStream {
do_alert(Color::Red, input);
panic!("Build failed");
}
/// Print a build warning.
///
/// It should be noted that the warning will be printed BEFORE the main function
/// is called, and as such this should NOT be thought analogous to `println!` or
/// similar utilities.
///
/// ## Example
///
/// ```rust
/// esp_build::warning! {"
/// WARNING: something unpleasant has happened!
/// "};
/// ```
#[proc_macro]
pub fn warning(input: TokenStream) -> TokenStream {
do_alert(Color::Yellow, input)
}
/// Given some features, assert that **at most** one of the features is enabled.
///
/// ## Example
/// ```rust
/// assert_unique_features!("foo", "bar", "baz");
/// ```
#[proc_macro]
pub fn assert_unique_features(input: TokenStream) -> TokenStream {
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
.into_iter()
.collect::<Vec<_>>();
let unique = impl_unique_features(&features, "exactly zero or one");
quote::quote! {
#unique
}
.into()
}
/// Given some features, assert that **at least** one of the features is
/// enabled.
///
/// ## Example
/// ```rust
/// assert_used_features!("foo", "bar", "baz");
/// ```
#[proc_macro]
pub fn assert_used_features(input: TokenStream) -> TokenStream {
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
.into_iter()
.collect::<Vec<_>>();
let used = impl_used_features(&features, "at least one");
quote::quote! {
#used
}
.into()
}
/// Given some features, assert that **exactly** one of the features is enabled.
///
/// ## Example
/// ```rust
/// assert_unique_used_features!("foo", "bar", "baz");
/// ```
#[proc_macro]
pub fn assert_unique_used_features(input: TokenStream) -> TokenStream {
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
.into_iter()
.collect::<Vec<_>>();
let unique = impl_unique_features(&features, "exactly one");
let used = impl_used_features(&features, "exactly one");
quote::quote! {
#unique
#used
}
.into()
}
// ----------------------------------------------------------------------------
// Helper Functions
fn impl_unique_features(features: &[LitStr], expectation: &str) -> impl ToTokens {
let pairs = unique_pairs(features);
let unique_cfgs = pairs
.iter()
.map(|(a, b)| quote::quote! { all(feature = #a, feature = #b) });
let message = format!(
r#"
ERROR: expected {expectation} enabled feature from feature group:
{:?}
"#,
features.iter().map(|lit| lit.value()).collect::<Vec<_>>(),
);
quote::quote! {
#[cfg(any(#(#unique_cfgs),*))]
::esp_build::error! { #message }
}
}
fn impl_used_features(features: &[LitStr], expectation: &str) -> impl ToTokens {
let message = format!(
r#"
ERROR: expected {expectation} enabled feature from feature group:
{:?}
"#,
features.iter().map(|lit| lit.value()).collect::<Vec<_>>()
);
quote::quote! {
#[cfg(not(any(#(feature = #features),*)))]
::esp_build::error! { #message }
}
}
// Adapted from:
// https://github.com/dtolnay/build-alert/blob/49d060e/src/lib.rs#L54-L93
fn do_alert(color: Color, input: TokenStream) -> TokenStream {
let message = parse_macro_input!(input as LitStr).value();
let stderr = &mut StandardStream::stderr(ColorChoice::Auto);
let color_spec = ColorSpec::new().set_fg(Some(color)).clone();
let mut has_nonspace = false;
for mut line in message.lines() {
if !has_nonspace {
let (maybe_heading, rest) = split_heading(line);
if let Some(heading) = maybe_heading {
stderr.set_color(color_spec.clone().set_bold(true)).ok();
write!(stderr, "\n{}", heading).ok();
has_nonspace = true;
}
line = rest;
}
if line.is_empty() {
writeln!(stderr).ok();
} else {
stderr.set_color(&color_spec).ok();
writeln!(stderr, "{}", line).ok();
has_nonspace = has_nonspace || line.contains(|ch: char| ch != ' ');
}
}
stderr.reset().ok();
writeln!(stderr).ok();
TokenStream::new()
}
// Adapted from:
// https://github.com/dtolnay/build-alert/blob/49d060e/src/lib.rs#L95-L114
fn split_heading(s: &str) -> (Option<&str>, &str) {
let mut end = 0;
while end < s.len() && s[end..].starts_with(|ch: char| ch.is_ascii_uppercase()) {
end += 1;
}
if end >= 3 && (end == s.len() || s[end..].starts_with(':')) {
let (heading, rest) = s.split_at(end);
(Some(heading), rest)
} else {
(None, s)
}
}
fn unique_pairs(features: &[LitStr]) -> Vec<(&LitStr, &LitStr)> {
let mut pairs = Vec::new();
let mut i = 0;
let mut j = 0;
while i < features.len() {
let a = &features[i];
let b = &features[j];
if a.value() != b.value() {
pairs.push((a, b));
}
j += 1;
if j >= features.len() {
i += 1;
j = i;
}
}
pairs
}

32
esp-config/CHANGELOG.md Normal file
View File

@ -0,0 +1,32 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
### Fixed
- Users no longer have to manually import `esp_config_int_parse`. (#2630)
### Changed
- Crate prefixes and configuration keys are now separated by `_CONFIG_` (#2848)
### Removed
## 0.2.0 - 2024-11-20
### Added
- Add configuration validation (#2475)
## 0.1.0 - 2024-10-10
- Initial release
[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-config?since=2024-11-20

18
esp-config/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "esp-config"
version = "0.2.0"
edition = "2021"
rust-version = "1.79.0"
description = "Configure projects using esp-hal and related packages"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
[dependencies]
document-features = "0.2.10"
[dev-dependencies]
temp-env = "0.3.6"
[features]
## Enable the generation and parsing of a config
build = []

65
esp-config/README.md Normal file
View File

@ -0,0 +1,65 @@
# esp-config
[![Crates.io](https://img.shields.io/crates/v/esp-config?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-config)
[![docs.rs](https://img.shields.io/docsrs/esp-config?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-config)
![MSRV](https://img.shields.io/badge/MSRV-1.79-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-config?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
## [Documentation](https://docs.rs/crate/esp-config)
## Usage
`esp-config` takes a prefix (usually the crate name) and a set of configuration keys and default values to produce a configuration system that supports:
- Emitting rustc cfg's for boolean keys
- Emitting environment variables for numbers
- Along with decimal parsing, it supports Hex, Octal and Binary with the respective `0x`, `0o` and `0b` prefixes.
- Emitting environment variables string values
### Viewing the configuration
The possible configuration values are output as a markdown table in the crates `OUT_DIR` with the format `{prefix}_config_table.md`, this can then be included into the crates top level documentation. Here is an example of the output:
| Name | Description | Default value |
|------|-------------|---------------|
|**ESP_HAL_PLACE_SPI_DRIVER_IN_RAM**|Places the SPI driver in RAM for better performance|false|
### Setting configuration options
For any available configuration option, the environment variable or cfg is _always_ set based on the default value specified in the table. Users can override this by setting environment variables locally in their shell _or_ the preferred option is to utilize cargo's [`env` section](https://doc.rust-lang.org/cargo/reference/config.html#env).
It's important to note that due to a [bug in cargo](https://github.com/rust-lang/cargo/issues/10358), any modifications to the environment, local or otherwise will only get picked up on a full clean build of the project.
To see the final selected configuration another table is output to the `OUT_DIR` with the format `{prefix}_selected_config.md`.
### Capturing configuration values in the downstream crate
For all supported data types, there are helper macros that emit `const` code for parsing the configuration values.
- Numbers - `esp_config_int!(integer_type, "ENV")`
- Strings - `esp_config_str!("ENV")`
- Bool - `esp_config_bool!("ENV")`
In addition to environment variables, for boolean types rust `cfg`'s are emitted in snake case _without_ the prefix.
## Minimum Supported Rust Version (MSRV)
This crate is guaranteed to compile on stable Rust 1.79 and up. It _might_
compile with older versions but that may change in any new patch release.
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.

699
esp-config/src/generate.rs Normal file
View File

@ -0,0 +1,699 @@
use std::{
collections::HashMap,
env,
fmt::{self, Write as _},
fs,
ops::Range,
path::PathBuf,
};
const DOC_TABLE_HEADER: &str = r#"
| Name | Description | Default value |
|------|-------------|---------------|
"#;
const SELECTED_TABLE_HEADER: &str = r#"
| Name | Selected value |
|------|----------------|
"#;
/// Configuration errors.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
/// Parse errors.
Parse(String),
/// Validation errors.
Validation(String),
}
impl Error {
/// Convenience function for creating parse errors.
pub fn parse<S>(message: S) -> Self
where
S: Into<String>,
{
Self::Parse(message.into())
}
/// Convenience function for creating validation errors.
pub fn validation<S>(message: S) -> Self
where
S: Into<String>,
{
Self::Validation(message.into())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Parse(message) => write!(f, "{message}"),
Error::Validation(message) => write!(f, "{message}"),
}
}
}
/// Supported configuration value types.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Value {
/// Booleans.
Bool(bool),
/// Integers.
Integer(i128),
/// Strings.
String(String),
}
// TODO: Do we want to handle negative values for non-decimal values?
impl Value {
fn parse_in_place(&mut self, s: &str) -> Result<(), Error> {
*self = match self {
Value::Bool(_) => match s {
"true" => Value::Bool(true),
"false" => Value::Bool(false),
_ => {
return Err(Error::parse(format!(
"Expected 'true' or 'false', found: '{s}'"
)))
}
},
Value::Integer(_) => {
let inner = match s.as_bytes() {
[b'0', b'x', ..] => i128::from_str_radix(&s[2..], 16),
[b'0', b'o', ..] => i128::from_str_radix(&s[2..], 8),
[b'0', b'b', ..] => i128::from_str_radix(&s[2..], 2),
_ => i128::from_str_radix(&s, 10),
}
.map_err(|_| Error::parse(format!("Expected valid intger value, found: '{s}'")))?;
Value::Integer(inner)
}
Value::String(_) => Value::String(s.into()),
};
Ok(())
}
/// Convert the value to a [bool].
pub fn as_bool(&self) -> bool {
match self {
Value::Bool(value) => *value,
_ => panic!("attempted to convert non-bool value to a bool"),
}
}
/// Convert the value to an [i128].
pub fn as_integer(&self) -> i128 {
match self {
Value::Integer(value) => *value,
_ => panic!("attempted to convert non-integer value to an integer"),
}
}
/// Convert the value to a [String].
pub fn as_string(&self) -> String {
match self {
Value::String(value) => value.to_owned(),
_ => panic!("attempted to convert non-string value to a string"),
}
}
/// Is the value a bool?
pub fn is_bool(&self) -> bool {
matches!(self, Value::Bool(_))
}
/// Is the value an integer?
pub fn is_integer(&self) -> bool {
matches!(self, Value::Integer(_))
}
/// Is the value a string?
pub fn is_string(&self) -> bool {
matches!(self, Value::String(_))
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Bool(b) => write!(f, "{b}"),
Value::Integer(i) => write!(f, "{i}"),
Value::String(s) => write!(f, "{s}"),
}
}
}
/// Configuration value validation functions.
pub enum Validator {
/// Only allow negative integers, i.e. any values less than 0.
NegativeInteger,
/// Only allow non-negative integers, i.e. any values greater than or equal
/// to 0.
NonNegativeInteger,
/// Only allow positive integers, i.e. any values greater than to 0.
PositiveInteger,
/// Ensure that an integer value falls within the specified range.
IntegerInRange(Range<i128>),
/// A custom validation function to run against any supported value type.
Custom(Box<dyn Fn(&Value) -> Result<(), Error>>),
}
impl Validator {
fn validate(&self, value: &Value) -> Result<(), Error> {
match self {
Validator::NegativeInteger => negative_integer(value)?,
Validator::NonNegativeInteger => non_negative_integer(value)?,
Validator::PositiveInteger => positive_integer(value)?,
Validator::IntegerInRange(range) => integer_in_range(range, value)?,
Validator::Custom(validator_fn) => validator_fn(value)?,
}
Ok(())
}
}
fn negative_integer(value: &Value) -> Result<(), Error> {
if !value.is_integer() {
return Err(Error::validation(
"Validator::NegativeInteger can only be used with integer values",
));
} else if value.as_integer() >= 0 {
return Err(Error::validation(format!(
"Expected negative integer, found '{}'",
value.as_integer()
)));
}
Ok(())
}
fn non_negative_integer(value: &Value) -> Result<(), Error> {
if !value.is_integer() {
return Err(Error::validation(
"Validator::NonNegativeInteger can only be used with integer values",
));
} else if value.as_integer() < 0 {
return Err(Error::validation(format!(
"Expected non-negative integer, found '{}'",
value.as_integer()
)));
}
Ok(())
}
fn positive_integer(value: &Value) -> Result<(), Error> {
if !value.is_integer() {
return Err(Error::validation(
"Validator::PositiveInteger can only be used with integer values",
));
} else if value.as_integer() <= 0 {
return Err(Error::validation(format!(
"Expected positive integer, found '{}'",
value.as_integer()
)));
}
Ok(())
}
fn integer_in_range(range: &Range<i128>, value: &Value) -> Result<(), Error> {
if !value.is_integer() || !range.contains(&value.as_integer()) {
Err(Error::validation(format!(
"Value '{}' does not fall within range '{:?}'",
value, range
)))
} else {
Ok(())
}
}
/// Generate and parse config from a prefix, and an array tuples containing the
/// name, description, default value, and an optional validator.
///
/// This function will parse any `SCREAMING_SNAKE_CASE` environment variables
/// that match the given prefix. It will then attempt to parse the [`Value`] and
/// run any validators which have been specified.
///
/// Once the config has been parsed, this function will emit `snake_case` cfg's
/// _without_ the prefix which can be used in the dependant crate. After that,
/// it will create a markdown table in the `OUT_DIR` under the name
/// `{prefix}_config_table.md` where prefix has also been converted to
/// `snake_case`. This can be included in crate documentation to outline the
/// available configuration options for the crate.
///
/// Passing a value of true for the `emit_md_tables` argument will create and
/// write markdown files of the available configuration and selected
/// configuration which can be included in documentation.
///
/// Unknown keys with the supplied prefix will cause this function to panic.
pub fn generate_config(
crate_name: &str,
config: &[(&str, &str, Value, Option<Validator>)],
emit_md_tables: bool,
) -> HashMap<String, Value> {
// Only rebuild if `build.rs` changed. Otherwise, Cargo will rebuild if any
// other file changed.
println!("cargo:rerun-if-changed=build.rs");
#[cfg(not(test))]
env_change_work_around();
let mut doc_table = String::from(DOC_TABLE_HEADER);
let mut selected_config = String::from(SELECTED_TABLE_HEADER);
// Ensure that the prefix is `SCREAMING_SNAKE_CASE`:
let prefix = format!("{}_CONFIG_", screaming_snake_case(crate_name));
// Build a lookup table for any provided validators; we must prefix the
// name of the config and transform it to SCREAMING_SNAKE_CASE so that
// it matches the keys in the hash table produced by `create_config`.
let config_validators = config
.iter()
.flat_map(|(name, _description, _default, validator)| {
if let Some(validator) = validator {
let name = format!("{prefix}{}", screaming_snake_case(name));
Some((name, validator))
} else {
None
}
})
.collect::<HashMap<_, _>>();
let mut configs = create_config(&prefix, config, &mut doc_table);
capture_from_env(&prefix, &mut configs);
for (name, value) in configs.iter() {
if let Some(validator) = config_validators.get(name) {
validator.validate(value).unwrap();
}
}
emit_configuration(&prefix, &configs, &mut selected_config);
if emit_md_tables {
let file_name = snake_case(crate_name);
write_config_tables(&file_name, doc_table, selected_config);
}
configs
}
// A work-around for https://github.com/rust-lang/cargo/issues/10358
// This can be removed when https://github.com/rust-lang/cargo/pull/14058 is merged.
// Unlikely to work on projects in workspaces
#[cfg(not(test))]
fn env_change_work_around() {
let mut out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
// We clean out_dir by removing all trailing directories, until it ends with
// target
while !out_dir.ends_with("target") {
if !out_dir.pop() {
return; // We ran out of directories...
}
}
out_dir.pop();
let dotcargo = out_dir.join(".cargo/");
if dotcargo.exists() {
if dotcargo.join("config.toml").exists() {
println!(
"cargo:rerun-if-changed={}",
dotcargo.join("config.toml").display()
);
}
if dotcargo.join("config").exists() {
println!(
"cargo:rerun-if-changed={}",
dotcargo.join("config").display()
);
}
}
}
fn create_config(
prefix: &str,
config: &[(&str, &str, Value, Option<Validator>)],
doc_table: &mut String,
) -> HashMap<String, Value> {
let mut configs = HashMap::new();
for (name, description, default, _validator) in config {
let name = format!("{prefix}{}", screaming_snake_case(name));
configs.insert(name.clone(), default.clone());
// Write documentation table line:
let default = default.to_string();
writeln!(doc_table, "|**{name}**|{description}|{default}|").unwrap();
// Rebuild if config environment variable changed:
println!("cargo:rerun-if-env-changed={name}");
}
configs
}
fn capture_from_env(prefix: &str, configs: &mut HashMap<String, Value>) {
let mut unknown = Vec::new();
let mut failed = Vec::new();
// Try and capture input from the environment:
for (var, value) in env::vars() {
if var.starts_with(prefix) {
let Some(cfg) = configs.get_mut(&var) else {
unknown.push(var);
continue;
};
if let Err(e) = cfg.parse_in_place(&value) {
failed.push(format!("{var}: {e}"));
}
}
}
if !failed.is_empty() {
panic!("Invalid configuration options detected: {:?}", failed);
}
if !unknown.is_empty() {
panic!("Unknown configuration options detected: {:?}", unknown);
}
}
fn emit_configuration(
prefix: &str,
configs: &HashMap<String, Value>,
selected_config: &mut String,
) {
for (name, value) in configs.iter() {
let cfg_name = snake_case(name.trim_start_matches(prefix));
println!("cargo:rustc-check-cfg=cfg({cfg_name})");
if let Value::Bool(true) = value {
println!("cargo:rustc-cfg={cfg_name}");
}
let value = value.to_string();
// Values that haven't been seen will be output here with the default value:
println!("cargo:rustc-env={}={}", name, value);
writeln!(selected_config, "|**{name}**|{value}|").unwrap();
}
}
fn write_config_tables(prefix: &str, doc_table: String, selected_config: String) {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir
.join(format!("{prefix}_config_table.md"))
.display()
.to_string();
fs::write(out_file, doc_table).unwrap();
let out_file = out_dir
.join(format!("{prefix}_selected_config.md"))
.display()
.to_string();
fs::write(out_file, selected_config).unwrap();
}
fn snake_case(name: &str) -> String {
let mut name = name.replace("-", "_");
name.make_ascii_lowercase();
name
}
fn screaming_snake_case(name: &str) -> String {
let mut name = name.replace("-", "_");
name.make_ascii_uppercase();
name
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn value_number_formats() {
const INPUTS: &[&str] = &["0xAA", "0o252", "0b0000000010101010", "170"];
let mut v = Value::Integer(0);
for input in INPUTS {
v.parse_in_place(input).unwrap();
// no matter the input format, the output format should be decimal
assert_eq!(format!("{v}"), "170");
}
}
#[test]
fn value_bool_inputs() {
let mut v = Value::Bool(false);
v.parse_in_place("true").unwrap();
assert_eq!(format!("{v}"), "true");
v.parse_in_place("false").unwrap();
assert_eq!(format!("{v}"), "false");
}
#[test]
fn env_override() {
temp_env::with_vars(
[
("ESP_TEST_CONFIG_NUMBER", Some("0xaa")),
("ESP_TEST_CONFIG_NUMBER_SIGNED", Some("-999")),
("ESP_TEST_CONFIG_STRING", Some("Hello world!")),
("ESP_TEST_CONFIG_BOOL", Some("true")),
],
|| {
let configs = generate_config(
"esp-test",
&[
("number", "NA", Value::Integer(999), None),
("number_signed", "NA", Value::Integer(-777), None),
("string", "NA", Value::String("Demo".to_owned()), None),
("bool", "NA", Value::Bool(false), None),
("number_default", "NA", Value::Integer(999), None),
(
"string_default",
"NA",
Value::String("Demo".to_owned()),
None,
),
("bool_default", "NA", Value::Bool(false), None),
],
false,
);
// some values have changed
assert_eq!(
match configs.get("ESP_TEST_CONFIG_NUMBER").unwrap() {
Value::Integer(num) => *num,
_ => unreachable!(),
},
0xaa
);
assert_eq!(
match configs.get("ESP_TEST_CONFIG_NUMBER_SIGNED").unwrap() {
Value::Integer(num) => *num,
_ => unreachable!(),
},
-999
);
assert_eq!(
match configs.get("ESP_TEST_CONFIG_STRING").unwrap() {
Value::String(val) => val,
_ => unreachable!(),
},
"Hello world!"
);
assert_eq!(
match configs.get("ESP_TEST_CONFIG_BOOL").unwrap() {
Value::Bool(val) => *val,
_ => unreachable!(),
},
true
);
// the rest are the defaults
assert_eq!(
match configs.get("ESP_TEST_CONFIG_NUMBER_DEFAULT").unwrap() {
Value::Integer(num) => *num,
_ => unreachable!(),
},
999
);
assert_eq!(
match configs.get("ESP_TEST_CONFIG_STRING_DEFAULT").unwrap() {
Value::String(val) => val,
_ => unreachable!(),
},
"Demo"
);
assert_eq!(
match configs.get("ESP_TEST_CONFIG_BOOL_DEFAULT").unwrap() {
Value::Bool(val) => *val,
_ => unreachable!(),
},
false
);
},
)
}
#[test]
fn builtin_validation_passes() {
temp_env::with_vars(
[
("ESP_TEST_CONFIG_POSITIVE_NUMBER", Some("7")),
("ESP_TEST_CONFIG_NEGATIVE_NUMBER", Some("-1")),
("ESP_TEST_CONFIG_NON_NEGATIVE_NUMBER", Some("0")),
("ESP_TEST_CONFIG_RANGE", Some("9")),
],
|| {
generate_config(
"esp-test",
&[
(
"positive_number",
"NA",
Value::Integer(-1),
Some(Validator::PositiveInteger),
),
(
"negative_number",
"NA",
Value::Integer(1),
Some(Validator::NegativeInteger),
),
(
"non_negative_number",
"NA",
Value::Integer(-1),
Some(Validator::NonNegativeInteger),
),
(
"range",
"NA",
Value::Integer(0),
Some(Validator::IntegerInRange(5..10)),
),
],
false,
)
},
);
}
#[test]
fn custom_validation_passes() {
temp_env::with_vars([("ESP_TEST_CONFIG_NUMBER", Some("13"))], || {
generate_config(
"esp-test",
&[(
"number",
"NA",
Value::Integer(-1),
Some(Validator::Custom(Box::new(|value| {
let range = 10..20;
if !value.is_integer() || !range.contains(&value.as_integer()) {
Err(Error::validation("value does not fall within range"))
} else {
Ok(())
}
}))),
)],
false,
)
});
}
#[test]
#[should_panic]
fn builtin_validation_bails() {
temp_env::with_vars([("ESP_TEST_CONFIG_POSITIVE_NUMBER", Some("-99"))], || {
generate_config(
"esp-test",
&[(
"positive_number",
"NA",
Value::Integer(-1),
Some(Validator::PositiveInteger),
)],
false,
)
});
}
#[test]
#[should_panic]
fn custom_validation_bails() {
temp_env::with_vars([("ESP_TEST_CONFIG_NUMBER", Some("37"))], || {
generate_config(
"esp-test",
&[(
"number",
"NA",
Value::Integer(-1),
Some(Validator::Custom(Box::new(|value| {
let range = 10..20;
if !value.is_integer() || !range.contains(&value.as_integer()) {
Err(Error::validation("value does not fall within range"))
} else {
Ok(())
}
}))),
)],
false,
)
});
}
#[test]
#[should_panic]
fn env_unknown_bails() {
temp_env::with_vars(
[
("ESP_TEST_CONFIG_NUMBER", Some("0xaa")),
("ESP_TEST_CONFIG_RANDOM_VARIABLE", Some("")),
],
|| {
generate_config(
"esp-test",
&[("number", "NA", Value::Integer(999), None)],
false,
);
},
);
}
#[test]
#[should_panic]
fn env_invalid_values_bails() {
temp_env::with_vars([("ESP_TEST_CONFIG_NUMBER", Some("Hello world"))], || {
generate_config(
"esp-test",
&[("number", "NA", Value::Integer(999), None)],
false,
);
});
}
#[test]
fn env_unknown_prefix_is_ignored() {
temp_env::with_vars(
[("ESP_TEST_OTHER_CONFIG_NUMBER", Some("Hello world"))],
|| {
generate_config(
"esp-test",
&[("number", "NA", Value::Integer(999), None)],
false,
);
},
);
}
}

110
esp-config/src/lib.rs Normal file
View File

@ -0,0 +1,110 @@
#![doc = include_str!("../README.md")]
//! ## Feature Flags
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
#![cfg_attr(not(feature = "build"), no_std)]
#![deny(missing_docs, rust_2018_idioms)]
#[cfg(feature = "build")]
mod generate;
#[cfg(feature = "build")]
pub use generate::{generate_config, Error, Validator, Value};
/// Parse the value of an environment variable as a [bool] at compile time.
#[macro_export]
macro_rules! esp_config_bool {
( $var:expr ) => {
match env!($var).as_bytes() {
b"true" => true,
b"false" => false,
_ => ::core::panic!("boolean value must be either 'true' or 'false'"),
}
};
}
// TODO: From 1.82 on, we can use `<$ty>::from_str_radix(env!($var), 10)`
/// Parse the value of an environment variable as an integer at compile time.
#[macro_export]
macro_rules! esp_config_int {
( $ty:ty, $var:expr ) => {
const {
const BYTES: &[u8] = env!($var).as_bytes();
$crate::esp_config_int_parse!($ty, BYTES)
}
};
}
/// Get the string value of an environment variable at compile time.
#[macro_export]
macro_rules! esp_config_str {
( $var:expr ) => {
env!($var)
};
}
/// Parse a string like "777" into an integer, which _can_ be used in a `const`
/// context
#[doc(hidden)] // To avoid confusion with `esp_config_int`, hide this in the docs
#[macro_export]
macro_rules! esp_config_int_parse {
( $ty:ty, $bytes:expr ) => {{
let mut bytes = $bytes;
let mut val: $ty = 0;
let mut sign_seen = false;
let mut is_negative = false;
while let [byte, rest @ ..] = bytes {
match *byte {
b'0'..=b'9' => {
val = val * 10 + (*byte - b'0') as $ty;
}
b'-' | b'+' if !sign_seen => {
is_negative = *byte == b'-';
sign_seen = true;
}
_ => ::core::panic!("invalid character encountered while parsing integer"),
}
bytes = rest;
}
if is_negative {
let original = val;
// Subtract the value twice to get a negative:
val -= original;
val -= original;
}
val
}};
}
#[cfg(test)]
mod test {
// We can only test success in the const context
const _: () = {
core::assert!(esp_config_int_parse!(i64, "-77777".as_bytes()) == -77777);
core::assert!(esp_config_int_parse!(isize, "-7777".as_bytes()) == -7777);
core::assert!(esp_config_int_parse!(i32, "-999".as_bytes()) == -999);
core::assert!(esp_config_int_parse!(i16, "-99".as_bytes()) == -99);
core::assert!(esp_config_int_parse!(i8, "-9".as_bytes()) == -9);
core::assert!(esp_config_int_parse!(u64, "77777".as_bytes()) == 77777);
core::assert!(esp_config_int_parse!(usize, "7777".as_bytes()) == 7777);
core::assert!(esp_config_int_parse!(u32, "999".as_bytes()) == 999);
core::assert!(esp_config_int_parse!(u16, "99".as_bytes()) == 99);
core::assert!(esp_config_int_parse!(u8, "9".as_bytes()) == 9);
};
#[test]
#[should_panic]
fn test_expect_positive() {
esp_config_int_parse!(u8, "-5".as_bytes());
}
#[test]
#[should_panic]
fn test_invalid_digit() {
esp_config_int_parse!(u32, "a".as_bytes());
}
}

View File

@ -1,182 +0,0 @@
[package]
name = "esp-hal-common"
version = "0.14.1"
edition = "2021"
rust-version = "1.67.0"
description = "HAL implementations for peripherals common among Espressif devices; should not be used directly"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"
# Prevent multiple copies of this crate in the same binary.
# Needed because different copies might get different features, causing
# confusing build errors due to expected features not getting enabled
# on the unintentional copy.
# This is especially common when mixing crates from crates.io and git.
links = "esp-hal-common"
[dependencies]
bitflags = "2.4.1"
bitfield = "0.14.0"
cfg-if = "1.0.0"
critical-section = "1.1.2"
defmt = { version = "=0.3.5", optional = true }
embedded-can = { version = "0.4.1", optional = true }
embedded-dma = "0.2.0"
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-hal-1 = { version = "=1.0.0-rc.2", optional = true, package = "embedded-hal" }
embedded-hal-nb = { version = "=1.0.0-rc.2", optional = true }
embedded-io = { version = "0.6.1", optional = true }
enumset = "1.1.3"
esp-synopsys-usb-otg = { version = "0.4.0", optional = true, features = ["fs", "esp32sx"] }
fugit = "0.3.7"
heapless = "0.8.0"
log = { version = "0.4.20", optional = true }
nb = "1.1.0"
paste = "1.0.14"
portable-atomic = { version = "1.6.0", default-features = false }
procmacros = { version = "0.8.0", features = ["enum-dispatch", "ram"], package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
strum = { version = "0.25.0", default-features = false, features = ["derive"] }
void = { version = "1.0.2", default-features = false }
usb-device = { version = "0.3.1", optional = true }
# async
embedded-hal-async = { version = "=1.0.0-rc.2", optional = true }
embedded-io-async = { version = "0.6.1", optional = true }
embassy-executor = { version = "0.4.0", optional = true }
embassy-futures = { version = "0.1.1", optional = true }
embassy-sync = { version = "0.5.0", optional = true }
embassy-time = { version = "0.2.0", optional = true }
# RISC-V
esp-riscv-rt = { version = "0.6.0", optional = true, path = "../esp-riscv-rt" }
# Xtensa
xtensa-lx = { version = "0.8.0", optional = true }
xtensa-lx-rt = { version = "0.16.0", optional = true }
# Part of `ufmt` containing only `uWrite` trait
ufmt-write = { version = "0.1.0", optional = true }
# IMPORTANT:
# Each supported device MUST have its PAC included below along with a
# corresponding feature.
esp32 = { version = "0.28.0", features = ["critical-section"], optional = true }
esp32c2 = { version = "0.17.0", features = ["critical-section"], optional = true }
esp32c3 = { version = "0.20.0", features = ["critical-section"], optional = true }
esp32c6 = { version = "0.11.0", features = ["critical-section"], optional = true }
esp32h2 = { version = "0.7.0", features = ["critical-section"], optional = true }
esp32s2 = { version = "0.19.0", features = ["critical-section"], optional = true }
esp32s3 = { version = "0.23.0", features = ["critical-section"], optional = true }
[build-dependencies]
basic-toml = "0.1.7"
serde = { version = "1.0.193", features = ["derive"] }
[features]
esp32 = ["xtensa", "esp32/rt", "procmacros/esp32", "xtensa-lx/esp32", "xtensa-lx-rt/esp32"]
esp32c2 = ["riscv", "esp32c2/rt", "procmacros/esp32c2", "portable-atomic/unsafe-assume-single-core"]
esp32c3 = ["riscv", "esp32c3/rt", "procmacros/esp32c3", "portable-atomic/unsafe-assume-single-core"]
esp32c6 = ["riscv", "esp32c6/rt", "procmacros/esp32c6"]
esp32h2 = ["riscv", "esp32h2/rt", "procmacros/esp32h2"]
esp32s2 = ["xtensa", "esp32s2/rt", "procmacros/esp32s2", "xtensa-lx/esp32s2", "xtensa-lx-rt/esp32s2", "usb-otg", "portable-atomic/critical-section"]
esp32s3 = ["xtensa", "esp32s3/rt", "procmacros/esp32s3", "xtensa-lx/esp32s3", "xtensa-lx-rt/esp32s3", "usb-otg"]
# Crystal frequency selection (ESP32 and ESP32-C2 only!)
xtal-26mhz = []
xtal-40mhz = []
# Only certain chips support flip-link (ESP32-C6 and ESPS32-H2)
flip-link = ["esp-riscv-rt/fix-sp"]
# PSRAM support
psram-2m = []
psram-4m = []
psram-8m = []
# Octal RAM support
opsram-2m = []
opsram-4m = []
opsram-8m = []
opsram-16m = []
# USB OTG support (ESP32-S2 and ESP32-S3 only! Enabled by default)
usb-otg = ["esp-synopsys-usb-otg", "usb-device"]
# Interrupt-related feature:
# - Use direct interrupt vectoring (RISC-V only!)
# - Use interrupt preemption (RISC-V only!)
# - Use vectored interrupts (calling the handlers defined in the PAC)
direct-vectoring = ["esp-riscv-rt/direct-vectoring"]
interrupt-preemption = ["esp-riscv-rt/interrupt-preemption"]
vectored = ["procmacros/interrupt"]
# Enable logging
log = ["dep:log"]
# Trait implementation features:
# - Implement the `embedded-hal@1.0.0-rc.x` traits (and friends)
# - Implement the `embedded-io` traits where able
# - Implement the `ufmt_write::Write` trait where able
eh1 = ["embedded-hal-1", "embedded-hal-nb", "embedded-can"]
embedded-io = ["dep:embedded-io"]
ufmt = ["ufmt-write"]
# Support for asynchronous operation, implementing traits from
# `embedded-hal-async` and `embedded-io-async`
async = [
"embedded-hal-async",
"eh1",
"embassy-sync",
"embassy-futures",
"embedded-io",
"embedded-io-async",
]
# Embassy support
embassy = ["embassy-time", "procmacros/embassy"]
embassy-executor-interrupt = ["embassy", "embassy-executor"]
embassy-executor-thread = ["embassy", "embassy-executor"]
embassy-time-systick = []
embassy-time-timg0 = []
# Prefer integrated timers, but allow using the generic queue if needed
embassy-integrated-timers = ["embassy-executor?/integrated-timers"]
embassy-generic-queue-8 = ["embassy-time/generic-queue-8"]
embassy-generic-queue-16 = ["embassy-time/generic-queue-16"]
embassy-generic-queue-32 = ["embassy-time/generic-queue-32"]
embassy-generic-queue-64 = ["embassy-time/generic-queue-64"]
embassy-generic-queue-128 = ["embassy-time/generic-queue-128"]
# Architecture-specific features (intended for internal use)
riscv = ["critical-section/restore-state-u8", "esp-riscv-rt", "esp-riscv-rt/zero-bss"]
xtensa = ["critical-section/restore-state-u32"]
# Initialize / clear data sections and RTC memory
rv-init-data = ["esp-riscv-rt/init-data", "esp-riscv-rt/init-rw-text"]
rv-zero-rtc-bss = ["esp-riscv-rt/zero-rtc-fast-bss"]
rv-init-rtc-data = ["esp-riscv-rt/init-rtc-fast-data", "esp-riscv-rt/init-rtc-fast-text"]
# Enable the `impl-register-debug` feature for the selected PAC
debug = [
"esp32?/impl-register-debug",
"esp32c2?/impl-register-debug",
"esp32c3?/impl-register-debug",
"esp32c6?/impl-register-debug",
"esp32h2?/impl-register-debug",
"esp32s2?/impl-register-debug",
"esp32s3?/impl-register-debug",
]
# Enable support for `defmt`, for `esp-hal-common` and also for all our dependencies
defmt = [
"dep:defmt",
"embassy-executor?/defmt",
"embassy-futures?/defmt",
"embassy-sync?/defmt",
"embassy-time?/defmt",
"embedded-hal-1?/defmt-03",
"embedded-io/defmt-03",
"embedded-io-async?/defmt-03",
]

View File

@ -1,37 +0,0 @@
# esp-hal-common
[![Crates.io](https://img.shields.io/crates/v/esp-hal-common?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-hal-common)
[![docs.rs](https://img.shields.io/docsrs/esp-hal-common?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-hal-common)
![Crates.io](https://img.shields.io/crates/l/esp-hal-common?labelColor=1C2C2E&style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)
`no_std` HAL implementations for the peripherals which are common among Espressif devices. Implements a number of the traits defined by [embedded-hal](https://github.com/rust-embedded/embedded-hal).
This crate should not be used directly; you should use one of the device-specific HAL crates instead:
- [esp32-hal](../esp32-hal/README.md)
- [esp32c2-hal](../esp32c2-hal/README.md)
- [esp32c3-hal](../esp32c3-hal/README.md)
- [esp32c6-hal](../esp32c6-hal/README.md)
- [esp32h2-hal](../esp32h2-hal/README.md)
- [esp32s2-hal](../esp32s2-hal/README.md)
- [esp32s3-hal](../esp32s3-hal/README.md)
## [Documentation]
[documentation]: https://docs.rs/esp-hal-common/
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.

View File

@ -1,416 +0,0 @@
use std::{
env,
error::Error,
fs::{self, File},
io::{BufRead, BufReader, Write},
path::{Path, PathBuf},
};
use serde::Deserialize;
// Macros taken from:
// https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110
// Given some features, assert that AT MOST one of the features is enabled.
macro_rules! assert_unique_features {
() => {};
( $first:tt $(,$rest:tt)* ) => {
$(
#[cfg(all(feature = $first, feature = $rest))]
compile_error!(concat!("Features \"", $first, "\" and \"", $rest, "\" cannot be used together"));
)*
assert_unique_features!($($rest),*);
};
}
// Given some features, assert that AT LEAST one of the features is enabled.
macro_rules! assert_used_features {
( $all:tt ) => {
#[cfg(not(feature = $all))]
compile_error!(concat!("The feature flag must be provided: ", $all));
};
( $($all:tt),+ ) => {
#[cfg(not(any($(feature = $all),*)))]
compile_error!(concat!("One of the feature flags must be provided: ", $($all, ", "),*));
};
}
// Given some features, assert that EXACTLY one of the features is enabled.
macro_rules! assert_unique_used_features {
( $($all:tt),* ) => {
assert_unique_features!($($all),*);
assert_used_features!($($all),*);
}
}
#[derive(Debug, Deserialize)]
enum Arch {
#[serde(rename = "riscv")]
RiscV,
#[serde(rename = "xtensa")]
Xtensa,
}
impl std::fmt::Display for Arch {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Arch::RiscV => "riscv",
Arch::Xtensa => "xtensa",
}
)
}
}
#[derive(Debug, Deserialize)]
enum CoreCount {
#[serde(rename = "single_core")]
Single,
#[serde(rename = "multi_core")]
Multi,
}
impl std::fmt::Display for CoreCount {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match self {
CoreCount::Single => "single_core",
CoreCount::Multi => "multi_core",
}
)
}
}
#[derive(Debug, Deserialize)]
struct Device {
pub arch: Arch,
pub cores: CoreCount,
pub peripherals: Vec<String>,
pub symbols: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct Config {
pub device: Device,
}
fn main() -> Result<(), Box<dyn Error>> {
// NOTE: update when adding new device support!
// Ensure that exactly one chip has been specified:
assert_unique_used_features!(
"esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s2", "esp32s3"
);
// Handle the features for the ESP32's and ESP32-C2's different crystal
// frequencies:
#[cfg(any(feature = "esp32", feature = "esp32c2"))]
{
assert_unique_used_features!("xtal-26mhz", "xtal-40mhz");
}
// If the `embassy` feature is enabled, ensure that a time driver implementation
// is available:
#[cfg(feature = "embassy")]
{
#[cfg(feature = "esp32")]
assert_unique_used_features!("embassy-time-timg0");
#[cfg(not(feature = "esp32"))]
assert_unique_used_features!("embassy-time-systick", "embassy-time-timg0");
}
#[cfg(feature = "flip-link")]
{
#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
panic!("flip-link is only available on ESP32-C6/ESP32-H2");
}
// NOTE: update when adding new device support!
// Determine the name of the configured device:
let device_name = if cfg!(feature = "esp32") {
"esp32"
} else if cfg!(feature = "esp32c2") {
"esp32c2"
} else if cfg!(feature = "esp32c3") {
"esp32c3"
} else if cfg!(feature = "esp32c6") {
"esp32c6"
} else if cfg!(feature = "esp32h2") {
"esp32h2"
} else if cfg!(feature = "esp32s2") {
"esp32s2"
} else if cfg!(feature = "esp32s3") {
"esp32s3"
} else {
unreachable!() // We've confirmed exactly one known device was selected
};
if detect_atomic_extension("a") || detect_atomic_extension("s32c1i") {
panic!(
"Atomic emulation flags detected in `.cargo/config.toml`, this is no longer supported!"
);
}
// Load the configuration file for the configured device:
let chip_toml_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("devices")
.join(device_name)
.join("device.toml")
.canonicalize()?;
let config = fs::read_to_string(chip_toml_path)?;
let config: Config = basic_toml::from_str(&config)?;
let device = &config.device;
// Check PSRAM features are only given if the target supports PSRAM:
if !&device.symbols.contains(&String::from("psram"))
&& (cfg!(feature = "psram-2m") || cfg!(feature = "psram-4m") || cfg!(feature = "psram-8m"))
{
panic!("The target does not support PSRAM");
}
// Define all necessary configuration symbols for the configured device:
println!("cargo:rustc-cfg={}", device_name);
println!("cargo:rustc-cfg={}", device.arch);
println!("cargo:rustc-cfg={}", device.cores);
for peripheral in &device.peripherals {
println!("cargo:rustc-cfg={peripheral}");
}
for symbol in &device.symbols {
println!("cargo:rustc-cfg={symbol}");
}
let mut config_symbols = Vec::new();
let arch = device.arch.to_string();
let cores = device.cores.to_string();
config_symbols.push(device_name);
config_symbols.push(&arch);
config_symbols.push(&cores);
for peripheral in &device.peripherals {
config_symbols.push(peripheral);
}
for symbol in &device.symbols {
config_symbols.push(symbol);
}
#[cfg(feature = "flip-link")]
config_symbols.push("flip-link");
// Place all linker scripts in `OUT_DIR`, and instruct Cargo how to find these
// files:
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());
if cfg!(feature = "esp32") || cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") {
fs::copy("ld/xtensa/hal-defaults.x", out.join("hal-defaults.x"))?;
let (irtc, drtc) = if cfg!(feature = "esp32s3") {
("rtc_fast_seg", "rtc_fast_seg")
} else {
("rtc_fast_iram_seg", "rtc_fast_dram_seg")
};
let alias = format!(
r#"
REGION_ALIAS("ROTEXT", irom_seg);
REGION_ALIAS("RWTEXT", iram_seg);
REGION_ALIAS("RODATA", drom_seg);
REGION_ALIAS("RWDATA", dram_seg);
REGION_ALIAS("RTC_FAST_RWTEXT", {});
REGION_ALIAS("RTC_FAST_RWDATA", {});
"#,
irtc, drtc
);
fs::write(out.join("alias.x"), alias)?;
} else {
preprocess_file(
&config_symbols,
"ld/riscv/hal-defaults.x",
out.join("hal-defaults.x"),
)?;
preprocess_file(&config_symbols, "ld/riscv/asserts.x", out.join("asserts.x"))?;
preprocess_file(&config_symbols, "ld/riscv/debug.x", out.join("debug.x"))?;
}
copy_dir_all(&config_symbols, "ld/sections", &out)?;
copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?;
// Generate the eFuse table from the selected device's CSV file:
gen_efuse_table(device_name, out)?;
Ok(())
}
fn copy_dir_all(
config_symbols: &Vec<&str>,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
) -> std::io::Result<()> {
fs::create_dir_all(&dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
if ty.is_dir() {
copy_dir_all(
config_symbols,
entry.path(),
dst.as_ref().join(entry.file_name()),
)?;
} else {
preprocess_file(
config_symbols,
entry.path(),
dst.as_ref().join(entry.file_name()),
)?;
}
}
Ok(())
}
/// A naive pre-processor for linker scripts
fn preprocess_file(
config: &Vec<&str>,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
) -> std::io::Result<()> {
let file = File::open(src)?;
let mut out_file = File::create(dst)?;
let mut take = Vec::new();
take.push(true);
for line in std::io::BufReader::new(file).lines() {
let line = line?;
println!("{} >> {}", *take.last().unwrap(), line);
let trimmed = line.trim();
if trimmed.starts_with("#IF ") {
let condition = &trimmed[4..];
let should_take = take.iter().all(|v| *v == true);
let should_take = should_take && config.contains(&condition);
take.push(should_take);
continue;
} else if trimmed == "#ELSE" {
let taken = take.pop().unwrap();
let should_take = take.iter().all(|v| *v == true);
let should_take = should_take && !taken;
take.push(should_take);
continue;
} else if trimmed == "#ENDIF" {
take.pop();
continue;
}
if *take.last().unwrap() {
out_file.write(line.as_bytes())?;
out_file.write(b"\n")?;
}
}
Ok(())
}
fn gen_efuse_table(device_name: &str, out_dir: impl AsRef<Path>) -> Result<(), Box<dyn Error>> {
let src_path = PathBuf::from(format!("devices/{device_name}/efuse.csv"));
let out_path = out_dir.as_ref().join("efuse_fields.rs");
println!("cargo:rerun-if-changed={}", src_path.display());
let mut writer = File::create(out_path)?;
let mut reader = BufReader::new(File::open(src_path)?);
let mut line = String::with_capacity(128);
while reader.read_line(&mut line)? > 0 {
if line.ends_with("\n") {
line.pop();
if line.ends_with("\r") {
line.pop();
}
}
// drop comment and trim
line.truncate(
if let Some((pfx, _cmt)) = line.split_once("#") {
pfx
} else {
&line
}
.trim()
.len(),
);
// skip empty
if line.is_empty() {
continue;
}
let mut fields = line.split(",");
match (
fields.next().map(|s| s.trim().replace(".", "_")),
fields
.next()
.map(|s| s.trim().replace(|c: char| !c.is_ascii_digit(), "")),
fields
.next()
.map(|s| s.trim())
.and_then(|s| s.parse::<u32>().ok()),
fields
.next()
.map(|s| s.trim())
.and_then(|s| s.parse::<u32>().ok()),
fields.next().map(|s| s.trim()),
) {
(Some(name), Some(block), Some(bit_off), Some(bit_len), Some(desc)) => {
let desc = desc.replace('[', "`[").replace(']', "]`");
writeln!(writer, "/// {desc}")?;
writeln!(
writer,
"pub const {name}: EfuseField = EfuseField::new(EfuseBlock::Block{block}, {bit_off}, {bit_len});"
)?;
}
other => eprintln!("Invalid data: {other:?}"),
}
line.clear();
}
Ok(())
}
fn detect_atomic_extension(ext: &str) -> bool {
let rustflags = env::var_os("CARGO_ENCODED_RUSTFLAGS")
.unwrap()
.into_string()
.unwrap();
// Users can pass -Ctarget-feature to the compiler multiple times, so we have to
// handle that
let target_flags = rustflags
.split(0x1f as char)
.filter(|s| s.starts_with("target-feature="))
.map(|s| s.strip_prefix("target-feature="))
.flatten();
for tf in target_flags {
let tf = tf
.split(",")
.map(|s| s.trim())
.filter(|s| s.starts_with('+'))
.map(|s| s.strip_prefix('+'))
.flatten();
for tf in tf {
if tf == ext {
return true;
}
}
}
false
}

View File

@ -1,118 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 369d2d860d34e777c0f7d545a7dfc3c4
WR_DIS, EFUSE_BLK0, 0, 16, [] Efuse write disable mask
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [WR_DIS.EFUSE_RD_DISABLE] wr_dis of RD_DIS
WR_DIS.WR_DIS, EFUSE_BLK0, 1, 1, [] wr_dis of WR_DIS
WR_DIS.FLASH_CRYPT_CNT, EFUSE_BLK0, 2, 1, [] wr_dis of FLASH_CRYPT_CNT
WR_DIS.UART_DOWNLOAD_DIS, EFUSE_BLK0, 2, 1, [] wr_dis of UART_DOWNLOAD_DIS
WR_DIS.MAC, EFUSE_BLK0, 3, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.MAC_CRC, EFUSE_BLK0, 3, 1, [WR_DIS.MAC_FACTORY_CRC] wr_dis of MAC_CRC
WR_DIS.DISABLE_APP_CPU, EFUSE_BLK0, 3, 1, [WR_DIS.CHIP_VER_DIS_APP_CPU] wr_dis of DISABLE_APP_CPU
WR_DIS.DISABLE_BT, EFUSE_BLK0, 3, 1, [WR_DIS.CHIP_VER_DIS_BT] wr_dis of DISABLE_BT
WR_DIS.DIS_CACHE, EFUSE_BLK0, 3, 1, [WR_DIS.CHIP_VER_DIS_CACHE] wr_dis of DIS_CACHE
WR_DIS.VOL_LEVEL_HP_INV, EFUSE_BLK0, 3, 1, [] wr_dis of VOL_LEVEL_HP_INV
WR_DIS.CLK8M_FREQ, EFUSE_BLK0, 4, 1, [WR_DIS.CK8M_FREQ] wr_dis of CLK8M_FREQ
WR_DIS.ADC_VREF, EFUSE_BLK0, 4, 1, [] wr_dis of ADC_VREF
WR_DIS.XPD_SDIO_REG, EFUSE_BLK0, 5, 1, [] wr_dis of XPD_SDIO_REG
WR_DIS.XPD_SDIO_TIEH, EFUSE_BLK0, 5, 1, [WR_DIS.SDIO_TIEH] wr_dis of XPD_SDIO_TIEH
WR_DIS.XPD_SDIO_FORCE, EFUSE_BLK0, 5, 1, [WR_DIS.SDIO_FORCE] wr_dis of XPD_SDIO_FORCE
WR_DIS.SPI_PAD_CONFIG_CLK, EFUSE_BLK0, 6, 1, [] wr_dis of SPI_PAD_CONFIG_CLK
WR_DIS.SPI_PAD_CONFIG_Q, EFUSE_BLK0, 6, 1, [] wr_dis of SPI_PAD_CONFIG_Q
WR_DIS.SPI_PAD_CONFIG_D, EFUSE_BLK0, 6, 1, [] wr_dis of SPI_PAD_CONFIG_D
WR_DIS.SPI_PAD_CONFIG_CS0, EFUSE_BLK0, 6, 1, [] wr_dis of SPI_PAD_CONFIG_CS0
WR_DIS.BLOCK1, EFUSE_BLK0, 7, 1, [WR_DIS.ENCRYPT_FLASH_KEY WR_DIS.BLK1] wr_dis of BLOCK1
WR_DIS.BLOCK2, EFUSE_BLK0, 8, 1, [WR_DIS.SECURE_BOOT_KEY WR_DIS.BLK2] wr_dis of BLOCK2
WR_DIS.BLOCK3, EFUSE_BLK0, 9, 1, [WR_DIS.BLK3] wr_dis of BLOCK3
WR_DIS.CUSTOM_MAC_CRC, EFUSE_BLK0, 9, 1, [WR_DIS.MAC_CUSTOM_CRC] wr_dis of CUSTOM_MAC_CRC
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 9, 1, [WR_DIS.MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.ADC1_TP_LOW, EFUSE_BLK0, 9, 1, [] wr_dis of ADC1_TP_LOW
WR_DIS.ADC1_TP_HIGH, EFUSE_BLK0, 9, 1, [] wr_dis of ADC1_TP_HIGH
WR_DIS.ADC2_TP_LOW, EFUSE_BLK0, 9, 1, [] wr_dis of ADC2_TP_LOW
WR_DIS.ADC2_TP_HIGH, EFUSE_BLK0, 9, 1, [] wr_dis of ADC2_TP_HIGH
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 9, 1, [] wr_dis of SECURE_VERSION
WR_DIS.MAC_VERSION, EFUSE_BLK0, 9, 1, [WR_DIS.MAC_CUSTOM_VER] wr_dis of MAC_VERSION
WR_DIS.BLK3_PART_RESERVE, EFUSE_BLK0, 10, 1, [] wr_dis of BLK3_PART_RESERVE
WR_DIS.FLASH_CRYPT_CONFIG, EFUSE_BLK0, 10, 1, [WR_DIS.ENCRYPT_CONFIG] wr_dis of FLASH_CRYPT_CONFIG
WR_DIS.CODING_SCHEME, EFUSE_BLK0, 10, 1, [] wr_dis of CODING_SCHEME
WR_DIS.KEY_STATUS, EFUSE_BLK0, 10, 1, [] wr_dis of KEY_STATUS
WR_DIS.ABS_DONE_0, EFUSE_BLK0, 12, 1, [] wr_dis of ABS_DONE_0
WR_DIS.ABS_DONE_1, EFUSE_BLK0, 13, 1, [] wr_dis of ABS_DONE_1
WR_DIS.JTAG_DISABLE, EFUSE_BLK0, 14, 1, [WR_DIS.DISABLE_JTAG] wr_dis of JTAG_DISABLE
WR_DIS.CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 15, 1, [] wr_dis of CONSOLE_DEBUG_DISABLE
WR_DIS.DISABLE_DL_ENCRYPT, EFUSE_BLK0, 15, 1, [] wr_dis of DISABLE_DL_ENCRYPT
WR_DIS.DISABLE_DL_DECRYPT, EFUSE_BLK0, 15, 1, [] wr_dis of DISABLE_DL_DECRYPT
WR_DIS.DISABLE_DL_CACHE, EFUSE_BLK0, 15, 1, [] wr_dis of DISABLE_DL_CACHE
RD_DIS, EFUSE_BLK0, 16, 4, [] Disable reading from BlOCK1-3
RD_DIS.BLOCK1, EFUSE_BLK0, 16, 1, [RD_DIS.ENCRYPT_FLASH_KEY RD_DIS.BLK1] rd_dis of BLOCK1
RD_DIS.BLOCK2, EFUSE_BLK0, 17, 1, [RD_DIS.SECURE_BOOT_KEY RD_DIS.BLK2] rd_dis of BLOCK2
RD_DIS.BLOCK3, EFUSE_BLK0, 18, 1, [RD_DIS.BLK3] rd_dis of BLOCK3
RD_DIS.CUSTOM_MAC_CRC, EFUSE_BLK0, 18, 1, [RD_DIS.MAC_CUSTOM_CRC] rd_dis of CUSTOM_MAC_CRC
RD_DIS.CUSTOM_MAC, EFUSE_BLK0, 18, 1, [RD_DIS.MAC_CUSTOM] rd_dis of CUSTOM_MAC
RD_DIS.ADC1_TP_LOW, EFUSE_BLK0, 18, 1, [] rd_dis of ADC1_TP_LOW
RD_DIS.ADC1_TP_HIGH, EFUSE_BLK0, 18, 1, [] rd_dis of ADC1_TP_HIGH
RD_DIS.ADC2_TP_LOW, EFUSE_BLK0, 18, 1, [] rd_dis of ADC2_TP_LOW
RD_DIS.ADC2_TP_HIGH, EFUSE_BLK0, 18, 1, [] rd_dis of ADC2_TP_HIGH
RD_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] rd_dis of SECURE_VERSION
RD_DIS.MAC_VERSION, EFUSE_BLK0, 18, 1, [RD_DIS.MAC_CUSTOM_VER] rd_dis of MAC_VERSION
RD_DIS.BLK3_PART_RESERVE, EFUSE_BLK0, 19, 1, [] rd_dis of BLK3_PART_RESERVE
RD_DIS.FLASH_CRYPT_CONFIG, EFUSE_BLK0, 19, 1, [RD_DIS.ENCRYPT_CONFIG] rd_dis of FLASH_CRYPT_CONFIG
RD_DIS.CODING_SCHEME, EFUSE_BLK0, 19, 1, [] rd_dis of CODING_SCHEME
RD_DIS.KEY_STATUS, EFUSE_BLK0, 19, 1, [] rd_dis of KEY_STATUS
FLASH_CRYPT_CNT, EFUSE_BLK0, 20, 7, [] Flash encryption is enabled if this field has an odd number of bits set
UART_DOWNLOAD_DIS, EFUSE_BLK0, 27, 1, [] Disable UART download mode. Valid for ESP32 V3 and newer; only
MAC_FACTORY, EFUSE_BLK0, 32, 48, [MAC_FACTORY] MAC address
MAC_CRC, EFUSE_BLK0, 80, 8, [MAC_FACTORY_CRC] CRC8 for MAC address
DISABLE_APP_CPU, EFUSE_BLK0, 96, 1, [CHIP_VER_DIS_APP_CPU] Disables APP CPU
DISABLE_BT, EFUSE_BLK0, 97, 1, [CHIP_VER_DIS_BT] Disables Bluetooth
CHIP_PACKAGE_4BIT, EFUSE_BLK0, 98, 1, [CHIP_VER_PKG_4BIT] Chip package identifier #4bit
DIS_CACHE, EFUSE_BLK0, 99, 1, [CHIP_VER_DIS_CACHE] Disables cache
SPI_PAD_CONFIG_HD, EFUSE_BLK0, 100, 5, [] read for SPI_pad_config_hd
CHIP_PACKAGE, EFUSE_BLK0, 105, 3, [CHIP_VER_PKG] Chip package identifier
CHIP_CPU_FREQ_LOW, EFUSE_BLK0, 108, 1, [] If set alongside EFUSE_RD_CHIP_CPU_FREQ_RATED; the ESP32's max CPU frequency is rated for 160MHz. 240MHz otherwise
CHIP_CPU_FREQ_RATED, EFUSE_BLK0, 109, 1, [] If set; the ESP32's maximum CPU frequency has been rated
BLK3_PART_RESERVE, EFUSE_BLK0, 110, 1, [] BLOCK3 partially served for ADC calibration data
CHIP_VER_REV1, EFUSE_BLK0, 111, 1, [] bit is set to 1 for rev1 silicon
CLK8M_FREQ, EFUSE_BLK0, 128, 8, [CK8M_FREQ] 8MHz clock freq override
ADC_VREF, EFUSE_BLK0, 136, 5, [] True ADC reference voltage
XPD_SDIO_REG, EFUSE_BLK0, 142, 1, [] read for XPD_SDIO_REG
XPD_SDIO_TIEH, EFUSE_BLK0, 143, 1, [SDIO_TIEH] If XPD_SDIO_FORCE & XPD_SDIO_REG {1: "3.3V"; 0: "1.8V"}
XPD_SDIO_FORCE, EFUSE_BLK0, 144, 1, [SDIO_FORCE] Ignore MTDI pin (GPIO12) for VDD_SDIO on reset
SPI_PAD_CONFIG_CLK, EFUSE_BLK0, 160, 5, [] Override SD_CLK pad (GPIO6/SPICLK)
SPI_PAD_CONFIG_Q, EFUSE_BLK0, 165, 5, [] Override SD_DATA_0 pad (GPIO7/SPIQ)
SPI_PAD_CONFIG_D, EFUSE_BLK0, 170, 5, [] Override SD_DATA_1 pad (GPIO8/SPID)
SPI_PAD_CONFIG_CS0, EFUSE_BLK0, 175, 5, [] Override SD_CMD pad (GPIO11/SPICS0)
CHIP_VER_REV2, EFUSE_BLK0, 180, 1, []
VOL_LEVEL_HP_INV, EFUSE_BLK0, 182, 2, [] This field stores the voltage level for CPU to run at 240 MHz; or for flash/PSRAM to run at 80 MHz.0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (RO)
WAFER_VERSION_MINOR, EFUSE_BLK0, 184, 2, []
FLASH_CRYPT_CONFIG, EFUSE_BLK0, 188, 4, [ENCRYPT_CONFIG] Flash encryption config (key tweak bits)
CODING_SCHEME, EFUSE_BLK0, 192, 2, [] Efuse variable block length scheme {0: "NONE (BLK1-3 len=256 bits)"; 1: "3/4 (BLK1-3 len=192 bits)"; 2: "REPEAT (BLK1-3 len=128 bits) not supported"; 3: "NONE (BLK1-3 len=256 bits)"}
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, [] Disable ROM BASIC interpreter fallback
DISABLE_SDIO_HOST, EFUSE_BLK0, 195, 1, []
ABS_DONE_0, EFUSE_BLK0, 196, 1, [] Secure boot V1 is enabled for bootloader image
ABS_DONE_1, EFUSE_BLK0, 197, 1, [] Secure boot V2 is enabled for bootloader image
JTAG_DISABLE, EFUSE_BLK0, 198, 1, [DISABLE_JTAG] Disable JTAG
DISABLE_DL_ENCRYPT, EFUSE_BLK0, 199, 1, [] Disable flash encryption in UART bootloader
DISABLE_DL_DECRYPT, EFUSE_BLK0, 200, 1, [] Disable flash decryption in UART bootloader
DISABLE_DL_CACHE, EFUSE_BLK0, 201, 1, [] Disable flash cache in UART bootloader
KEY_STATUS, EFUSE_BLK0, 202, 1, [] Usage of efuse block 3 (reserved)
BLOCK1, EFUSE_BLK1, 0, MAX_BLK_LEN, [ENCRYPT_FLASH_KEY] Flash encryption key
BLOCK2, EFUSE_BLK2, 0, MAX_BLK_LEN, [SECURE_BOOT_KEY] Security boot key
CUSTOM_MAC_CRC, EFUSE_BLK3, 0, 8, [MAC_CUSTOM_CRC] CRC8 for custom MAC address
MAC_CUSTOM, EFUSE_BLK3, 8, 48, [MAC_CUSTOM] Custom MAC address
ADC1_TP_LOW, EFUSE_BLK3, 96, 7, [] ADC1 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE
ADC1_TP_HIGH, EFUSE_BLK3, 103, 9, [] ADC1 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE
ADC2_TP_LOW, EFUSE_BLK3, 112, 7, [] ADC2 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE
ADC2_TP_HIGH, EFUSE_BLK3, 119, 9, [] ADC2 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE
SECURE_VERSION, EFUSE_BLK3, 128, 32, [] Secure version for anti-rollback
MAC_VERSION, EFUSE_BLK3, 184, 8, [MAC_CUSTOM_VER] Version of the MAC field {1: "Custom MAC in BLOCK3"}
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,107 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 897499b0349a608b895d467abbcf006b
WR_DIS, EFUSE_BLK0, 0, 8, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 1, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.DIS_PAD_JTAG, EFUSE_BLK0, 1, 1, [] wr_dis of DIS_PAD_JTAG
WR_DIS.DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 1, 1, [] wr_dis of DIS_DOWNLOAD_ICACHE
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 2, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.XTS_KEY_LENGTH_256, EFUSE_BLK0, 2, 1, [] wr_dis of XTS_KEY_LENGTH_256
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 2, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 3, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 3, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 3, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_DIRECT_BOOT, EFUSE_BLK0, 3, 1, [] wr_dis of DIS_DIRECT_BOOT
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 3, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 3, 1, [] wr_dis of FLASH_TPUW
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 4, 1, [] wr_dis of SECURE_VERSION
WR_DIS.CUSTOM_MAC_USED, EFUSE_BLK0, 4, 1, [WR_DIS.ENABLE_CUSTOM_MAC] wr_dis of CUSTOM_MAC_USED
WR_DIS.DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 4, 1, [] wr_dis of DISABLE_WAFER_VERSION_MAJOR
WR_DIS.DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 4, 1, [] wr_dis of DISABLE_BLK_VERSION_MAJOR
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 5, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.MAC, EFUSE_BLK0, 6, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.WAFER_VERSION_MINOR, EFUSE_BLK0, 6, 1, [] wr_dis of WAFER_VERSION_MINOR
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 6, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.PKG_VERSION, EFUSE_BLK0, 6, 1, [] wr_dis of PKG_VERSION
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 6, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 6, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.OCODE, EFUSE_BLK0, 6, 1, [] wr_dis of OCODE
WR_DIS.TEMP_CALIB, EFUSE_BLK0, 6, 1, [] wr_dis of TEMP_CALIB
WR_DIS.ADC1_INIT_CODE_ATTEN0, EFUSE_BLK0, 6, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0
WR_DIS.ADC1_INIT_CODE_ATTEN3, EFUSE_BLK0, 6, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN3
WR_DIS.ADC1_CAL_VOL_ATTEN0, EFUSE_BLK0, 6, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN0
WR_DIS.ADC1_CAL_VOL_ATTEN3, EFUSE_BLK0, 6, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN3
WR_DIS.DIG_DBIAS_HVT, EFUSE_BLK0, 6, 1, [] wr_dis of DIG_DBIAS_HVT
WR_DIS.DIG_LDO_SLP_DBIAS2, EFUSE_BLK0, 6, 1, [] wr_dis of DIG_LDO_SLP_DBIAS2
WR_DIS.DIG_LDO_SLP_DBIAS26, EFUSE_BLK0, 6, 1, [] wr_dis of DIG_LDO_SLP_DBIAS26
WR_DIS.DIG_LDO_ACT_DBIAS26, EFUSE_BLK0, 6, 1, [] wr_dis of DIG_LDO_ACT_DBIAS26
WR_DIS.DIG_LDO_ACT_STEPD10, EFUSE_BLK0, 6, 1, [] wr_dis of DIG_LDO_ACT_STEPD10
WR_DIS.RTC_LDO_SLP_DBIAS13, EFUSE_BLK0, 6, 1, [] wr_dis of RTC_LDO_SLP_DBIAS13
WR_DIS.RTC_LDO_SLP_DBIAS29, EFUSE_BLK0, 6, 1, [] wr_dis of RTC_LDO_SLP_DBIAS29
WR_DIS.RTC_LDO_SLP_DBIAS31, EFUSE_BLK0, 6, 1, [] wr_dis of RTC_LDO_SLP_DBIAS31
WR_DIS.RTC_LDO_ACT_DBIAS31, EFUSE_BLK0, 6, 1, [] wr_dis of RTC_LDO_ACT_DBIAS31
WR_DIS.RTC_LDO_ACT_DBIAS13, EFUSE_BLK0, 6, 1, [] wr_dis of RTC_LDO_ACT_DBIAS13
WR_DIS.ADC_CALIBRATION_3, EFUSE_BLK0, 6, 1, [] wr_dis of ADC_CALIBRATION_3
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 7, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
RD_DIS, EFUSE_BLK0, 32, 2, [] Disable reading from BlOCK3
RD_DIS.KEY0, EFUSE_BLK0, 32, 2, [] Read protection for EFUSE_BLK3. KEY0
RD_DIS.KEY0.LOW, EFUSE_BLK0, 32, 1, [] Read protection for EFUSE_BLK3. KEY0 lower 128-bit key
RD_DIS.KEY0.HI, EFUSE_BLK0, 33, 1, [] Read protection for EFUSE_BLK3. KEY0 higher 128-bit key
WDT_DELAY_SEL, EFUSE_BLK0, 34, 2, [] RTC watchdog timeout threshold; in unit of slow clock cycle {0: "40000"; 1: "80000"; 2: "160000"; 3: "320000"}
DIS_PAD_JTAG, EFUSE_BLK0, 36, 1, [] Set this bit to disable pad jtag
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 37, 1, [] The bit be set to disable icache in download mode
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 38, 1, [] The bit be set to disable manual encryption
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 39, 3, [] Enables flash encryption when 1 or 3 bits are set and disables otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
XTS_KEY_LENGTH_256, EFUSE_BLK0, 42, 1, [] Flash encryption key length {0: "128 bits key"; 1: "256 bits key"}
UART_PRINT_CONTROL, EFUSE_BLK0, 43, 2, [] Set the default UARTboot message output mode {0: "Enable"; 1: "Enable when GPIO8 is low at reset"; 2: "Enable when GPIO8 is high at reset"; 3: "Disable"}
FORCE_SEND_RESUME, EFUSE_BLK0, 45, 1, [] Set this bit to force ROM code to send a resume command during SPI boot
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 46, 1, [] Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 4; 5; 6; 7)
DIS_DIRECT_BOOT, EFUSE_BLK0, 47, 1, [] This bit set means disable direct_boot mode
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 48, 1, [] Set this bit to enable secure UART download mode
FLASH_TPUW, EFUSE_BLK0, 49, 4, [] Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value. Otherwise; the waiting time is twice the configurable value
SECURE_BOOT_EN, EFUSE_BLK0, 53, 1, [] The bit be set to enable secure boot
SECURE_VERSION, EFUSE_BLK0, 54, 4, [] Secure version for anti-rollback
CUSTOM_MAC_USED, EFUSE_BLK0, 58, 1, [ENABLE_CUSTOM_MAC] True if MAC_CUSTOM is burned
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 59, 1, [] Disables check of wafer version major
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 60, 1, [] Disables check of blk version major
USER_DATA, EFUSE_BLK1, 0, 88, [] User data block
USER_DATA.MAC_CUSTOM, EFUSE_BLK1, 0, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC address
MAC_FACTORY, EFUSE_BLK2, 0, 48, [MAC_FACTORY] MAC address
WAFER_VERSION_MINOR, EFUSE_BLK2, 48, 4, [] WAFER_VERSION_MINOR
WAFER_VERSION_MAJOR, EFUSE_BLK2, 52, 2, [] WAFER_VERSION_MAJOR
PKG_VERSION, EFUSE_BLK2, 54, 3, [] EFUSE_PKG_VERSION
BLK_VERSION_MINOR, EFUSE_BLK2, 57, 3, [] Minor version of BLOCK2 {0: "No calib"; 1: "With calib"}
BLK_VERSION_MAJOR, EFUSE_BLK2, 60, 2, [] Major version of BLOCK2
OCODE, EFUSE_BLK2, 62, 7, [] OCode
TEMP_CALIB, EFUSE_BLK2, 69, 9, [] Temperature calibration data
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 78, 8, [] ADC1 init code at atten0
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 86, 5, [] ADC1 init code at atten3
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 91, 8, [] ADC1 calibration voltage at atten0
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 99, 6, [] ADC1 calibration voltage at atten3
DIG_DBIAS_HVT, EFUSE_BLK2, 105, 5, [] BLOCK2 digital dbias when hvt
DIG_LDO_SLP_DBIAS2, EFUSE_BLK2, 110, 7, [] BLOCK2 DIG_LDO_DBG0_DBIAS2
DIG_LDO_SLP_DBIAS26, EFUSE_BLK2, 117, 8, [] BLOCK2 DIG_LDO_DBG0_DBIAS26
DIG_LDO_ACT_DBIAS26, EFUSE_BLK2, 125, 6, [] BLOCK2 DIG_LDO_ACT_DBIAS26
DIG_LDO_ACT_STEPD10, EFUSE_BLK2, 131, 4, [] BLOCK2 DIG_LDO_ACT_STEPD10
RTC_LDO_SLP_DBIAS13, EFUSE_BLK2, 135, 7, [] BLOCK2 DIG_LDO_SLP_DBIAS13
RTC_LDO_SLP_DBIAS29, EFUSE_BLK2, 142, 9, [] BLOCK2 DIG_LDO_SLP_DBIAS29
RTC_LDO_SLP_DBIAS31, EFUSE_BLK2, 151, 6, [] BLOCK2 DIG_LDO_SLP_DBIAS31
RTC_LDO_ACT_DBIAS31, EFUSE_BLK2, 157, 6, [] BLOCK2 DIG_LDO_ACT_DBIAS31
RTC_LDO_ACT_DBIAS13, EFUSE_BLK2, 163, 8, [] BLOCK2 DIG_LDO_ACT_DBIAS13
ADC_CALIBRATION_3, EFUSE_BLK2, 192, 11, [] Store the bit [86:96] of ADC calibration data
KEY0, EFUSE_BLK3, 0, 256, [BLOCK_KEY0] BLOCK_BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryption
KEY0.FE_256BIT, EFUSE_BLK3, 0, 256, [] 256bit FE key
KEY0.FE_128BIT, EFUSE_BLK3, 0, 128, [] 128bit FE key
KEY0.SB_128BIT, EFUSE_BLK3, 128, 128, [] 128bit SB key
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,187 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: a85f874ae2b6538ca48b7c3db4a79531
WR_DIS, EFUSE_BLK0, 0, 32, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.DIS_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_ICACHE
WR_DIS.DIS_USB_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB_JTAG
WR_DIS.DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_ICACHE
WR_DIS.DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_USB_DEVICE] wr_dis of DIS_USB_SERIAL_JTAG
WR_DIS.DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_FORCE_DOWNLOAD
WR_DIS.DIS_TWAI, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_CAN] wr_dis of DIS_TWAI
WR_DIS.JTAG_SEL_ENABLE, EFUSE_BLK0, 2, 1, [] wr_dis of JTAG_SEL_ENABLE
WR_DIS.DIS_PAD_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_PAD_JTAG
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 3, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 5, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE0
WR_DIS.SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 6, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE1
WR_DIS.SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 7, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE2
WR_DIS.KEY_PURPOSE_0, EFUSE_BLK0, 8, 1, [WR_DIS.KEY0_PURPOSE] wr_dis of KEY_PURPOSE_0
WR_DIS.KEY_PURPOSE_1, EFUSE_BLK0, 9, 1, [WR_DIS.KEY1_PURPOSE] wr_dis of KEY_PURPOSE_1
WR_DIS.KEY_PURPOSE_2, EFUSE_BLK0, 10, 1, [WR_DIS.KEY2_PURPOSE] wr_dis of KEY_PURPOSE_2
WR_DIS.KEY_PURPOSE_3, EFUSE_BLK0, 11, 1, [WR_DIS.KEY3_PURPOSE] wr_dis of KEY_PURPOSE_3
WR_DIS.KEY_PURPOSE_4, EFUSE_BLK0, 12, 1, [WR_DIS.KEY4_PURPOSE] wr_dis of KEY_PURPOSE_4
WR_DIS.KEY_PURPOSE_5, EFUSE_BLK0, 13, 1, [WR_DIS.KEY5_PURPOSE] wr_dis of KEY_PURPOSE_5
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 16, 1, [] wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TPUW
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_DIRECT_BOOT, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_LEGACY_SPI_BOOT] wr_dis of DIS_DIRECT_BOOT
WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 18, 1, [WR_DIS.UART_PRINT_CHANNEL] wr_dis of DIS_USB_SERIAL_JTAG_ROM_PRINT
WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_USB_DOWNLOAD_MODE] wr_dis of DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 18, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION
WR_DIS.ERR_RST_ENABLE, EFUSE_BLK0, 19, 1, [] wr_dis of ERR_RST_ENABLE
WR_DIS.DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_WAFER_VERSION_MAJOR
WR_DIS.DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_BLK_VERSION_MAJOR
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1
WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.SPI_PAD_CONFIG_CLK, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CLK
WR_DIS.SPI_PAD_CONFIG_Q, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_Q
WR_DIS.SPI_PAD_CONFIG_D, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D
WR_DIS.SPI_PAD_CONFIG_CS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CS
WR_DIS.SPI_PAD_CONFIG_HD, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_HD
WR_DIS.SPI_PAD_CONFIG_WP, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_WP
WR_DIS.SPI_PAD_CONFIG_DQS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_DQS
WR_DIS.SPI_PAD_CONFIG_D4, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D4
WR_DIS.SPI_PAD_CONFIG_D5, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D5
WR_DIS.SPI_PAD_CONFIG_D6, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D6
WR_DIS.SPI_PAD_CONFIG_D7, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D7
WR_DIS.WAFER_VERSION_MINOR_LO, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_LO
WR_DIS.PKG_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PKG_VERSION
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 20, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.K_RTC_LDO, EFUSE_BLK0, 20, 1, [] wr_dis of K_RTC_LDO
WR_DIS.K_DIG_LDO, EFUSE_BLK0, 20, 1, [] wr_dis of K_DIG_LDO
WR_DIS.V_RTC_DBIAS20, EFUSE_BLK0, 20, 1, [] wr_dis of V_RTC_DBIAS20
WR_DIS.V_DIG_DBIAS20, EFUSE_BLK0, 20, 1, [] wr_dis of V_DIG_DBIAS20
WR_DIS.DIG_DBIAS_HVT, EFUSE_BLK0, 20, 1, [] wr_dis of DIG_DBIAS_HVT
WR_DIS.THRES_HVT, EFUSE_BLK0, 20, 1, [] wr_dis of THRES_HVT
WR_DIS.WAFER_VERSION_MINOR_HI, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_HI
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2
WR_DIS.OPTIONAL_UNIQUE_ID, EFUSE_BLK0, 21, 1, [] wr_dis of OPTIONAL_UNIQUE_ID
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 21, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.TEMP_CALIB, EFUSE_BLK0, 21, 1, [] wr_dis of TEMP_CALIB
WR_DIS.OCODE, EFUSE_BLK0, 21, 1, [] wr_dis of OCODE
WR_DIS.ADC1_INIT_CODE_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0
WR_DIS.ADC1_INIT_CODE_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN1
WR_DIS.ADC1_INIT_CODE_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN2
WR_DIS.ADC1_INIT_CODE_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN3
WR_DIS.ADC1_CAL_VOL_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN0
WR_DIS.ADC1_CAL_VOL_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN1
WR_DIS.ADC1_CAL_VOL_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN2
WR_DIS.ADC1_CAL_VOL_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN3
WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
WR_DIS.BLOCK_KEY1, EFUSE_BLK0, 24, 1, [WR_DIS.KEY1] wr_dis of BLOCK_KEY1
WR_DIS.BLOCK_KEY2, EFUSE_BLK0, 25, 1, [WR_DIS.KEY2] wr_dis of BLOCK_KEY2
WR_DIS.BLOCK_KEY3, EFUSE_BLK0, 26, 1, [WR_DIS.KEY3] wr_dis of BLOCK_KEY3
WR_DIS.BLOCK_KEY4, EFUSE_BLK0, 27, 1, [WR_DIS.KEY4] wr_dis of BLOCK_KEY4
WR_DIS.BLOCK_KEY5, EFUSE_BLK0, 28, 1, [WR_DIS.KEY5] wr_dis of BLOCK_KEY5
WR_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 29, 1, [WR_DIS.SYS_DATA_PART2] wr_dis of BLOCK_SYS_DATA2
WR_DIS.USB_EXCHG_PINS, EFUSE_BLK0, 30, 1, [] wr_dis of USB_EXCHG_PINS
WR_DIS.VDD_SPI_AS_GPIO, EFUSE_BLK0, 30, 1, [] wr_dis of VDD_SPI_AS_GPIO
WR_DIS.SOFT_DIS_JTAG, EFUSE_BLK0, 31, 1, [] wr_dis of SOFT_DIS_JTAG
RD_DIS, EFUSE_BLK0, 32, 7, [] Disable reading from BlOCK4-10
RD_DIS.BLOCK_KEY0, EFUSE_BLK0, 32, 1, [RD_DIS.KEY0] rd_dis of BLOCK_KEY0
RD_DIS.BLOCK_KEY1, EFUSE_BLK0, 33, 1, [RD_DIS.KEY1] rd_dis of BLOCK_KEY1
RD_DIS.BLOCK_KEY2, EFUSE_BLK0, 34, 1, [RD_DIS.KEY2] rd_dis of BLOCK_KEY2
RD_DIS.BLOCK_KEY3, EFUSE_BLK0, 35, 1, [RD_DIS.KEY3] rd_dis of BLOCK_KEY3
RD_DIS.BLOCK_KEY4, EFUSE_BLK0, 36, 1, [RD_DIS.KEY4] rd_dis of BLOCK_KEY4
RD_DIS.BLOCK_KEY5, EFUSE_BLK0, 37, 1, [RD_DIS.KEY5] rd_dis of BLOCK_KEY5
RD_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 38, 1, [RD_DIS.SYS_DATA_PART2] rd_dis of BLOCK_SYS_DATA2
DIS_ICACHE, EFUSE_BLK0, 40, 1, [] Set this bit to disable Icache
DIS_USB_JTAG, EFUSE_BLK0, 41, 1, [] Set this bit to disable function of usb switch to jtag in module of usb device
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, [] Set this bit to disable Icache in download mode (boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 43, 1, [DIS_USB_DEVICE] USB-Serial-JTAG {0: "Enable"; 1: "Disable"}
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, [] Set this bit to disable the function that forces chip into download mode
DIS_TWAI, EFUSE_BLK0, 46, 1, [DIS_CAN] Set this bit to disable CAN function
JTAG_SEL_ENABLE, EFUSE_BLK0, 47, 1, [] Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0
SOFT_DIS_JTAG, EFUSE_BLK0, 48, 3, [] Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module
DIS_PAD_JTAG, EFUSE_BLK0, 51, 1, [] Set this bit to disable JTAG in the hard way. JTAG is disabled permanently
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 52, 1, [] Set this bit to disable flash encryption when in download boot modes
USB_EXCHG_PINS, EFUSE_BLK0, 57, 1, [] Set this bit to exchange USB D+ and D- pins
VDD_SPI_AS_GPIO, EFUSE_BLK0, 58, 1, [] Set this bit to vdd spi pin function as gpio
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, [] RTC watchdog timeout threshold; in unit of slow clock cycle {0: "40000"; 1: "80000"; 2: "160000"; 3: "320000"}
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, [] Enables flash encryption when 1 or 3 bits are set and disables otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, [] Revoke 1st secure boot key
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, [] Revoke 2nd secure boot key
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, [] Revoke 3rd secure boot key
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, [KEY0_PURPOSE] Purpose of Key0
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, [KEY1_PURPOSE] Purpose of Key1
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, [KEY2_PURPOSE] Purpose of Key2
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, [KEY3_PURPOSE] Purpose of Key3
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, [KEY4_PURPOSE] Purpose of Key4
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, [KEY5_PURPOSE] Purpose of Key5
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, [] Set this bit to enable secure boot
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, [] Set this bit to enable revoking aggressive secure boot
FLASH_TPUW, EFUSE_BLK0, 124, 4, [] Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value; Otherwise; the waiting time is twice the configurable value
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, [] Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 3; 6; 7)
DIS_DIRECT_BOOT, EFUSE_BLK0, 129, 1, [DIS_LEGACY_SPI_BOOT] Disable direct boot mode
DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 130, 1, [UART_PRINT_CHANNEL] USB printing {0: "Enable"; 1: "Disable"}
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, [DIS_USB_DOWNLOAD_MODE] Disable UART download mode through USB-Serial-JTAG
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, [] Set this bit to enable secure UART download mode
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, [] Set the default UARTboot message output mode {0: "Enable"; 1: "Enable when GPIO8 is low at reset"; 2: "Enable when GPIO8 is high at reset"; 3: "Disable"}
FORCE_SEND_RESUME, EFUSE_BLK0, 141, 1, [] Set this bit to force ROM code to send a resume command during SPI boot
SECURE_VERSION, EFUSE_BLK0, 142, 16, [] Secure version (used by ESP-IDF anti-rollback feature)
ERR_RST_ENABLE, EFUSE_BLK0, 159, 1, [] Use BLOCK0 to check error record registers {0: "without check"; 1: "with check"}
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 160, 1, [] Disables check of wafer version major
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 161, 1, [] Disables check of blk version major
MAC_FACTORY, EFUSE_BLK1, 0, 48, [MAC_FACTORY] MAC address
SPI_PAD_CONFIG_CLK, EFUSE_BLK1, 48, 6, [] SPI PAD CLK
SPI_PAD_CONFIG_Q, EFUSE_BLK1, 54, 6, [] SPI PAD Q(D1)
SPI_PAD_CONFIG_D, EFUSE_BLK1, 60, 6, [] SPI PAD D(D0)
SPI_PAD_CONFIG_CS, EFUSE_BLK1, 66, 6, [] SPI PAD CS
SPI_PAD_CONFIG_HD, EFUSE_BLK1, 72, 6, [] SPI PAD HD(D3)
SPI_PAD_CONFIG_WP, EFUSE_BLK1, 78, 6, [] SPI PAD WP(D2)
SPI_PAD_CONFIG_DQS, EFUSE_BLK1, 84, 6, [] SPI PAD DQS
SPI_PAD_CONFIG_D4, EFUSE_BLK1, 90, 6, [] SPI PAD D4
SPI_PAD_CONFIG_D5, EFUSE_BLK1, 96, 6, [] SPI PAD D5
SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, [] SPI PAD D6
SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, [] SPI PAD D7
WAFER_VERSION_MINOR_LO, EFUSE_BLK1, 114, 3, [] WAFER_VERSION_MINOR least significant bits
PKG_VERSION, EFUSE_BLK1, 117, 3, [] Package version
BLK_VERSION_MINOR, EFUSE_BLK1, 120, 3, [] BLK_VERSION_MINOR
K_RTC_LDO, EFUSE_BLK1, 135, 7, [] BLOCK1 K_RTC_LDO
K_DIG_LDO, EFUSE_BLK1, 142, 7, [] BLOCK1 K_DIG_LDO
V_RTC_DBIAS20, EFUSE_BLK1, 149, 8, [] BLOCK1 voltage of rtc dbias20
V_DIG_DBIAS20, EFUSE_BLK1, 157, 8, [] BLOCK1 voltage of digital dbias20
DIG_DBIAS_HVT, EFUSE_BLK1, 165, 5, [] BLOCK1 digital dbias when hvt
THRES_HVT, EFUSE_BLK1, 170, 10, [] BLOCK1 pvt threshold when hvt
WAFER_VERSION_MINOR_HI, EFUSE_BLK1, 183, 1, [] WAFER_VERSION_MINOR most significant bit
WAFER_VERSION_MAJOR, EFUSE_BLK1, 184, 2, [] WAFER_VERSION_MAJOR
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, [] Optional unique 128-bit ID
BLK_VERSION_MAJOR, EFUSE_BLK2, 128, 2, [] BLK_VERSION_MAJOR of BLOCK2 {0: "No calibration"; 1: "With calibration"}
TEMP_CALIB, EFUSE_BLK2, 131, 9, [] Temperature calibration data
OCODE, EFUSE_BLK2, 140, 8, [] ADC OCode
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 148, 10, [] ADC1 init code at atten0
ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 158, 10, [] ADC1 init code at atten1
ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 168, 10, [] ADC1 init code at atten2
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 178, 10, [] ADC1 init code at atten3
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 188, 10, [] ADC1 calibration voltage at atten0
ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 198, 10, [] ADC1 calibration voltage at atten1
ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 208, 10, [] ADC1 calibration voltage at atten2
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 218, 10, [] ADC1 calibration voltage at atten3
USER_DATA, EFUSE_BLK3, 0, 256, [BLOCK_USR_DATA] User data
USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC address
KEY0, EFUSE_BLK4, 0, 256, [BLOCK_KEY0] Key0 or user data
KEY1, EFUSE_BLK5, 0, 256, [BLOCK_KEY1] Key1 or user data
KEY2, EFUSE_BLK6, 0, 256, [BLOCK_KEY2] Key2 or user data
KEY3, EFUSE_BLK7, 0, 256, [BLOCK_KEY3] Key3 or user data
KEY4, EFUSE_BLK8, 0, 256, [BLOCK_KEY4] Key4 or user data
KEY5, EFUSE_BLK9, 0, 256, [BLOCK_KEY5] Key5 or user data
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, [BLOCK_SYS_DATA2] System data part 2 (reserved)
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,181 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 709e8ea096e8a03a10006d40d5451a49
WR_DIS, EFUSE_BLK0, 0, 32, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.CRYPT_DPA_ENABLE, EFUSE_BLK0, 1, 1, [] wr_dis of CRYPT_DPA_ENABLE
WR_DIS.SWAP_UART_SDIO_EN, EFUSE_BLK0, 2, 1, [] wr_dis of SWAP_UART_SDIO_EN
WR_DIS.DIS_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_ICACHE
WR_DIS.DIS_USB_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB_JTAG
WR_DIS.DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_ICACHE
WR_DIS.DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB_SERIAL_JTAG
WR_DIS.DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_FORCE_DOWNLOAD
WR_DIS.DIS_TWAI, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_CAN] wr_dis of DIS_TWAI
WR_DIS.JTAG_SEL_ENABLE, EFUSE_BLK0, 2, 1, [] wr_dis of JTAG_SEL_ENABLE
WR_DIS.DIS_PAD_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_PAD_JTAG
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 3, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 5, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE0
WR_DIS.SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 6, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE1
WR_DIS.SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 7, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE2
WR_DIS.KEY_PURPOSE_0, EFUSE_BLK0, 8, 1, [WR_DIS.KEY0_PURPOSE] wr_dis of KEY_PURPOSE_0
WR_DIS.KEY_PURPOSE_1, EFUSE_BLK0, 9, 1, [WR_DIS.KEY1_PURPOSE] wr_dis of KEY_PURPOSE_1
WR_DIS.KEY_PURPOSE_2, EFUSE_BLK0, 10, 1, [WR_DIS.KEY2_PURPOSE] wr_dis of KEY_PURPOSE_2
WR_DIS.KEY_PURPOSE_3, EFUSE_BLK0, 11, 1, [WR_DIS.KEY3_PURPOSE] wr_dis of KEY_PURPOSE_3
WR_DIS.KEY_PURPOSE_4, EFUSE_BLK0, 12, 1, [WR_DIS.KEY4_PURPOSE] wr_dis of KEY_PURPOSE_4
WR_DIS.KEY_PURPOSE_5, EFUSE_BLK0, 13, 1, [WR_DIS.KEY5_PURPOSE] wr_dis of KEY_PURPOSE_5
WR_DIS.SEC_DPA_LEVEL, EFUSE_BLK0, 14, 1, [WR_DIS.DPA_SEC_LEVEL] wr_dis of SEC_DPA_LEVEL
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 16, 1, [] wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE
WR_DIS.SPI_DOWNLOAD_MSPI_DIS, EFUSE_BLK0, 17, 1, [] wr_dis of SPI_DOWNLOAD_MSPI_DIS
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TPUW
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_DIRECT_BOOT, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DIRECT_BOOT
WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_USB_PRINT] wr_dis of DIS_USB_SERIAL_JTAG_ROM_PRINT
WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 18, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION
WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE, EFUSE_BLK0, 19, 1, [] wr_dis of SECURE_BOOT_DISABLE_FAST_WAKE
WR_DIS.DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_WAFER_VERSION_MAJOR
WR_DIS.DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_BLK_VERSION_MAJOR
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1
WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.MAC_EXT, EFUSE_BLK0, 20, 1, [] wr_dis of MAC_EXT
WR_DIS.WAFER_VERSION_MINOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.PKG_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PKG_VERSION
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 20, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.FLASH_CAP, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_CAP
WR_DIS.FLASH_TEMP, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_TEMP
WR_DIS.FLASH_VENDOR, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_VENDOR
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2
WR_DIS.OPTIONAL_UNIQUE_ID, EFUSE_BLK0, 21, 1, [] wr_dis of OPTIONAL_UNIQUE_ID
WR_DIS.TEMP_CALIB, EFUSE_BLK0, 21, 1, [] wr_dis of TEMP_CALIB
WR_DIS.OCODE, EFUSE_BLK0, 21, 1, [] wr_dis of OCODE
WR_DIS.ADC1_INIT_CODE_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0
WR_DIS.ADC1_INIT_CODE_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN1
WR_DIS.ADC1_INIT_CODE_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN2
WR_DIS.ADC1_INIT_CODE_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN3
WR_DIS.ADC1_CAL_VOL_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN0
WR_DIS.ADC1_CAL_VOL_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN1
WR_DIS.ADC1_CAL_VOL_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN2
WR_DIS.ADC1_CAL_VOL_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN3
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH0
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH1
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH2
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH3
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH4, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH4
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH5, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH5
WR_DIS.ADC1_INIT_CODE_ATTEN0_CH6, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0_CH6
WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
WR_DIS.BLOCK_KEY1, EFUSE_BLK0, 24, 1, [WR_DIS.KEY1] wr_dis of BLOCK_KEY1
WR_DIS.BLOCK_KEY2, EFUSE_BLK0, 25, 1, [WR_DIS.KEY2] wr_dis of BLOCK_KEY2
WR_DIS.BLOCK_KEY3, EFUSE_BLK0, 26, 1, [WR_DIS.KEY3] wr_dis of BLOCK_KEY3
WR_DIS.BLOCK_KEY4, EFUSE_BLK0, 27, 1, [WR_DIS.KEY4] wr_dis of BLOCK_KEY4
WR_DIS.BLOCK_KEY5, EFUSE_BLK0, 28, 1, [WR_DIS.KEY5] wr_dis of BLOCK_KEY5
WR_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 29, 1, [WR_DIS.SYS_DATA_PART2] wr_dis of BLOCK_SYS_DATA2
WR_DIS.USB_EXCHG_PINS, EFUSE_BLK0, 30, 1, [] wr_dis of USB_EXCHG_PINS
WR_DIS.VDD_SPI_AS_GPIO, EFUSE_BLK0, 30, 1, [] wr_dis of VDD_SPI_AS_GPIO
WR_DIS.SOFT_DIS_JTAG, EFUSE_BLK0, 31, 1, [] wr_dis of SOFT_DIS_JTAG
RD_DIS, EFUSE_BLK0, 32, 7, [] Disable reading from BlOCK4-10
RD_DIS.BLOCK_KEY0, EFUSE_BLK0, 32, 1, [RD_DIS.KEY0] rd_dis of BLOCK_KEY0
RD_DIS.BLOCK_KEY1, EFUSE_BLK0, 33, 1, [RD_DIS.KEY1] rd_dis of BLOCK_KEY1
RD_DIS.BLOCK_KEY2, EFUSE_BLK0, 34, 1, [RD_DIS.KEY2] rd_dis of BLOCK_KEY2
RD_DIS.BLOCK_KEY3, EFUSE_BLK0, 35, 1, [RD_DIS.KEY3] rd_dis of BLOCK_KEY3
RD_DIS.BLOCK_KEY4, EFUSE_BLK0, 36, 1, [RD_DIS.KEY4] rd_dis of BLOCK_KEY4
RD_DIS.BLOCK_KEY5, EFUSE_BLK0, 37, 1, [RD_DIS.KEY5] rd_dis of BLOCK_KEY5
RD_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 38, 1, [RD_DIS.SYS_DATA_PART2] rd_dis of BLOCK_SYS_DATA2
SWAP_UART_SDIO_EN, EFUSE_BLK0, 39, 1, [] Represents whether pad of uart and sdio is swapped or not. 1: swapped. 0: not swapped
DIS_ICACHE, EFUSE_BLK0, 40, 1, [] Represents whether icache is disabled or enabled. 1: disabled. 0: enabled
DIS_USB_JTAG, EFUSE_BLK0, 41, 1, [] Represents whether the function of usb switch to jtag is disabled or enabled. 1: disabled. 0: enabled
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, [] Represents whether icache is disabled or enabled in Download mode. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 43, 1, [] Represents whether USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, [] Represents whether the function that forces chip into download mode is disabled or enabled. 1: disabled. 0: enabled
SPI_DOWNLOAD_MSPI_DIS, EFUSE_BLK0, 45, 1, [] Represents whether SPI0 controller during boot_mode_download is disabled or enabled. 1: disabled. 0: enabled
DIS_TWAI, EFUSE_BLK0, 46, 1, [DIS_CAN] Represents whether TWAI function is disabled or enabled. 1: disabled. 0: enabled
JTAG_SEL_ENABLE, EFUSE_BLK0, 47, 1, [] Represents whether the selection between usb_to_jtag and pad_to_jtag through strapping gpio15 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0 is enabled or disabled. 1: enabled. 0: disabled
SOFT_DIS_JTAG, EFUSE_BLK0, 48, 3, [] Represents whether JTAG is disabled in soft way. Odd number: disabled. Even number: enabled
DIS_PAD_JTAG, EFUSE_BLK0, 51, 1, [] Represents whether JTAG is disabled in the hard way(permanently). 1: disabled. 0: enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 52, 1, [] Represents whether flash encrypt function is disabled or enabled(except in SPI boot mode). 1: disabled. 0: enabled
USB_EXCHG_PINS, EFUSE_BLK0, 57, 1, [] Represents whether the D+ and D- pins is exchanged. 1: exchanged. 0: not exchanged
VDD_SPI_AS_GPIO, EFUSE_BLK0, 58, 1, [] Represents whether vdd spi pin is functioned as gpio. 1: functioned. 0: not functioned
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, [] Represents whether RTC watchdog timeout threshold is selected at startup. 1: selected. 0: not selected
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, [] Enables flash encryption when 1 or 3 bits are set and disables otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, [] Revoke 1st secure boot key
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, [] Revoke 2nd secure boot key
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, [] Revoke 3rd secure boot key
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, [KEY0_PURPOSE] Represents the purpose of Key0
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, [KEY1_PURPOSE] Represents the purpose of Key1
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, [KEY2_PURPOSE] Represents the purpose of Key2
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, [KEY3_PURPOSE] Represents the purpose of Key3
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, [KEY4_PURPOSE] Represents the purpose of Key4
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, [KEY5_PURPOSE] Represents the purpose of Key5
SEC_DPA_LEVEL, EFUSE_BLK0, 112, 2, [DPA_SEC_LEVEL] Represents the spa secure level by configuring the clock random divide mode
CRYPT_DPA_ENABLE, EFUSE_BLK0, 114, 1, [] Represents whether anti-dpa attack is enabled. 1:enabled. 0: disabled
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, [] Represents whether secure boot is enabled or disabled. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, [] Represents whether revoking aggressive secure boot is enabled or disabled. 1: enabled. 0: disabled
FLASH_TPUW, EFUSE_BLK0, 124, 4, [] Represents the flash waiting time after power-up; in unit of ms. When the value less than 15; the waiting time is the programmed value. Otherwise; the waiting time is 2 times the programmed value
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, [] Represents whether Download mode is disabled or enabled. 1: disabled. 0: enabled
DIS_DIRECT_BOOT, EFUSE_BLK0, 129, 1, [] Represents whether direct boot mode is disabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 130, 1, [DIS_USB_PRINT] Represents whether print from USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, [] Represents whether the USB-Serial-JTAG download function is disabled or enabled. 1: disabled. 0: enabled
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, [] Represents whether security download is enabled or disabled. 1: enabled. 0: disabled
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, [] Set the default UARTboot message output mode {0: "Enable"; 1: "Enable when GPIO8 is low at reset"; 2: "Enable when GPIO8 is high at reset"; 3: "Disable"}
FORCE_SEND_RESUME, EFUSE_BLK0, 141, 1, [] Represents whether ROM code is forced to send a resume command during SPI boot. 1: forced. 0:not forced
SECURE_VERSION, EFUSE_BLK0, 142, 16, [] Represents the version used by ESP-IDF anti-rollback feature
SECURE_BOOT_DISABLE_FAST_WAKE, EFUSE_BLK0, 158, 1, [] Represents whether FAST VERIFY ON WAKE is disabled or enabled when Secure Boot is enabled. 1: disabled. 0: enabled
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 160, 1, [] Disables check of wafer version major
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 161, 1, [] Disables check of blk version major
MAC_FACTORY, EFUSE_BLK1, 0, 48, [MAC_FACTORY] MAC address
MAC_EXT, EFUSE_BLK1, 48, 16, [] Stores the extended bits of MAC address
WAFER_VERSION_MINOR, EFUSE_BLK1, 114, 4, []
WAFER_VERSION_MAJOR, EFUSE_BLK1, 118, 2, []
PKG_VERSION, EFUSE_BLK1, 120, 3, [] Package version
BLK_VERSION_MINOR, EFUSE_BLK1, 123, 3, [] BLK_VERSION_MINOR of BLOCK2
BLK_VERSION_MAJOR, EFUSE_BLK1, 126, 2, [] BLK_VERSION_MAJOR of BLOCK2
FLASH_CAP, EFUSE_BLK1, 128, 3, []
FLASH_TEMP, EFUSE_BLK1, 131, 2, []
FLASH_VENDOR, EFUSE_BLK1, 133, 3, []
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, [] Optional unique 128-bit ID
TEMP_CALIB, EFUSE_BLK2, 128, 9, [] Temperature calibration data
OCODE, EFUSE_BLK2, 137, 8, [] ADC OCode
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 145, 10, [] ADC1 init code at atten0
ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 155, 10, [] ADC1 init code at atten1
ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 165, 10, [] ADC1 init code at atten2
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 175, 10, [] ADC1 init code at atten3
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 185, 10, [] ADC1 calibration voltage at atten0
ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 195, 10, [] ADC1 calibration voltage at atten1
ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 205, 10, [] ADC1 calibration voltage at atten2
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 215, 10, [] ADC1 calibration voltage at atten3
ADC1_INIT_CODE_ATTEN0_CH0, EFUSE_BLK2, 225, 4, [] ADC1 init code at atten0 ch0
ADC1_INIT_CODE_ATTEN0_CH1, EFUSE_BLK2, 229, 4, [] ADC1 init code at atten0 ch1
ADC1_INIT_CODE_ATTEN0_CH2, EFUSE_BLK2, 233, 4, [] ADC1 init code at atten0 ch2
ADC1_INIT_CODE_ATTEN0_CH3, EFUSE_BLK2, 237, 4, [] ADC1 init code at atten0 ch3
ADC1_INIT_CODE_ATTEN0_CH4, EFUSE_BLK2, 241, 4, [] ADC1 init code at atten0 ch4
ADC1_INIT_CODE_ATTEN0_CH5, EFUSE_BLK2, 245, 4, [] ADC1 init code at atten0 ch5
ADC1_INIT_CODE_ATTEN0_CH6, EFUSE_BLK2, 249, 4, [] ADC1 init code at atten0 ch6
USER_DATA, EFUSE_BLK3, 0, 256, [BLOCK_USR_DATA] User data
USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC
KEY0, EFUSE_BLK4, 0, 256, [BLOCK_KEY0] Key0 or user data
KEY1, EFUSE_BLK5, 0, 256, [BLOCK_KEY1] Key1 or user data
KEY2, EFUSE_BLK6, 0, 256, [BLOCK_KEY2] Key2 or user data
KEY3, EFUSE_BLK7, 0, 256, [BLOCK_KEY3] Key3 or user data
KEY4, EFUSE_BLK8, 0, 256, [BLOCK_KEY4] Key4 or user data
KEY5, EFUSE_BLK9, 0, 256, [BLOCK_KEY5] Key5 or user data
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, [BLOCK_SYS_DATA2] System data part 2 (reserved)
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,155 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 4df10f83de85f2d830b7c466aabb28e7
WR_DIS, EFUSE_BLK0, 0, 32, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.DIS_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_ICACHE
WR_DIS.DIS_USB_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB_JTAG
WR_DIS.POWERGLITCH_EN, EFUSE_BLK0, 2, 1, [] wr_dis of POWERGLITCH_EN
WR_DIS.DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_FORCE_DOWNLOAD
WR_DIS.SPI_DOWNLOAD_MSPI_DIS, EFUSE_BLK0, 2, 1, [] wr_dis of SPI_DOWNLOAD_MSPI_DIS
WR_DIS.DIS_TWAI, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_CAN] wr_dis of DIS_TWAI
WR_DIS.JTAG_SEL_ENABLE, EFUSE_BLK0, 2, 1, [] wr_dis of JTAG_SEL_ENABLE
WR_DIS.DIS_PAD_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_PAD_JTAG
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 3, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 5, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE0
WR_DIS.SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 6, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE1
WR_DIS.SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 7, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE2
WR_DIS.KEY_PURPOSE_0, EFUSE_BLK0, 8, 1, [WR_DIS.KEY0_PURPOSE] wr_dis of KEY_PURPOSE_0
WR_DIS.KEY_PURPOSE_1, EFUSE_BLK0, 9, 1, [WR_DIS.KEY1_PURPOSE] wr_dis of KEY_PURPOSE_1
WR_DIS.KEY_PURPOSE_2, EFUSE_BLK0, 10, 1, [WR_DIS.KEY2_PURPOSE] wr_dis of KEY_PURPOSE_2
WR_DIS.KEY_PURPOSE_3, EFUSE_BLK0, 11, 1, [WR_DIS.KEY3_PURPOSE] wr_dis of KEY_PURPOSE_3
WR_DIS.KEY_PURPOSE_4, EFUSE_BLK0, 12, 1, [WR_DIS.KEY4_PURPOSE] wr_dis of KEY_PURPOSE_4
WR_DIS.KEY_PURPOSE_5, EFUSE_BLK0, 13, 1, [WR_DIS.KEY5_PURPOSE] wr_dis of KEY_PURPOSE_5
WR_DIS.SEC_DPA_LEVEL, EFUSE_BLK0, 14, 1, [] wr_dis of SEC_DPA_LEVEL
WR_DIS.CRYPT_DPA_ENABLE, EFUSE_BLK0, 14, 1, [] wr_dis of CRYPT_DPA_ENABLE
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 16, 1, [] wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE
WR_DIS.ECDSA_FORCE_USE_HARDWARE_K, EFUSE_BLK0, 17, 1, [] wr_dis of ECDSA_FORCE_USE_HARDWARE_K
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TPUW
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_DIRECT_BOOT, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DIRECT_BOOT
WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_USB_PRINT] wr_dis of DIS_USB_SERIAL_JTAG_ROM_PRINT
WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 18, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION
WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_BOOT_DISABLE_FAST_WAKE
WR_DIS.HYS_EN_PAD0, EFUSE_BLK0, 19, 1, [] wr_dis of HYS_EN_PAD0
WR_DIS.HYS_EN_PAD1, EFUSE_BLK0, 19, 1, [] wr_dis of HYS_EN_PAD1
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1
WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.MAC_EXT, EFUSE_BLK0, 20, 1, [] wr_dis of MAC_EXT
WR_DIS.RXIQ_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of RXIQ_VERSION
WR_DIS.RXIQ_0, EFUSE_BLK0, 20, 1, [] wr_dis of RXIQ_0
WR_DIS.RXIQ_1, EFUSE_BLK0, 20, 1, [] wr_dis of RXIQ_1
WR_DIS.WAFER_VERSION_MINOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of DISABLE_WAFER_VERSION_MAJOR
WR_DIS.FLASH_CAP, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_CAP
WR_DIS.FLASH_TEMP, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_TEMP
WR_DIS.FLASH_VENDOR, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_VENDOR
WR_DIS.PKG_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PKG_VERSION
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2
WR_DIS.OPTIONAL_UNIQUE_ID, EFUSE_BLK0, 21, 1, [] wr_dis of OPTIONAL_UNIQUE_ID
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 21, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 21, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 21, 1, [] wr_dis of DISABLE_BLK_VERSION_MAJOR
WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
WR_DIS.BLOCK_KEY1, EFUSE_BLK0, 24, 1, [WR_DIS.KEY1] wr_dis of BLOCK_KEY1
WR_DIS.BLOCK_KEY2, EFUSE_BLK0, 25, 1, [WR_DIS.KEY2] wr_dis of BLOCK_KEY2
WR_DIS.BLOCK_KEY3, EFUSE_BLK0, 26, 1, [WR_DIS.KEY3] wr_dis of BLOCK_KEY3
WR_DIS.BLOCK_KEY4, EFUSE_BLK0, 27, 1, [WR_DIS.KEY4] wr_dis of BLOCK_KEY4
WR_DIS.BLOCK_KEY5, EFUSE_BLK0, 28, 1, [WR_DIS.KEY5] wr_dis of BLOCK_KEY5
WR_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 29, 1, [WR_DIS.SYS_DATA_PART2] wr_dis of BLOCK_SYS_DATA2
WR_DIS.USB_EXCHG_PINS, EFUSE_BLK0, 30, 1, [] wr_dis of USB_EXCHG_PINS
WR_DIS.VDD_SPI_AS_GPIO, EFUSE_BLK0, 30, 1, [] wr_dis of VDD_SPI_AS_GPIO
WR_DIS.SOFT_DIS_JTAG, EFUSE_BLK0, 31, 1, [] wr_dis of SOFT_DIS_JTAG
RD_DIS, EFUSE_BLK0, 32, 7, [] Disable reading from BlOCK4-10
RD_DIS.BLOCK_KEY0, EFUSE_BLK0, 32, 1, [RD_DIS.KEY0] rd_dis of BLOCK_KEY0
RD_DIS.BLOCK_KEY1, EFUSE_BLK0, 33, 1, [RD_DIS.KEY1] rd_dis of BLOCK_KEY1
RD_DIS.BLOCK_KEY2, EFUSE_BLK0, 34, 1, [RD_DIS.KEY2] rd_dis of BLOCK_KEY2
RD_DIS.BLOCK_KEY3, EFUSE_BLK0, 35, 1, [RD_DIS.KEY3] rd_dis of BLOCK_KEY3
RD_DIS.BLOCK_KEY4, EFUSE_BLK0, 36, 1, [RD_DIS.KEY4] rd_dis of BLOCK_KEY4
RD_DIS.BLOCK_KEY5, EFUSE_BLK0, 37, 1, [RD_DIS.KEY5] rd_dis of BLOCK_KEY5
RD_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 38, 1, [RD_DIS.SYS_DATA_PART2] rd_dis of BLOCK_SYS_DATA2
DIS_ICACHE, EFUSE_BLK0, 40, 1, [] Represents whether icache is disabled or enabled. 1: disabled. 0: enabled
DIS_USB_JTAG, EFUSE_BLK0, 41, 1, [] Represents whether the function of usb switch to jtag is disabled or enabled. 1: disabled. 0: enabled
POWERGLITCH_EN, EFUSE_BLK0, 42, 1, [] Represents whether power glitch function is enabled. 1: enabled. 0: disabled
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, [] Represents whether the function that forces chip into download mode is disabled or enabled. 1: disabled. 0: enabled
SPI_DOWNLOAD_MSPI_DIS, EFUSE_BLK0, 45, 1, [] Represents whether SPI0 controller during boot_mode_download is disabled or enabled. 1: disabled. 0: enabled
DIS_TWAI, EFUSE_BLK0, 46, 1, [DIS_CAN] Represents whether TWAI function is disabled or enabled. 1: disabled. 0: enabled
JTAG_SEL_ENABLE, EFUSE_BLK0, 47, 1, [] Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio25 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0
SOFT_DIS_JTAG, EFUSE_BLK0, 48, 3, [] Represents whether JTAG is disabled in soft way. Odd number: disabled. Even number: enabled
DIS_PAD_JTAG, EFUSE_BLK0, 51, 1, [] Represents whether JTAG is disabled in the hard way(permanently). 1: disabled. 0: enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 52, 1, [] Represents whether flash encrypt function is disabled or enabled(except in SPI boot mode). 1: disabled. 0: enabled
USB_EXCHG_PINS, EFUSE_BLK0, 57, 1, [] Represents whether the D+ and D- pins is exchanged. 1: exchanged. 0: not exchanged
VDD_SPI_AS_GPIO, EFUSE_BLK0, 58, 1, [] Represents whether vdd spi pin is functioned as gpio. 1: functioned. 0: not functioned
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, [] Represents whether RTC watchdog timeout threshold is selected at startup. 1: selected. 0: not selected
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, [] Enables flash encryption when 1 or 3 bits are set and disables otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, [] Revoke 1st secure boot key
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, [] Revoke 2nd secure boot key
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, [] Revoke 3rd secure boot key
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, [KEY0_PURPOSE] Represents the purpose of Key0
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, [KEY1_PURPOSE] Represents the purpose of Key1
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, [KEY2_PURPOSE] Represents the purpose of Key2
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, [KEY3_PURPOSE] Represents the purpose of Key3
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, [KEY4_PURPOSE] Represents the purpose of Key4
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, [KEY5_PURPOSE] Represents the purpose of Key5
SEC_DPA_LEVEL, EFUSE_BLK0, 112, 2, [] Represents the spa secure level by configuring the clock random divide mode
ECDSA_FORCE_USE_HARDWARE_K, EFUSE_BLK0, 114, 1, [] Represents whether hardware random number k is forced used in ESDCA. 1: force used. 0: not force used
CRYPT_DPA_ENABLE, EFUSE_BLK0, 115, 1, [] Represents whether anti-dpa attack is enabled. 1:enabled. 0: disabled
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, [] Represents whether secure boot is enabled or disabled. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, [] Represents whether revoking aggressive secure boot is enabled or disabled. 1: enabled. 0: disabled
FLASH_TPUW, EFUSE_BLK0, 124, 4, [] Represents the flash waiting time after power-up; in unit of ms. When the value less than 15; the waiting time is the programmed value. Otherwise; the waiting time is 2 times the programmed value
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, [] Represents whether Download mode is disabled or enabled. 1: disabled. 0: enabled
DIS_DIRECT_BOOT, EFUSE_BLK0, 129, 1, [] Represents whether direct boot mode is disabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 130, 1, [DIS_USB_PRINT] Set this bit to disable USB-Serial-JTAG print during rom boot
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, [] Represents whether the USB-Serial-JTAG download function is disabled or enabled. 1: disabled. 0: enabled
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, [] Represents whether security download is enabled or disabled. 1: enabled. 0: disabled
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, [] Set the default UARTboot message output mode {0: "Enable"; 1: "Enable when GPIO8 is low at reset"; 2: "Enable when GPIO8 is high at reset"; 3: "Disable"}
FORCE_SEND_RESUME, EFUSE_BLK0, 136, 1, [] Represents whether ROM code is forced to send a resume command during SPI boot. 1: forced. 0:not forced
SECURE_VERSION, EFUSE_BLK0, 137, 16, [] Represents the version used by ESP-IDF anti-rollback feature
SECURE_BOOT_DISABLE_FAST_WAKE, EFUSE_BLK0, 153, 1, [] Represents whether FAST VERIFY ON WAKE is disabled or enabled when Secure Boot is enabled. 1: disabled. 0: enabled
HYS_EN_PAD0, EFUSE_BLK0, 154, 6, [] Set bits to enable hysteresis function of PAD0~5
HYS_EN_PAD1, EFUSE_BLK0, 160, 22, [] Set bits to enable hysteresis function of PAD6~27
MAC_FACTORY, EFUSE_BLK1, 0, 48, [MAC_FACTORY] MAC address
MAC_EXT, EFUSE_BLK1, 48, 16, [] Stores the extended bits of MAC address
RXIQ_VERSION, EFUSE_BLK1, 64, 3, [] RF Calibration data. RXIQ version
RXIQ_0, EFUSE_BLK1, 67, 7, [] RF Calibration data. RXIQ data 0
RXIQ_1, EFUSE_BLK1, 74, 7, [] RF Calibration data. RXIQ data 1
WAFER_VERSION_MINOR, EFUSE_BLK1, 114, 3, []
WAFER_VERSION_MAJOR, EFUSE_BLK1, 117, 2, []
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK1, 119, 1, [] Disables check of wafer version major
FLASH_CAP, EFUSE_BLK1, 120, 3, []
FLASH_TEMP, EFUSE_BLK1, 123, 2, []
FLASH_VENDOR, EFUSE_BLK1, 125, 3, []
PKG_VERSION, EFUSE_BLK1, 128, 3, [] Package version
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, [] Optional unique 128-bit ID
BLK_VERSION_MINOR, EFUSE_BLK2, 130, 3, [] BLK_VERSION_MINOR of BLOCK2. 1: RF Calibration data in BLOCK1
BLK_VERSION_MAJOR, EFUSE_BLK2, 133, 2, [] BLK_VERSION_MAJOR of BLOCK2
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK2, 135, 1, [] Disables check of blk version major
USER_DATA, EFUSE_BLK3, 0, 256, [BLOCK_USR_DATA] User data
USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC
KEY0, EFUSE_BLK4, 0, 256, [BLOCK_KEY0] Key0 or user data
KEY1, EFUSE_BLK5, 0, 256, [BLOCK_KEY1] Key1 or user data
KEY2, EFUSE_BLK6, 0, 256, [BLOCK_KEY2] Key2 or user data
KEY3, EFUSE_BLK7, 0, 256, [BLOCK_KEY3] Key3 or user data
KEY4, EFUSE_BLK8, 0, 256, [BLOCK_KEY4] Key4 or user data
KEY5, EFUSE_BLK9, 0, 256, [BLOCK_KEY5] Key5 or user data
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, [BLOCK_SYS_DATA2] System data part 2 (reserved)
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,207 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 888a61f6f500d9c7ee0aa32016b0bee7
WR_DIS, EFUSE_BLK0, 0, 32, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.DIS_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_ICACHE
WR_DIS.DIS_DCACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DCACHE
WR_DIS.DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_ICACHE
WR_DIS.DIS_DOWNLOAD_DCACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_DCACHE
WR_DIS.DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_FORCE_DOWNLOAD
WR_DIS.DIS_USB, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB
WR_DIS.DIS_TWAI, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_CAN] wr_dis of DIS_TWAI
WR_DIS.DIS_BOOT_REMAP, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_BOOT_REMAP
WR_DIS.SOFT_DIS_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of SOFT_DIS_JTAG
WR_DIS.HARD_DIS_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of HARD_DIS_JTAG
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.VDD_SPI_XPD, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_XPD
WR_DIS.VDD_SPI_TIEH, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_TIEH
WR_DIS.VDD_SPI_FORCE, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_FORCE
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 3, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 5, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE0
WR_DIS.SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 6, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE1
WR_DIS.SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 7, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE2
WR_DIS.KEY_PURPOSE_0, EFUSE_BLK0, 8, 1, [WR_DIS.KEY0_PURPOSE] wr_dis of KEY_PURPOSE_0
WR_DIS.KEY_PURPOSE_1, EFUSE_BLK0, 9, 1, [WR_DIS.KEY1_PURPOSE] wr_dis of KEY_PURPOSE_1
WR_DIS.KEY_PURPOSE_2, EFUSE_BLK0, 10, 1, [WR_DIS.KEY2_PURPOSE] wr_dis of KEY_PURPOSE_2
WR_DIS.KEY_PURPOSE_3, EFUSE_BLK0, 11, 1, [WR_DIS.KEY3_PURPOSE] wr_dis of KEY_PURPOSE_3
WR_DIS.KEY_PURPOSE_4, EFUSE_BLK0, 12, 1, [WR_DIS.KEY4_PURPOSE] wr_dis of KEY_PURPOSE_4
WR_DIS.KEY_PURPOSE_5, EFUSE_BLK0, 13, 1, [WR_DIS.KEY5_PURPOSE] wr_dis of KEY_PURPOSE_5
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 16, 1, [] wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TPUW
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_LEGACY_SPI_BOOT, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_LEGACY_SPI_BOOT
WR_DIS.UART_PRINT_CHANNEL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CHANNEL
WR_DIS.DIS_USB_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_USB_DOWNLOAD_MODE
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 18, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.PIN_POWER_SELECTION, EFUSE_BLK0, 18, 1, [] wr_dis of PIN_POWER_SELECTION
WR_DIS.FLASH_TYPE, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TYPE
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1
WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.SPI_PAD_CONFIG_CLK, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CLK
WR_DIS.SPI_PAD_CONFIG_Q, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_Q
WR_DIS.SPI_PAD_CONFIG_D, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D
WR_DIS.SPI_PAD_CONFIG_CS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CS
WR_DIS.SPI_PAD_CONFIG_HD, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_HD
WR_DIS.SPI_PAD_CONFIG_WP, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_WP
WR_DIS.SPI_PAD_CONFIG_DQS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_DQS
WR_DIS.SPI_PAD_CONFIG_D4, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D4
WR_DIS.SPI_PAD_CONFIG_D5, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D5
WR_DIS.SPI_PAD_CONFIG_D6, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D6
WR_DIS.SPI_PAD_CONFIG_D7, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D7
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.WAFER_VERSION_MINOR_HI, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_HI
WR_DIS.FLASH_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_VERSION
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.PSRAM_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PSRAM_VERSION
WR_DIS.PKG_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PKG_VERSION
WR_DIS.WAFER_VERSION_MINOR_LO, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_LO
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2
WR_DIS.OPTIONAL_UNIQUE_ID, EFUSE_BLK0, 21, 1, [] wr_dis of OPTIONAL_UNIQUE_ID
WR_DIS.ADC_CALIB, EFUSE_BLK0, 21, 1, [] wr_dis of ADC_CALIB
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 21, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.TEMP_CALIB, EFUSE_BLK0, 21, 1, [] wr_dis of TEMP_CALIB
WR_DIS.RTCCALIB_V1IDX_A10H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A10H
WR_DIS.RTCCALIB_V1IDX_A11H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A11H
WR_DIS.RTCCALIB_V1IDX_A12H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A12H
WR_DIS.RTCCALIB_V1IDX_A13H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A13H
WR_DIS.RTCCALIB_V1IDX_A20H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A20H
WR_DIS.RTCCALIB_V1IDX_A21H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A21H
WR_DIS.RTCCALIB_V1IDX_A22H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A22H
WR_DIS.RTCCALIB_V1IDX_A23H, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A23H
WR_DIS.RTCCALIB_V1IDX_A10L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A10L
WR_DIS.RTCCALIB_V1IDX_A11L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A11L
WR_DIS.RTCCALIB_V1IDX_A12L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A12L
WR_DIS.RTCCALIB_V1IDX_A13L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A13L
WR_DIS.RTCCALIB_V1IDX_A20L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A20L
WR_DIS.RTCCALIB_V1IDX_A21L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A21L
WR_DIS.RTCCALIB_V1IDX_A22L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A22L
WR_DIS.RTCCALIB_V1IDX_A23L, EFUSE_BLK0, 21, 1, [] wr_dis of RTCCALIB_V1IDX_A23L
WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
WR_DIS.BLOCK_KEY1, EFUSE_BLK0, 24, 1, [WR_DIS.KEY1] wr_dis of BLOCK_KEY1
WR_DIS.BLOCK_KEY2, EFUSE_BLK0, 25, 1, [WR_DIS.KEY2] wr_dis of BLOCK_KEY2
WR_DIS.BLOCK_KEY3, EFUSE_BLK0, 26, 1, [WR_DIS.KEY3] wr_dis of BLOCK_KEY3
WR_DIS.BLOCK_KEY4, EFUSE_BLK0, 27, 1, [WR_DIS.KEY4] wr_dis of BLOCK_KEY4
WR_DIS.BLOCK_KEY5, EFUSE_BLK0, 28, 1, [WR_DIS.KEY5] wr_dis of BLOCK_KEY5
WR_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 29, 1, [WR_DIS.SYS_DATA_PART2] wr_dis of BLOCK_SYS_DATA2
WR_DIS.USB_EXCHG_PINS, EFUSE_BLK0, 30, 1, [] wr_dis of USB_EXCHG_PINS
WR_DIS.USB_EXT_PHY_ENABLE, EFUSE_BLK0, 30, 1, [WR_DIS.EXT_PHY_ENABLE] wr_dis of USB_EXT_PHY_ENABLE
WR_DIS.USB_FORCE_NOPERSIST, EFUSE_BLK0, 30, 1, [] wr_dis of USB_FORCE_NOPERSIST
WR_DIS.BLOCK0_VERSION, EFUSE_BLK0, 30, 1, [] wr_dis of BLOCK0_VERSION
RD_DIS, EFUSE_BLK0, 32, 7, [] Disable reading from BlOCK4-10
RD_DIS.BLOCK_KEY0, EFUSE_BLK0, 32, 1, [RD_DIS.KEY0] rd_dis of BLOCK_KEY0
RD_DIS.BLOCK_KEY1, EFUSE_BLK0, 33, 1, [RD_DIS.KEY1] rd_dis of BLOCK_KEY1
RD_DIS.BLOCK_KEY2, EFUSE_BLK0, 34, 1, [RD_DIS.KEY2] rd_dis of BLOCK_KEY2
RD_DIS.BLOCK_KEY3, EFUSE_BLK0, 35, 1, [RD_DIS.KEY3] rd_dis of BLOCK_KEY3
RD_DIS.BLOCK_KEY4, EFUSE_BLK0, 36, 1, [RD_DIS.KEY4] rd_dis of BLOCK_KEY4
RD_DIS.BLOCK_KEY5, EFUSE_BLK0, 37, 1, [RD_DIS.KEY5] rd_dis of BLOCK_KEY5
RD_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 38, 1, [RD_DIS.SYS_DATA_PART2] rd_dis of BLOCK_SYS_DATA2
DIS_ICACHE, EFUSE_BLK0, 40, 1, [] Set this bit to disable Icache
DIS_DCACHE, EFUSE_BLK0, 41, 1, [] Set this bit to disable Dcache
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, [] Disables Icache when SoC is in Download mode
DIS_DOWNLOAD_DCACHE, EFUSE_BLK0, 43, 1, [] Disables Dcache when SoC is in Download mode
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, [] Set this bit to disable the function that forces chip into download mode
DIS_USB, EFUSE_BLK0, 45, 1, [] Set this bit to disable USB OTG function
DIS_TWAI, EFUSE_BLK0, 46, 1, [DIS_CAN] Set this bit to disable the TWAI Controller function
DIS_BOOT_REMAP, EFUSE_BLK0, 47, 1, [] Disables capability to Remap RAM to ROM address space
SOFT_DIS_JTAG, EFUSE_BLK0, 49, 1, [] Software disables JTAG. When software disabled; JTAG can be activated temporarily by HMAC peripheral
HARD_DIS_JTAG, EFUSE_BLK0, 50, 1, [] Hardware disables JTAG permanently
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 51, 1, [] Disables flash encryption when in download boot modes
USB_EXCHG_PINS, EFUSE_BLK0, 56, 1, [] Set this bit to exchange USB D+ and D- pins
USB_EXT_PHY_ENABLE, EFUSE_BLK0, 57, 1, [EXT_PHY_ENABLE] Set this bit to enable external USB PHY
USB_FORCE_NOPERSIST, EFUSE_BLK0, 58, 1, [] If set; forces USB BVALID to 1
BLOCK0_VERSION, EFUSE_BLK0, 59, 2, [] BLOCK0 efuse version
VDD_SPI_XPD, EFUSE_BLK0, 68, 1, [] If VDD_SPI_FORCE is 1; this value determines if the VDD_SPI regulator is powered on
VDD_SPI_TIEH, EFUSE_BLK0, 69, 1, [] If VDD_SPI_FORCE is 1; determines VDD_SPI voltage {0: "VDD_SPI connects to 1.8 V LDO"; 1: "VDD_SPI connects to VDD3P3_RTC_IO"}
VDD_SPI_FORCE, EFUSE_BLK0, 70, 1, [] Set this bit to use XPD_VDD_PSI_REG and VDD_SPI_TIEH to configure VDD_SPI LDO
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, [] RTC watchdog timeout threshold; in unit of slow clock cycle {0: "40000"; 1: "80000"; 2: "160000"; 3: "320000"}
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, [] Enables flash encryption when 1 or 3 bits are set and disabled otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, [] Revoke 1st secure boot key
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, [] Revoke 2nd secure boot key
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, [] Revoke 3rd secure boot key
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, [KEY0_PURPOSE] Purpose of KEY0
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, [KEY1_PURPOSE] Purpose of KEY1
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, [KEY2_PURPOSE] Purpose of KEY2
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, [KEY3_PURPOSE] Purpose of KEY3
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, [KEY4_PURPOSE] Purpose of KEY4
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, [KEY5_PURPOSE] Purpose of KEY5
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, [] Set this bit to enable secure boot
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, [] Set this bit to enable aggressive secure boot key revocation mode
FLASH_TPUW, EFUSE_BLK0, 124, 4, [] Configures flash startup delay after SoC power-up; in unit of (ms/2). When the value is 15; delay is 7.5 ms
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, [] Set this bit to disable all download boot modes
DIS_LEGACY_SPI_BOOT, EFUSE_BLK0, 129, 1, [] Set this bit to disable Legacy SPI boot mode
UART_PRINT_CHANNEL, EFUSE_BLK0, 130, 1, [] Selects the default UART for printing boot messages {0: "UART0"; 1: "UART1"}
DIS_USB_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, [] Set this bit to disable use of USB OTG in UART download boot mode
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, [] Set this bit to enable secure UART download mode (read/write flash only)
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, [] Set the default UART boot message output mode {0: "Enable"; 1: "Enable when GPIO46 is low at reset"; 2: "Enable when GPIO46 is high at reset"; 3: "Disable"}
PIN_POWER_SELECTION, EFUSE_BLK0, 136, 1, [] Set default power supply for GPIO33-GPIO37; set when SPI flash is initialized {0: "VDD3P3_CPU"; 1: "VDD_SPI"}
FLASH_TYPE, EFUSE_BLK0, 137, 1, [] SPI flash type {0: "4 data lines"; 1: "8 data lines"}
FORCE_SEND_RESUME, EFUSE_BLK0, 138, 1, [] If set; forces ROM code to send an SPI flash resume command during SPI boot
SECURE_VERSION, EFUSE_BLK0, 139, 16, [] Secure version (used by ESP-IDF anti-rollback feature)
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 160, 1, [] Disables check of wafer version major
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 161, 1, [] Disables check of blk version major
MAC_FACTORY, EFUSE_BLK1, 0, 48, [MAC_FACTORY] MAC address
SPI_PAD_CONFIG_CLK, EFUSE_BLK1, 48, 6, [] SPI_PAD_configure CLK
SPI_PAD_CONFIG_Q, EFUSE_BLK1, 54, 6, [] SPI_PAD_configure Q(D1)
SPI_PAD_CONFIG_D, EFUSE_BLK1, 60, 6, [] SPI_PAD_configure D(D0)
SPI_PAD_CONFIG_CS, EFUSE_BLK1, 66, 6, [] SPI_PAD_configure CS
SPI_PAD_CONFIG_HD, EFUSE_BLK1, 72, 6, [] SPI_PAD_configure HD(D3)
SPI_PAD_CONFIG_WP, EFUSE_BLK1, 78, 6, [] SPI_PAD_configure WP(D2)
SPI_PAD_CONFIG_DQS, EFUSE_BLK1, 84, 6, [] SPI_PAD_configure DQS
SPI_PAD_CONFIG_D4, EFUSE_BLK1, 90, 6, [] SPI_PAD_configure D4
SPI_PAD_CONFIG_D5, EFUSE_BLK1, 96, 6, [] SPI_PAD_configure D5
SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, [] SPI_PAD_configure D6
SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, [] SPI_PAD_configure D7
WAFER_VERSION_MAJOR, EFUSE_BLK1, 114, 2, [] WAFER_VERSION_MAJOR
WAFER_VERSION_MINOR_HI, EFUSE_BLK1, 116, 1, [] WAFER_VERSION_MINOR most significant bit
FLASH_VERSION, EFUSE_BLK1, 117, 4, [] Flash version
BLK_VERSION_MAJOR, EFUSE_BLK1, 121, 2, [] BLK_VERSION_MAJOR
PSRAM_VERSION, EFUSE_BLK1, 124, 4, [] PSRAM version
PKG_VERSION, EFUSE_BLK1, 128, 4, [] Package version
WAFER_VERSION_MINOR_LO, EFUSE_BLK1, 132, 3, [] WAFER_VERSION_MINOR least significant bits
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, [] Optional unique 128-bit ID
ADC_CALIB, EFUSE_BLK2, 128, 4, [] 4 bit of ADC calibration
BLK_VERSION_MINOR, EFUSE_BLK2, 132, 3, [] BLK_VERSION_MINOR of BLOCK2 {0: "No calib"; 1: "ADC calib V1"; 2: "ADC calib V2"}
TEMP_CALIB, EFUSE_BLK2, 135, 9, [] Temperature calibration data
RTCCALIB_V1IDX_A10H, EFUSE_BLK2, 144, 8, []
RTCCALIB_V1IDX_A11H, EFUSE_BLK2, 152, 8, []
RTCCALIB_V1IDX_A12H, EFUSE_BLK2, 160, 8, []
RTCCALIB_V1IDX_A13H, EFUSE_BLK2, 168, 8, []
RTCCALIB_V1IDX_A20H, EFUSE_BLK2, 176, 8, []
RTCCALIB_V1IDX_A21H, EFUSE_BLK2, 184, 8, []
RTCCALIB_V1IDX_A22H, EFUSE_BLK2, 192, 8, []
RTCCALIB_V1IDX_A23H, EFUSE_BLK2, 200, 8, []
RTCCALIB_V1IDX_A10L, EFUSE_BLK2, 208, 6, []
RTCCALIB_V1IDX_A11L, EFUSE_BLK2, 214, 6, []
RTCCALIB_V1IDX_A12L, EFUSE_BLK2, 220, 6, []
RTCCALIB_V1IDX_A13L, EFUSE_BLK2, 226, 6, []
RTCCALIB_V1IDX_A20L, EFUSE_BLK2, 232, 6, []
RTCCALIB_V1IDX_A21L, EFUSE_BLK2, 238, 6, []
RTCCALIB_V1IDX_A22L, EFUSE_BLK2, 244, 6, []
RTCCALIB_V1IDX_A23L, EFUSE_BLK2, 250, 6, []
USER_DATA, EFUSE_BLK3, 0, 256, [BLOCK_USR_DATA] User data
USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC
KEY0, EFUSE_BLK4, 0, 256, [BLOCK_KEY0] Key0 or user data
KEY1, EFUSE_BLK5, 0, 256, [BLOCK_KEY1] Key1 or user data
KEY2, EFUSE_BLK6, 0, 256, [BLOCK_KEY2] Key2 or user data
KEY3, EFUSE_BLK7, 0, 256, [BLOCK_KEY3] Key3 or user data
KEY4, EFUSE_BLK8, 0, 256, [BLOCK_KEY4] Key4 or user data
KEY5, EFUSE_BLK9, 0, 256, [BLOCK_KEY5] Key5 or user data
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, [BLOCK_SYS_DATA2] System data part 2 (reserved)
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,227 +0,0 @@
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
# | (EFUSE_BLK0 | (0..255) | (1-256) | #
# | EFUSE_BLK1 | | | #
# | ...) | | | #
##########################################################################
# !!!!!!!!!!! #
# After editing this file, run the command manually "idf.py efuse-common-table"
# this will generate new source files, next rebuild all the sources.
# !!!!!!!!!!! #
# This file was generated by regtools.py based on the efuses.yaml file with the version: 6925129eca795b8b087d31be539740ec
WR_DIS, EFUSE_BLK0, 0, 32, [] Disable programming of individual eFuses
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, [] wr_dis of RD_DIS
WR_DIS.DIS_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_ICACHE
WR_DIS.DIS_DCACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DCACHE
WR_DIS.DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_ICACHE
WR_DIS.DIS_DOWNLOAD_DCACHE, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_DCACHE
WR_DIS.DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_FORCE_DOWNLOAD
WR_DIS.DIS_USB_OTG, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_USB] wr_dis of DIS_USB_OTG
WR_DIS.DIS_TWAI, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_CAN] wr_dis of DIS_TWAI
WR_DIS.DIS_APP_CPU, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_APP_CPU
WR_DIS.DIS_PAD_JTAG, EFUSE_BLK0, 2, 1, [WR_DIS.HARD_DIS_JTAG] wr_dis of DIS_PAD_JTAG
WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT
WR_DIS.DIS_USB_JTAG, EFUSE_BLK0, 2, 1, [] wr_dis of DIS_USB_JTAG
WR_DIS.DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 2, 1, [WR_DIS.DIS_USB_DEVICE] wr_dis of DIS_USB_SERIAL_JTAG
WR_DIS.STRAP_JTAG_SEL, EFUSE_BLK0, 2, 1, [] wr_dis of STRAP_JTAG_SEL
WR_DIS.USB_PHY_SEL, EFUSE_BLK0, 2, 1, [] wr_dis of USB_PHY_SEL
WR_DIS.VDD_SPI_XPD, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_XPD
WR_DIS.VDD_SPI_TIEH, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_TIEH
WR_DIS.VDD_SPI_FORCE, EFUSE_BLK0, 3, 1, [] wr_dis of VDD_SPI_FORCE
WR_DIS.WDT_DELAY_SEL, EFUSE_BLK0, 3, 1, [] wr_dis of WDT_DELAY_SEL
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, [] wr_dis of SPI_BOOT_CRYPT_CNT
WR_DIS.SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 5, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE0
WR_DIS.SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 6, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE1
WR_DIS.SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 7, 1, [] wr_dis of SECURE_BOOT_KEY_REVOKE2
WR_DIS.KEY_PURPOSE_0, EFUSE_BLK0, 8, 1, [WR_DIS.KEY0_PURPOSE] wr_dis of KEY_PURPOSE_0
WR_DIS.KEY_PURPOSE_1, EFUSE_BLK0, 9, 1, [WR_DIS.KEY1_PURPOSE] wr_dis of KEY_PURPOSE_1
WR_DIS.KEY_PURPOSE_2, EFUSE_BLK0, 10, 1, [WR_DIS.KEY2_PURPOSE] wr_dis of KEY_PURPOSE_2
WR_DIS.KEY_PURPOSE_3, EFUSE_BLK0, 11, 1, [WR_DIS.KEY3_PURPOSE] wr_dis of KEY_PURPOSE_3
WR_DIS.KEY_PURPOSE_4, EFUSE_BLK0, 12, 1, [WR_DIS.KEY4_PURPOSE] wr_dis of KEY_PURPOSE_4
WR_DIS.KEY_PURPOSE_5, EFUSE_BLK0, 13, 1, [WR_DIS.KEY5_PURPOSE] wr_dis of KEY_PURPOSE_5
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, [] wr_dis of SECURE_BOOT_EN
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 16, 1, [] wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE
WR_DIS.FLASH_TPUW, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TPUW
WR_DIS.DIS_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of DIS_DOWNLOAD_MODE
WR_DIS.DIS_DIRECT_BOOT, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_LEGACY_SPI_BOOT] wr_dis of DIS_DIRECT_BOOT
WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 18, 1, [WR_DIS.UART_PRINT_CHANNEL] wr_dis of DIS_USB_SERIAL_JTAG_ROM_PRINT
WR_DIS.FLASH_ECC_MODE, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_ECC_MODE
WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 18, 1, [WR_DIS.DIS_USB_DOWNLOAD_MODE] wr_dis of DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE
WR_DIS.ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 18, 1, [] wr_dis of ENABLE_SECURITY_DOWNLOAD
WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis of UART_PRINT_CONTROL
WR_DIS.PIN_POWER_SELECTION, EFUSE_BLK0, 18, 1, [] wr_dis of PIN_POWER_SELECTION
WR_DIS.FLASH_TYPE, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_TYPE
WR_DIS.FLASH_PAGE_SIZE, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_PAGE_SIZE
WR_DIS.FLASH_ECC_EN, EFUSE_BLK0, 18, 1, [] wr_dis of FLASH_ECC_EN
WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME
WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION
WR_DIS.DIS_USB_OTG_DOWNLOAD_MODE, EFUSE_BLK0, 19, 1, [] wr_dis of DIS_USB_OTG_DOWNLOAD_MODE
WR_DIS.DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_WAFER_VERSION_MAJOR
WR_DIS.DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 19, 1, [] wr_dis of DISABLE_BLK_VERSION_MAJOR
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1
WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC
WR_DIS.SPI_PAD_CONFIG_CLK, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CLK
WR_DIS.SPI_PAD_CONFIG_Q, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_Q
WR_DIS.SPI_PAD_CONFIG_D, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D
WR_DIS.SPI_PAD_CONFIG_CS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_CS
WR_DIS.SPI_PAD_CONFIG_HD, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_HD
WR_DIS.SPI_PAD_CONFIG_WP, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_WP
WR_DIS.SPI_PAD_CONFIG_DQS, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_DQS
WR_DIS.SPI_PAD_CONFIG_D4, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D4
WR_DIS.SPI_PAD_CONFIG_D5, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D5
WR_DIS.SPI_PAD_CONFIG_D6, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D6
WR_DIS.SPI_PAD_CONFIG_D7, EFUSE_BLK0, 20, 1, [] wr_dis of SPI_PAD_CONFIG_D7
WR_DIS.WAFER_VERSION_MINOR_LO, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_LO
WR_DIS.PKG_VERSION, EFUSE_BLK0, 20, 1, [] wr_dis of PKG_VERSION
WR_DIS.BLK_VERSION_MINOR, EFUSE_BLK0, 20, 1, [] wr_dis of BLK_VERSION_MINOR
WR_DIS.K_RTC_LDO, EFUSE_BLK0, 20, 1, [] wr_dis of K_RTC_LDO
WR_DIS.K_DIG_LDO, EFUSE_BLK0, 20, 1, [] wr_dis of K_DIG_LDO
WR_DIS.V_RTC_DBIAS20, EFUSE_BLK0, 20, 1, [] wr_dis of V_RTC_DBIAS20
WR_DIS.V_DIG_DBIAS20, EFUSE_BLK0, 20, 1, [] wr_dis of V_DIG_DBIAS20
WR_DIS.DIG_DBIAS_HVT, EFUSE_BLK0, 20, 1, [] wr_dis of DIG_DBIAS_HVT
WR_DIS.WAFER_VERSION_MINOR_HI, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MINOR_HI
WR_DIS.WAFER_VERSION_MAJOR, EFUSE_BLK0, 20, 1, [] wr_dis of WAFER_VERSION_MAJOR
WR_DIS.ADC2_CAL_VOL_ATTEN3, EFUSE_BLK0, 20, 1, [] wr_dis of ADC2_CAL_VOL_ATTEN3
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2
WR_DIS.OPTIONAL_UNIQUE_ID, EFUSE_BLK0, 21, 1, [] wr_dis of OPTIONAL_UNIQUE_ID
WR_DIS.BLK_VERSION_MAJOR, EFUSE_BLK0, 21, 1, [] wr_dis of BLK_VERSION_MAJOR
WR_DIS.TEMP_CALIB, EFUSE_BLK0, 21, 1, [] wr_dis of TEMP_CALIB
WR_DIS.OCODE, EFUSE_BLK0, 21, 1, [] wr_dis of OCODE
WR_DIS.ADC1_INIT_CODE_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN0
WR_DIS.ADC1_INIT_CODE_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN1
WR_DIS.ADC1_INIT_CODE_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN2
WR_DIS.ADC1_INIT_CODE_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_INIT_CODE_ATTEN3
WR_DIS.ADC2_INIT_CODE_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_INIT_CODE_ATTEN0
WR_DIS.ADC2_INIT_CODE_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_INIT_CODE_ATTEN1
WR_DIS.ADC2_INIT_CODE_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_INIT_CODE_ATTEN2
WR_DIS.ADC2_INIT_CODE_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_INIT_CODE_ATTEN3
WR_DIS.ADC1_CAL_VOL_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN0
WR_DIS.ADC1_CAL_VOL_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN1
WR_DIS.ADC1_CAL_VOL_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN2
WR_DIS.ADC1_CAL_VOL_ATTEN3, EFUSE_BLK0, 21, 1, [] wr_dis of ADC1_CAL_VOL_ATTEN3
WR_DIS.ADC2_CAL_VOL_ATTEN0, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_CAL_VOL_ATTEN0
WR_DIS.ADC2_CAL_VOL_ATTEN1, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_CAL_VOL_ATTEN1
WR_DIS.ADC2_CAL_VOL_ATTEN2, EFUSE_BLK0, 21, 1, [] wr_dis of ADC2_CAL_VOL_ATTEN2
WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA
WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC
WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0
WR_DIS.BLOCK_KEY1, EFUSE_BLK0, 24, 1, [WR_DIS.KEY1] wr_dis of BLOCK_KEY1
WR_DIS.BLOCK_KEY2, EFUSE_BLK0, 25, 1, [WR_DIS.KEY2] wr_dis of BLOCK_KEY2
WR_DIS.BLOCK_KEY3, EFUSE_BLK0, 26, 1, [WR_DIS.KEY3] wr_dis of BLOCK_KEY3
WR_DIS.BLOCK_KEY4, EFUSE_BLK0, 27, 1, [WR_DIS.KEY4] wr_dis of BLOCK_KEY4
WR_DIS.BLOCK_KEY5, EFUSE_BLK0, 28, 1, [WR_DIS.KEY5] wr_dis of BLOCK_KEY5
WR_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 29, 1, [WR_DIS.SYS_DATA_PART2] wr_dis of BLOCK_SYS_DATA2
WR_DIS.USB_EXCHG_PINS, EFUSE_BLK0, 30, 1, [] wr_dis of USB_EXCHG_PINS
WR_DIS.USB_EXT_PHY_ENABLE, EFUSE_BLK0, 30, 1, [WR_DIS.EXT_PHY_ENABLE] wr_dis of USB_EXT_PHY_ENABLE
WR_DIS.SOFT_DIS_JTAG, EFUSE_BLK0, 31, 1, [] wr_dis of SOFT_DIS_JTAG
RD_DIS, EFUSE_BLK0, 32, 7, [] Disable reading from BlOCK4-10
RD_DIS.BLOCK_KEY0, EFUSE_BLK0, 32, 1, [RD_DIS.KEY0] rd_dis of BLOCK_KEY0
RD_DIS.BLOCK_KEY1, EFUSE_BLK0, 33, 1, [RD_DIS.KEY1] rd_dis of BLOCK_KEY1
RD_DIS.BLOCK_KEY2, EFUSE_BLK0, 34, 1, [RD_DIS.KEY2] rd_dis of BLOCK_KEY2
RD_DIS.BLOCK_KEY3, EFUSE_BLK0, 35, 1, [RD_DIS.KEY3] rd_dis of BLOCK_KEY3
RD_DIS.BLOCK_KEY4, EFUSE_BLK0, 36, 1, [RD_DIS.KEY4] rd_dis of BLOCK_KEY4
RD_DIS.BLOCK_KEY5, EFUSE_BLK0, 37, 1, [RD_DIS.KEY5] rd_dis of BLOCK_KEY5
RD_DIS.BLOCK_SYS_DATA2, EFUSE_BLK0, 38, 1, [RD_DIS.SYS_DATA_PART2] rd_dis of BLOCK_SYS_DATA2
DIS_ICACHE, EFUSE_BLK0, 40, 1, [] Set this bit to disable Icache
DIS_DCACHE, EFUSE_BLK0, 41, 1, [] Set this bit to disable Dcache
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, [] Set this bit to disable Icache in download mode (boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_DOWNLOAD_DCACHE, EFUSE_BLK0, 43, 1, [] Set this bit to disable Dcache in download mode ( boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, [] Set this bit to disable the function that forces chip into download mode
DIS_USB_OTG, EFUSE_BLK0, 45, 1, [DIS_USB] Set this bit to disable USB function
DIS_TWAI, EFUSE_BLK0, 46, 1, [DIS_CAN] Set this bit to disable CAN function
DIS_APP_CPU, EFUSE_BLK0, 47, 1, [] Disable app cpu
SOFT_DIS_JTAG, EFUSE_BLK0, 48, 3, [] Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module
DIS_PAD_JTAG, EFUSE_BLK0, 51, 1, [HARD_DIS_JTAG] Set this bit to disable JTAG in the hard way. JTAG is disabled permanently
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 52, 1, [] Set this bit to disable flash encryption when in download boot modes
USB_EXCHG_PINS, EFUSE_BLK0, 57, 1, [] Set this bit to exchange USB D+ and D- pins
USB_EXT_PHY_ENABLE, EFUSE_BLK0, 58, 1, [EXT_PHY_ENABLE] Set this bit to enable external PHY
VDD_SPI_XPD, EFUSE_BLK0, 68, 1, [] SPI regulator power up signal
VDD_SPI_TIEH, EFUSE_BLK0, 69, 1, [] If VDD_SPI_FORCE is 1; determines VDD_SPI voltage {0: "VDD_SPI connects to 1.8 V LDO"; 1: "VDD_SPI connects to VDD3P3_RTC_IO"}
VDD_SPI_FORCE, EFUSE_BLK0, 70, 1, [] Set this bit and force to use the configuration of eFuse to configure VDD_SPI
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, [] RTC watchdog timeout threshold; in unit of slow clock cycle {0: "40000"; 1: "80000"; 2: "160000"; 3: "320000"}
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, [] Enables flash encryption when 1 or 3 bits are set and disabled otherwise {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"}
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, [] Revoke 1st secure boot key
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, [] Revoke 2nd secure boot key
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, [] Revoke 3rd secure boot key
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, [KEY0_PURPOSE] Purpose of Key0
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, [KEY1_PURPOSE] Purpose of Key1
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, [KEY2_PURPOSE] Purpose of Key2
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, [KEY3_PURPOSE] Purpose of Key3
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, [KEY4_PURPOSE] Purpose of Key4
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, [KEY5_PURPOSE] Purpose of Key5
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, [] Set this bit to enable secure boot
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, [] Set this bit to enable revoking aggressive secure boot
DIS_USB_JTAG, EFUSE_BLK0, 118, 1, [] Set this bit to disable function of usb switch to jtag in module of usb device
DIS_USB_SERIAL_JTAG, EFUSE_BLK0, 119, 1, [DIS_USB_DEVICE] Set this bit to disable usb device
STRAP_JTAG_SEL, EFUSE_BLK0, 120, 1, [] Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0
USB_PHY_SEL, EFUSE_BLK0, 121, 1, [] This bit is used to switch internal PHY and external PHY for USB OTG and USB Device {0: "internal PHY is assigned to USB Device while external PHY is assigned to USB OTG"; 1: "internal PHY is assigned to USB OTG while external PHY is assigned to USB Device"}
FLASH_TPUW, EFUSE_BLK0, 124, 4, [] Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value. Otherwise; the waiting time is twice the configurable value
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, [] Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 3; 6; 7)
DIS_DIRECT_BOOT, EFUSE_BLK0, 129, 1, [DIS_LEGACY_SPI_BOOT] Disable direct boot mode
DIS_USB_SERIAL_JTAG_ROM_PRINT, EFUSE_BLK0, 130, 1, [UART_PRINT_CHANNEL] USB printing {0: "Enable"; 1: "Disable"}
FLASH_ECC_MODE, EFUSE_BLK0, 131, 1, [] Flash ECC mode in ROM {0: "16to18 byte"; 1: "16to17 byte"}
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, [DIS_USB_DOWNLOAD_MODE] Set this bit to disable UART download mode through USB
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, [] Set this bit to enable secure UART download mode
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, [] Set the default UART boot message output mode {0: "Enable"; 1: "Enable when GPIO46 is low at reset"; 2: "Enable when GPIO46 is high at reset"; 3: "Disable"}
PIN_POWER_SELECTION, EFUSE_BLK0, 136, 1, [] Set default power supply for GPIO33-GPIO37; set when SPI flash is initialized {0: "VDD3P3_CPU"; 1: "VDD_SPI"}
FLASH_TYPE, EFUSE_BLK0, 137, 1, [] SPI flash type {0: "4 data lines"; 1: "8 data lines"}
FLASH_PAGE_SIZE, EFUSE_BLK0, 138, 2, [] Set Flash page size
FLASH_ECC_EN, EFUSE_BLK0, 140, 1, [] Set 1 to enable ECC for flash boot
FORCE_SEND_RESUME, EFUSE_BLK0, 141, 1, [] Set this bit to force ROM code to send a resume command during SPI boot
SECURE_VERSION, EFUSE_BLK0, 142, 16, [] Secure version (used by ESP-IDF anti-rollback feature)
DIS_USB_OTG_DOWNLOAD_MODE, EFUSE_BLK0, 159, 1, [] Set this bit to disable download through USB-OTG
DISABLE_WAFER_VERSION_MAJOR, EFUSE_BLK0, 160, 1, [] Disables check of wafer version major
DISABLE_BLK_VERSION_MAJOR, EFUSE_BLK0, 161, 1, [] Disables check of blk version major
MAC_FACTORY, EFUSE_BLK1, 0, 48, [MAC_FACTORY] MAC address
SPI_PAD_CONFIG_CLK, EFUSE_BLK1, 48, 6, [] SPI_PAD_configure CLK
SPI_PAD_CONFIG_Q, EFUSE_BLK1, 54, 6, [] SPI_PAD_configure Q(D1)
SPI_PAD_CONFIG_D, EFUSE_BLK1, 60, 6, [] SPI_PAD_configure D(D0)
SPI_PAD_CONFIG_CS, EFUSE_BLK1, 66, 6, [] SPI_PAD_configure CS
SPI_PAD_CONFIG_HD, EFUSE_BLK1, 72, 6, [] SPI_PAD_configure HD(D3)
SPI_PAD_CONFIG_WP, EFUSE_BLK1, 78, 6, [] SPI_PAD_configure WP(D2)
SPI_PAD_CONFIG_DQS, EFUSE_BLK1, 84, 6, [] SPI_PAD_configure DQS
SPI_PAD_CONFIG_D4, EFUSE_BLK1, 90, 6, [] SPI_PAD_configure D4
SPI_PAD_CONFIG_D5, EFUSE_BLK1, 96, 6, [] SPI_PAD_configure D5
SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, [] SPI_PAD_configure D6
SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, [] SPI_PAD_configure D7
WAFER_VERSION_MINOR_LO, EFUSE_BLK1, 114, 3, [] WAFER_VERSION_MINOR least significant bits
PKG_VERSION, EFUSE_BLK1, 117, 3, [] Package version
BLK_VERSION_MINOR, EFUSE_BLK1, 120, 3, [] BLK_VERSION_MINOR
K_RTC_LDO, EFUSE_BLK1, 141, 7, [] BLOCK1 K_RTC_LDO
K_DIG_LDO, EFUSE_BLK1, 148, 7, [] BLOCK1 K_DIG_LDO
V_RTC_DBIAS20, EFUSE_BLK1, 155, 8, [] BLOCK1 voltage of rtc dbias20
V_DIG_DBIAS20, EFUSE_BLK1, 163, 8, [] BLOCK1 voltage of digital dbias20
DIG_DBIAS_HVT, EFUSE_BLK1, 171, 5, [] BLOCK1 digital dbias when hvt
WAFER_VERSION_MINOR_HI, EFUSE_BLK1, 183, 1, [] WAFER_VERSION_MINOR most significant bit
WAFER_VERSION_MAJOR, EFUSE_BLK1, 184, 2, [] WAFER_VERSION_MAJOR
ADC2_CAL_VOL_ATTEN3, EFUSE_BLK1, 186, 6, [] ADC2 calibration voltage at atten3
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, [] Optional unique 128-bit ID
BLK_VERSION_MAJOR, EFUSE_BLK2, 128, 2, [] BLK_VERSION_MAJOR of BLOCK2 {0: "No calib"; 1: "ADC calib V1"}
TEMP_CALIB, EFUSE_BLK2, 132, 9, [] Temperature calibration data
OCODE, EFUSE_BLK2, 141, 8, [] ADC OCode
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 149, 8, [] ADC1 init code at atten0
ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 157, 6, [] ADC1 init code at atten1
ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 163, 6, [] ADC1 init code at atten2
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 169, 6, [] ADC1 init code at atten3
ADC2_INIT_CODE_ATTEN0, EFUSE_BLK2, 175, 8, [] ADC2 init code at atten0
ADC2_INIT_CODE_ATTEN1, EFUSE_BLK2, 183, 6, [] ADC2 init code at atten1
ADC2_INIT_CODE_ATTEN2, EFUSE_BLK2, 189, 6, [] ADC2 init code at atten2
ADC2_INIT_CODE_ATTEN3, EFUSE_BLK2, 195, 6, [] ADC2 init code at atten3
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 201, 8, [] ADC1 calibration voltage at atten0
ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 209, 8, [] ADC1 calibration voltage at atten1
ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 217, 8, [] ADC1 calibration voltage at atten2
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 225, 8, [] ADC1 calibration voltage at atten3
ADC2_CAL_VOL_ATTEN0, EFUSE_BLK2, 233, 8, [] ADC2 calibration voltage at atten0
ADC2_CAL_VOL_ATTEN1, EFUSE_BLK2, 241, 7, [] ADC2 calibration voltage at atten1
ADC2_CAL_VOL_ATTEN2, EFUSE_BLK2, 248, 7, [] ADC2 calibration voltage at atten2
USER_DATA, EFUSE_BLK3, 0, 256, [BLOCK_USR_DATA] User data
USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, [MAC_CUSTOM CUSTOM_MAC] Custom MAC
KEY0, EFUSE_BLK4, 0, 256, [BLOCK_KEY0] Key0 or user data
KEY1, EFUSE_BLK5, 0, 256, [BLOCK_KEY1] Key1 or user data
KEY2, EFUSE_BLK6, 0, 256, [BLOCK_KEY2] Key2 or user data
KEY3, EFUSE_BLK7, 0, 256, [BLOCK_KEY3] Key3 or user data
KEY4, EFUSE_BLK8, 0, 256, [BLOCK_KEY4] Key4 or user data
KEY5, EFUSE_BLK9, 0, 256, [BLOCK_KEY5] Key5 or user data
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, [BLOCK_SYS_DATA2] System data part 2 (reserved)
Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -1,29 +0,0 @@
PROVIDE(ets_delay_us = 0x40008534);
PROVIDE(ets_update_cpu_frequency_rom = 0x40008550);
PROVIDE(rom_i2c_writeReg = 0x400041a4);
PROVIDE(rom_i2c_writeReg_Mask = 0x400041fc);
PROVIDE(rtc_get_reset_reason = 0x400081d4);
PROVIDE(software_reset = 0x4000824c);
PROVIDE(software_reset_cpu = 0x40008264);
PROVIDE ( ets_efuse_get_spiconfig = 0x40008658 );
PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig );
PROVIDE ( esp_rom_gpio_connect_out_signal = gpio_matrix_out );
PROVIDE ( gpio_matrix_out = 0x40009f0c );
PROVIDE ( gpio_matrix_in = 0x40009edc );
PROVIDE ( esp_rom_gpio_connect_in_signal = gpio_matrix_in );
PROVIDE ( esp_rom_spiflash_config_clk = 0x40062bc8 );
PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
PROVIDE ( g_rom_flashchip = 0x3ffae270 );
PROVIDE ( cache_sram_mmu_set_rom = 0x400097f4 );
PROVIDE (esp_rom_crc32_be = 0x4005d024);
PROVIDE (esp_rom_crc16_be = 0x4005d09c);
PROVIDE (esp_rom_crc8_be = 0x4005d114);
PROVIDE (esp_rom_crc32_le = 0x4005cfec);
PROVIDE (esp_rom_crc16_le = 0x4005d05c);
PROVIDE (esp_rom_crc8_le = 0x4005d0e0);
PROVIDE (esp_rom_md5_init = 0x4005da7c);
PROVIDE (esp_rom_md5_update = 0x4005da9c);
PROVIDE (esp_rom_md5_final = 0x4005db1c);

View File

@ -1,18 +0,0 @@
PROVIDE(ets_delay_us = 0x40000044);
PROVIDE(ets_update_cpu_frequency_rom = 0x40000774);
PROVIDE(rom_i2c_writeReg = 0x400022f4);
PROVIDE(rom_i2c_writeReg_Mask = 0x400022fc);
PROVIDE(rtc_get_reset_reason = 0x40000018);
PROVIDE(software_reset = 0x40000088);
PROVIDE(software_reset_cpu = 0x4000008c);
PROVIDE(esp_rom_crc32_be = 0x40000808);
PROVIDE(esp_rom_crc16_be = 0x4000080c);
PROVIDE(esp_rom_crc8_be = 0x40000810);
PROVIDE(esp_rom_crc32_le = 0x400007fc);
PROVIDE(esp_rom_crc16_le = 0x40000800);
PROVIDE(esp_rom_crc8_le = 0x40000804);
PROVIDE(esp_rom_mbedtls_md5_starts_ret = 0x40002be4);
PROVIDE(esp_rom_mbedtls_md5_update_ret = 0x40002be8);
PROVIDE(esp_rom_mbedtls_md5_finish_ret = 0x40002bec);

View File

@ -1,25 +0,0 @@
ets_printf = 0x40000040;
PROVIDE(esp_rom_printf = ets_printf);
PROVIDE(cache_invalidate_icache_all = 0x400004d8);
PROVIDE(cache_suspend_icache = 0x40000524);
PROVIDE(cache_resume_icache = 0x40000528);
PROVIDE(cache_ibus_mmu_set = 0x40000560);
PROVIDE(cache_dbus_mmu_set = 0x40000564);
PROVIDE(ets_delay_us = 0x40000050);
PROVIDE(ets_update_cpu_frequency_rom = 0x40000588);
PROVIDE(rom_i2c_writeReg = 0x4000195c);
PROVIDE(rom_i2c_writeReg_Mask = 0x40001960);
PROVIDE(rtc_get_reset_reason = 0x40000018);
PROVIDE(software_reset = 0x40000090);
PROVIDE(software_reset_cpu = 0x40000094);
PROVIDE(esp_rom_crc32_be = 0x4000062c);
PROVIDE(esp_rom_crc16_be = 0x40000634);
PROVIDE(esp_rom_crc8_be = 0x4000063c);
PROVIDE(esp_rom_crc32_le = 0x40000628);
PROVIDE(esp_rom_crc16_le = 0x40000630);
PROVIDE(esp_rom_crc8_le = 0x40000638);
PROVIDE(esp_rom_md5_init = 0x40000614);
PROVIDE(esp_rom_md5_update = 0x40000618);
PROVIDE(esp_rom_md5_final = 0x4000061c);

View File

@ -1,25 +0,0 @@
ets_printf = 0x40000028;
ets_update_cpu_frequency = ets_update_cpu_frequency_rom;
PROVIDE(esp_rom_printf = ets_printf);
PROVIDE(cache_invalidate_icache_all = 0x4000064c);
PROVIDE(cache_suspend_icache = 0x40000698);
PROVIDE(cache_resume_icache = 0x4000069c);
/* TODO PROVIDE(cache_ibus_mmu_set = 0x40000560); */
/* TODO PROVIDE(cache_dbus_mmu_set = 0x40000564); */
PROVIDE(ets_delay_us = 0x40000040);
PROVIDE(ets_update_cpu_frequency_rom = 0x40000048);
PROVIDE(rtc_get_reset_reason = 0x40000018);
ets_update_cpu_frequency = 0x40000048;
PROVIDE(software_reset = 0x40000090);
PROVIDE(software_reset_cpu = 0x40000094);
PROVIDE(esp_rom_crc32_be = 0x40000764);
PROVIDE(esp_rom_crc16_be = 0x40000768);
PROVIDE(esp_rom_crc8_be = 0x4000076c);
PROVIDE(esp_rom_crc32_le = 0x40000758);
PROVIDE(esp_rom_crc16_le = 0x4000075c);
PROVIDE(esp_rom_crc8_le = 0x40000760);
PROVIDE(esp_rom_md5_init = 0x4000074c);
PROVIDE(esp_rom_md5_update = 0x40000750);
PROVIDE(esp_rom_md5_final = 0x40000754);

View File

@ -1,25 +0,0 @@
ets_printf = 0x40000028;
ets_update_cpu_frequency = ets_update_cpu_frequency_rom;
PROVIDE(esp_rom_printf = ets_printf);
PROVIDE(cache_invalidate_icache_all = 0x40000620);
PROVIDE(cache_suspend_icache = 0x4000066c);
PROVIDE(cache_resume_icache = 0x40000670);
/* TODO PROVIDE(cache_ibus_mmu_set = 0x40000560); */
/* TODO PROVIDE(cache_dbus_mmu_set = 0x40000564); */
PROVIDE(ets_delay_us = 0x40000040);
PROVIDE(ets_update_cpu_frequency_rom = 0x40000048);
PROVIDE(rtc_get_reset_reason = 0x40000018);
ets_update_cpu_frequency = 0x40000048;
PROVIDE(software_reset = 0x40000090);
PROVIDE(software_reset_cpu = 0x40000094);
PROVIDE(esp_rom_crc32_be = 0x40000730);
PROVIDE(esp_rom_crc16_be = 0x40000734);
PROVIDE(esp_rom_crc8_be = 0x40000738);
PROVIDE(esp_rom_crc32_le = 0x40000724);
PROVIDE(esp_rom_crc16_le = 0x40000728);
PROVIDE(esp_rom_crc8_le = 0x4000072c);
PROVIDE(esp_rom_md5_init = 0x40000718);
PROVIDE(esp_rom_md5_update = 0x4000071c);
PROVIDE(esp_rom_md5_final = 0x40000720);

View File

@ -1,29 +0,0 @@
PROVIDE(ets_delay_us = 0x4000d888);
PROVIDE(ets_update_cpu_frequency_rom = 0x4000d8a4);
PROVIDE(rom_i2c_writeReg = 0x4000a9a8);
PROVIDE(rom_i2c_writeReg_Mask = 0x4000aa00);
PROVIDE(rtc_get_reset_reason = 0x4000ff58);
PROVIDE(software_reset = 0x40010068);
PROVIDE(software_reset_cpu = 0x40010080);
PROVIDE ( cache_dbus_mmu_set = 0x40018eb0 );
PROVIDE ( Cache_Allocate_SRAM = 0x40018d6c );
PROVIDE ( Cache_Invalidate_DCache_All = 0x4001842c );
PROVIDE ( Cache_Set_DCache_Mode = 0x40018074 );
PROVIDE ( ets_efuse_get_spiconfig = 0x4000e4a0 );
PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig );
PROVIDE ( esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad );
PROVIDE ( ets_efuse_get_wp_pad = 0x4000e444 );
PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO );
PROVIDE ( SelectSpiQIO = 0x40015b88 );
PROVIDE ( esp_rom_spi_set_op_mode = 0x400179e8 );
PROVIDE ( esp_rom_spi_cmd_start = 0x40017ba8 );
PROVIDE ( esp_rom_spi_cmd_config = 0x40017c58 );
PROVIDE(esp_rom_crc32_le = 0x400119dc);
PROVIDE(esp_rom_crc16_le = 0x40011a10);
PROVIDE(esp_rom_crc8_le = 0x40011a4c);
PROVIDE(esp_rom_md5_final = 0x4000530c);
PROVIDE(esp_rom_md5_init = 0x4000526c);
PROVIDE(esp_rom_md5_update = 0x4000528c);

View File

@ -1,36 +0,0 @@
PROVIDE(ets_delay_us = 0x40000600);
PROVIDE(ets_update_cpu_frequency_rom = 0x40043164);
PROVIDE(rom_i2c_writeReg = 0x40005d60);
PROVIDE(rom_i2c_writeReg_Mask = 0x40005d6c);
PROVIDE(rtc_get_reset_reason = 0x4000057c);
PROVIDE(rom_config_instruction_cache_mode = 0x40001a1c);
PROVIDE(software_reset = 0x400006d8);
PROVIDE(software_reset_cpu = 0x400006e4);
PROVIDE(cache_dbus_mmu_set = 0x400019b0);
PROVIDE(ets_efuse_get_spiconfig = 0x40001f74);
PROVIDE(esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig);
PROVIDE(esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad);
PROVIDE(esp_rom_spiflash_select_qio_pins = 0x40000a68 );
PROVIDE(esp_rom_spi_set_op_mode = 0x400008a0 );
PROVIDE(esp_rom_spi_cmd_start = 0x40000888);
PROVIDE(esp_rom_spi_cmd_config = 0x4000087c);
PROVIDE(Cache_Suspend_DCache = 0x400018b4 );
PROVIDE(Cache_Resume_DCache = 0x400018c0 );
PROVIDE(rom_config_data_cache_mode = 0x40001a28 );
PROVIDE(rom_config_instruction_cache_mode = 0x40001a1c );
PROVIDE(ets_efuse_get_wp_pad = 0x40001fa4);
PROVIDE(esp_rom_crc32_be = 0x40001ca4);
PROVIDE(esp_rom_crc16_be = 0x40001cbc);
PROVIDE(esp_rom_crc8_be = 0x40001cd4);
PROVIDE(esp_rom_crc32_le = 0x40001c98);
PROVIDE(esp_rom_crc16_le = 0x40001cb0);
PROVIDE(esp_rom_crc8_le = 0x40001cc8);
PROVIDE(esp_rom_md5_init = 0x40001c5c);
PROVIDE(esp_rom_md5_update = 0x40001c68);
PROVIDE(esp_rom_md5_final = 0x40001c74);
PROVIDE (esp_rom_opiflash_exec_cmd = 0x400008b8);
PROVIDE( esp_rom_spi_set_dtr_swap_mode = 0x4000093c );
PROVIDE( esp_rom_opiflash_pin_config = 0x40000894 );

View File

@ -1,10 +0,0 @@
SECTIONS {
.text : ALIGN(4)
{
*(.literal .text .literal.* .text.*)
} > ROTEXT
}

View File

@ -1,563 +0,0 @@
//! # Advanced Encryption Standard (AES) support.
//!
//! ## Overview
//!
//! The AES module provides an interface to interact with the AES peripheral,
//! provides encryption and decryption capabilities for ESP chips using the AES
//! algorithm. We currently support the following AES encryption modes:
//!
//! * AES-128
//! * AES-192
//! * AES-256
//!
//! ## Example
//!
//! ### Initialization
//!
//! ```no_run
//! let mut aes = Aes::new(peripherals.AES);
//! ```
//!
//! ### Creating key and block Buffer
//!
//! ```no_run
//! let keytext = "SUp4SeCp@sSw0rd".as_bytes();
//! let plaintext = "message".as_bytes();
//!
//! // create an array with aes128 key size
//! let mut keybuf = [0_u8; 16];
//! keybuf[..keytext.len()].copy_from_slice(keytext);
//!
//! // create an array with aes block size
//! let mut block_buf = [0_u8; 16];
//! block_buf[..plaintext.len()].copy_from_slice(plaintext);
//! ```
//!
//! ### Encrypting and Decrypting (using hardware)
//!
//! ```no_run
//! let mut block = block_buf.clone();
//! aes.process(&mut block, Mode::Encryption128, &keybuf);
//! let hw_encrypted = block.clone();
//!
//! aes.process(&mut block, Mode::Decryption128, &keybuf);
//! let hw_decrypted = block;
//! ```
//!
//! ### Encrypting and Decrypting (using software)
//!
//! ```no_run
//! let key = GenericArray::from(keybuf);
//!
//! let mut block = GenericArray::from(block_buf);
//! let cipher = Aes128SW::new(&key);
//! cipher.encrypt_block(&mut block);
//!
//! let sw_encrypted = block.clone();
//! cipher.decrypt_block(&mut block);
//!
//! let sw_decrypted = block;
//! ```
//!
//! ### Implementation State
//!
//! * DMA mode is currently not supported on ESP32 and ESP32S2 ⚠️
//!
//! ## DMA-AES Mode
//!
//! Supports 6 block cipher modes including `ECB/CBC/OFB/CTR/CFB8/CFB128`.
//!
//! * Initialization vector (IV) is currently not supported ⚠️
//!
//! ## Example
//!
//! ### Initialization
//!
//! ```no_run
//! let dma = Gdma::new(peripherals.DMA);
//! let dma_channel = dma.channel0;
//!
//! let mut descriptors = [0u32; 8 * 3];
//! let mut rx_descriptors = [0u32; 8 * 3];
//!
//! let aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure(
//! false,
//! &mut descriptors,
//! &mut rx_descriptors,
//! DmaPriority::Priority0,
//! ));
//! ```
//!
//! ### Operation
//!
//! ```no_run
//! let transfer = aes
//! .process(
//! plaintext,
//! hw_encrypted,
//! Mode::Encryption128,
//! CipherMode::Ecb,
//! keybuf,
//! )
//! .unwrap();
//! let (hw_encrypted, plaintext, aes) = transfer.wait().unwrap();
//! ```
#[cfg(esp32)]
use crate::peripherals::generic::{Readable, Reg, RegisterSpec};
#[cfg(not(esp32))]
use crate::reg_access::AlignmentHelper;
use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::AES,
};
#[cfg_attr(esp32, path = "esp32.rs")]
#[cfg_attr(esp32s3, path = "esp32s3.rs")]
#[cfg_attr(esp32s2, path = "esp32s2.rs")]
#[cfg_attr(esp32c3, path = "esp32cX.rs")]
#[cfg_attr(esp32c6, path = "esp32cX.rs")]
#[cfg_attr(esp32h2, path = "esp32cX.rs")]
mod aes_spec_impl;
const ALIGN_SIZE: usize = core::mem::size_of::<u32>();
pub enum Mode {
Encryption128 = 0,
Encryption256 = 2,
Decryption128 = 4,
Decryption256 = 6,
}
/// AES peripheral container
pub struct Aes<'d> {
aes: PeripheralRef<'d, AES>,
#[cfg(not(esp32))]
alignment_helper: AlignmentHelper,
}
impl<'d> Aes<'d> {
pub fn new(aes: impl Peripheral<P = AES> + 'd) -> Self {
crate::into_ref!(aes);
let mut ret = Self {
aes: aes,
#[cfg(not(esp32))]
alignment_helper: AlignmentHelper::default(),
};
ret.init();
ret
}
/// Encrypts/Decrypts the given buffer based on `mode` parameter
pub fn process(&mut self, block: &mut [u8; 16], mode: Mode, key: &[u8; 16]) {
self.write_key(key);
self.set_mode(mode as u8);
self.set_block(block);
self.start();
while !(self.is_idle()) {}
self.get_block(block);
}
fn set_mode(&mut self, mode: u8) {
self.write_mode(mode as u32);
}
fn is_idle(&mut self) -> bool {
self.read_idle()
}
fn set_block(&mut self, block: &[u8; 16]) {
self.write_block(block);
}
fn get_block(&self, block: &mut [u8; 16]) {
self.read_block(block);
}
fn start(&mut self) {
self.write_start();
}
// TODO: for some reason, the `volatile read/write` helpers from `reg_access`
// don't work for ESP32
#[cfg(esp32)]
fn write_to_regset(input: &[u8], n_offset: usize, reg_0: *mut u32) {
let chunks = input.chunks_exact(ALIGN_SIZE);
for (offset, chunk) in (0..n_offset).zip(chunks) {
let to_write = u32::from_ne_bytes(chunk.try_into().unwrap());
unsafe {
let p = reg_0.add(offset);
p.write_volatile(to_write);
}
}
}
// TODO: for some reason, the `volatile read/write` helpers from `reg_access`
// don't work for ESP32
#[cfg(esp32)]
fn read_from_regset<T>(out_buf: &mut [u8], n_offset: usize, reg_0: &Reg<T>)
where
T: RegisterSpec<Ux = u32> + Readable,
{
let chunks = out_buf.chunks_exact_mut(ALIGN_SIZE);
for (offset, chunk) in (0..n_offset).zip(chunks) {
unsafe {
let p = reg_0.as_ptr().add(offset);
let read_val: [u8; ALIGN_SIZE] = p.read_volatile().to_ne_bytes();
chunk.copy_from_slice(&read_val);
}
}
}
}
mod sealed {
/// Specifications for AES flavours
pub trait AesFlavour {
type KeyType<'b>;
const ENCRYPT_MODE: u32;
const DECRYPT_MODE: u32;
}
}
use sealed::AesFlavour;
/// Marker type for AES-128
pub struct Aes128;
/// Marker type for AES-192
#[cfg(any(esp32, esp32s2))]
pub struct Aes192;
/// Marker type for AES-256
pub struct Aes256;
/// State matrix endianness
#[cfg(any(esp32, esp32s2))]
pub enum Endianness {
BigEndian = 1,
LittleEndian = 0,
}
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
pub mod dma {
use core::mem;
use embedded_dma::{ReadBuffer, WriteBuffer};
use crate::{
aes::Mode,
dma::{
AesPeripheral,
Channel,
ChannelTypes,
DmaError,
DmaPeripheral,
DmaTransferRxTx,
RxPrivate,
TxPrivate,
},
};
const ALIGN_SIZE: usize = core::mem::size_of::<u32>();
pub enum CipherMode {
Ecb = 0,
Cbc,
Ofb,
Ctr,
Cfb8,
Cfb128,
}
/// A DMA capable AES instance.
pub struct AesDma<'d, C>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
pub aes: super::Aes<'d>,
pub(crate) channel: Channel<'d, C>,
}
pub trait WithDmaAes<'d, C>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
fn with_dma(self, channel: Channel<'d, C>) -> AesDma<'d, C>;
}
impl<'d, C> WithDmaAes<'d, C> for crate::aes::Aes<'d>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
fn with_dma(self, mut channel: Channel<'d, C>) -> AesDma<'d, C> {
channel.tx.init_channel(); // no need to call this for both, TX and RX
AesDma { aes: self, channel }
}
}
/// An in-progress DMA transfer
pub struct AesDmaTransferRxTx<'d, C, RBUFFER, TBUFFER>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
aes_dma: AesDma<'d, C>,
rbuffer: RBUFFER,
tbuffer: TBUFFER,
}
impl<'d, C, RXBUF, TXBUF> DmaTransferRxTx<RXBUF, TXBUF, AesDma<'d, C>>
for AesDmaTransferRxTx<'d, C, RXBUF, TXBUF>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
/// Wait for the DMA transfer to complete and return the buffers and the
/// AES instance.
fn wait(
self,
) -> Result<(RXBUF, TXBUF, AesDma<'d, C>), (DmaError, RXBUF, TXBUF, AesDma<'d, C>)>
{
// Waiting for the DMA transfer is not enough. We need to wait for the
// peripheral to finish flushing its buffers, too.
while self.aes_dma.aes.aes.state().read().state().bits() != 2 // DMA status DONE == 2
&& !self.aes_dma.channel.tx.is_done()
{
// wait until done
}
self.aes_dma.finish_transform();
let err = self.aes_dma.channel.rx.has_error() || self.aes_dma.channel.tx.has_error();
// `DmaTransferRxTx` needs to have a `Drop` implementation, because we accept
// managed buffers that can free their memory on drop. Because of that
// we can't move out of the `DmaTransferRxTx`'s fields, so we use `ptr::read`
// and `mem::forget`.
//
// NOTE(unsafe) There is no panic branch between getting the resources
// and forgetting `self`.
unsafe {
let rbuffer = core::ptr::read(&self.rbuffer);
let tbuffer = core::ptr::read(&self.tbuffer);
let payload = core::ptr::read(&self.aes_dma);
mem::forget(self);
if err {
Err((DmaError::DescriptorError, rbuffer, tbuffer, payload))
} else {
Ok((rbuffer, tbuffer, payload))
}
}
}
/// Check if the DMA transfer is complete
fn is_done(&self) -> bool {
let ch = &self.aes_dma.channel;
ch.tx.is_done() && ch.rx.is_done()
}
}
impl<'d, C, RXBUF, TXBUF> Drop for AesDmaTransferRxTx<'d, C, RXBUF, TXBUF>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
fn drop(&mut self) {
self.aes_dma
.aes
.aes
.dma_exit()
.write(|w| w.dma_exit().set_bit());
}
}
impl<'d, C> core::fmt::Debug for AesDma<'d, C>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("AesDma").finish()
}
}
impl<'d, C> AesDma<'d, C>
where
C: ChannelTypes,
C::P: AesPeripheral,
{
pub fn write_key(&mut self, key: &[u8]) {
debug_assert!(key.len() <= 8 * ALIGN_SIZE);
debug_assert_eq!(key.len() % ALIGN_SIZE, 0);
self.aes.write_key(key);
}
pub fn write_block(&mut self, block: &[u8]) {
debug_assert_eq!(block.len(), 4 * ALIGN_SIZE);
self.aes.write_key(block);
}
/// Perform a DMA transfer.
///
/// This will return a [AesDmaTransferRxTx] owning the buffer(s) and the
/// AES instance. The maximum amount of data to be sent/received
/// is 32736 bytes.
pub fn process<TXBUF, RXBUF>(
mut self,
words: TXBUF,
mut read_buffer: RXBUF,
mode: Mode,
cipher_mode: CipherMode,
key: [u8; 16],
) -> Result<AesDmaTransferRxTx<'d, C, RXBUF, TXBUF>, crate::dma::DmaError>
where
TXBUF: ReadBuffer<Word = u8>,
RXBUF: WriteBuffer<Word = u8>,
{
let (write_ptr, write_len) = unsafe { words.read_buffer() };
let (read_ptr, read_len) = unsafe { read_buffer.write_buffer() };
self.start_transfer_dma(
write_ptr,
write_len,
read_ptr,
read_len,
mode,
cipher_mode,
key,
)?;
Ok(AesDmaTransferRxTx {
aes_dma: self,
rbuffer: read_buffer,
tbuffer: words,
})
}
fn start_transfer_dma<'w>(
&mut self,
write_buffer_ptr: *const u8,
write_buffer_len: usize,
read_buffer_ptr: *mut u8,
read_buffer_len: usize,
mode: Mode,
cipher_mode: CipherMode,
key: [u8; 16],
) -> Result<(), crate::dma::DmaError> {
// AES has to be restarted after each calculation
self.reset_aes();
self.channel.tx.is_done();
self.channel.rx.is_done();
self.channel
.tx
.prepare_transfer_without_start(
self.dma_peripheral(),
false,
write_buffer_ptr,
write_buffer_len,
)
.and_then(|_| self.channel.tx.start_transfer())?;
self.channel
.rx
.prepare_transfer_without_start(
false,
self.dma_peripheral(),
read_buffer_ptr,
read_buffer_len,
)
.and_then(|_| self.channel.rx.start_transfer())?;
self.enable_dma(true);
self.enable_interrupt();
self.set_mode(mode);
self.set_cipher_mode(cipher_mode);
self.write_key(&key);
// TODO: verify 16?
self.set_num_block(16);
self.start_transform();
Ok(())
}
#[cfg(any(esp32c3, esp32s3))]
pub fn reset_aes(&self) {
unsafe {
let s = crate::peripherals::SYSTEM::steal();
s.perip_rst_en1()
.modify(|_, w| w.crypto_aes_rst().set_bit());
s.perip_rst_en1()
.modify(|_, w| w.crypto_aes_rst().clear_bit());
}
}
#[cfg(any(esp32c6, esp32h2))]
pub fn reset_aes(&self) {
unsafe {
let s = crate::peripherals::PCR::steal();
s.aes_conf().modify(|_, w| w.aes_rst_en().set_bit());
s.aes_conf().modify(|_, w| w.aes_rst_en().clear_bit());
}
}
fn dma_peripheral(&self) -> DmaPeripheral {
DmaPeripheral::Aes
}
fn enable_dma(&self, enable: bool) {
self.aes
.aes
.dma_enable()
.write(|w| w.dma_enable().bit(enable));
}
fn enable_interrupt(&self) {
self.aes.aes.int_ena().write(|w| w.int_ena().set_bit());
}
pub fn set_cipher_mode(&self, mode: CipherMode) {
self.aes
.aes
.block_mode()
.modify(|_, w| unsafe { w.bits(mode as u32) });
if self.aes.aes.block_mode().read().block_mode().bits() == CipherMode::Ctr as u8 {
self.aes
.aes
.inc_sel()
.modify(|_, w| w.inc_sel().clear_bit());
}
}
pub fn set_mode(&self, mode: Mode) {
self.aes
.aes
.mode()
.modify(|_, w| w.mode().variant(mode as u8));
}
fn start_transform(&self) {
self.aes.aes.trigger().write(|w| w.trigger().set_bit());
}
pub fn finish_transform(&self) {
self.aes.aes.dma_exit().write(|w| w.dma_exit().set_bit());
self.enable_dma(false);
}
fn set_num_block(&self, block: u32) {
self.aes
.aes
.block_num()
.modify(|_, w| unsafe { w.block_num().bits(block) });
}
}
}

View File

@ -1,505 +0,0 @@
use core::marker::PhantomData;
use embedded_hal::adc::{Channel, OneShot};
pub use crate::analog::{ADC1, ADC2};
use crate::{
peripheral::PeripheralRef,
peripherals::{RTC_IO, SENS},
};
/// The sampling/readout resolution of the ADC
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum Resolution {
Resolution9Bit = 0b00,
Resolution10Bit = 0b01,
Resolution11Bit = 0b10,
Resolution12Bit = 0b11,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum Attenuation {
Attenuation0dB = 0b00,
Attenuation2p5dB = 0b01,
Attenuation6dB = 0b10,
Attenuation11dB = 0b11,
}
pub struct AdcPin<PIN, ADCI> {
pub pin: PIN,
_phantom: PhantomData<ADCI>,
}
impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
type ID = u8;
fn channel() -> Self::ID {
PIN::channel()
}
}
pub struct AdcConfig<ADCI> {
pub resolution: Resolution,
pub attenuations: [Option<Attenuation>; 10],
_phantom: PhantomData<ADCI>,
}
impl<ADCI> AdcConfig<ADCI>
where
ADCI: RegisterAccess,
{
pub fn new() -> AdcConfig<ADCI> {
crate::into_ref!();
Self::default()
}
pub fn enable_pin<PIN: Channel<ADCI, ID = u8>>(
&mut self,
pin: PIN,
attenuation: Attenuation,
) -> AdcPin<PIN, ADCI> {
self.attenuations[PIN::channel() as usize] = Some(attenuation);
AdcPin {
pin,
_phantom: PhantomData::default(),
}
}
}
impl<ADCI> Default for AdcConfig<ADCI> {
fn default() -> Self {
AdcConfig {
resolution: Resolution::Resolution12Bit,
attenuations: [None; 10],
_phantom: PhantomData::default(),
}
}
}
pub trait RegisterAccess {
fn set_bit_width(resolution: u8);
fn set_sample_bit(resolution: u8);
fn set_attenuation(channel: usize, attenuation: u8);
fn clear_dig_force();
fn set_start_force();
fn set_en_pad_force();
fn set_en_pad(channel: u8);
fn clear_start_sar();
fn set_start_sar();
fn read_done_sar() -> bool;
fn read_data_sar() -> u16;
}
#[doc(hidden)]
impl RegisterAccess for ADC1 {
fn set_bit_width(resolution: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_start_force()
.modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) });
}
fn set_sample_bit(resolution: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_read_ctrl()
.modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) });
}
fn set_attenuation(channel: usize, attenuation: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors.sar_atten1().modify(|r, w| {
let new_value = (r.bits() & !(0b11 << (channel * 2)))
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
unsafe { w.sar1_atten().bits(new_value) }
});
}
fn clear_dig_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_read_ctrl()
.modify(|_, w| w.sar1_dig_force().clear_bit());
}
fn set_start_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.modify(|_, w| w.meas1_start_force().set_bit());
}
fn set_en_pad_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.modify(|_, w| w.sar1_en_pad_force().set_bit());
}
fn set_en_pad(channel: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
}
fn clear_start_sar() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.modify(|_, w| w.meas1_start_sar().clear_bit());
}
fn set_start_sar() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.modify(|_, w| w.meas1_start_sar().set_bit());
}
fn read_done_sar() -> bool {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start1()
.read()
.meas1_done_sar()
.bit_is_set()
}
fn read_data_sar() -> u16 {
let sensors = unsafe { &*SENS::ptr() };
sensors.sar_meas_start1().read().meas1_data_sar().bits() as u16
}
}
impl RegisterAccess for ADC2 {
fn set_bit_width(resolution: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_start_force()
.modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) });
}
fn set_sample_bit(resolution: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_read_ctrl2()
.modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) });
}
fn set_attenuation(channel: usize, attenuation: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors.sar_atten2().modify(|r, w| {
let new_value = (r.bits() & !(0b11 << (channel * 2)))
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
unsafe { w.sar2_atten().bits(new_value) }
});
}
fn clear_dig_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_read_ctrl2()
.modify(|_, w| w.sar2_dig_force().clear_bit());
}
fn set_start_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.modify(|_, w| w.meas2_start_force().set_bit());
}
fn set_en_pad_force() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.modify(|_, w| w.sar2_en_pad_force().set_bit());
}
fn set_en_pad(channel: u8) {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
}
fn clear_start_sar() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.modify(|_, w| w.meas2_start_sar().clear_bit());
}
fn set_start_sar() {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.modify(|_, w| w.meas2_start_sar().set_bit());
}
fn read_done_sar() -> bool {
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_meas_start2()
.read()
.meas2_done_sar()
.bit_is_set()
}
fn read_data_sar() -> u16 {
let sensors = unsafe { &*SENS::ptr() };
sensors.sar_meas_start2().read().meas2_data_sar().bits() as u16
}
}
pub struct ADC<'d, ADC> {
_adc: PeripheralRef<'d, ADC>,
attenuations: [Option<Attenuation>; 10],
active_channel: Option<u8>,
}
impl<'d, ADCI> ADC<'d, ADCI>
where
ADCI: RegisterAccess,
{
pub fn adc(
adc_instance: impl crate::peripheral::Peripheral<P = ADCI> + 'd,
config: AdcConfig<ADCI>,
) -> Result<Self, ()> {
let sensors = unsafe { &*SENS::ptr() };
// Set reading and sampling resolution
let resolution: u8 = config.resolution as u8;
ADCI::set_bit_width(resolution);
ADCI::set_sample_bit(resolution);
// Set attenuation for pins
let attenuations = config.attenuations;
for channel in 0..attenuations.len() {
if let Some(attenuation) = attenuations[channel] {
ADC1::set_attenuation(channel, attenuation as u8);
}
}
// Set controller to RTC
ADCI::clear_dig_force();
ADCI::set_start_force();
ADCI::set_en_pad_force();
sensors
.sar_touch_ctrl1()
.modify(|_, w| w.xpd_hall_force().set_bit());
sensors
.sar_touch_ctrl1()
.modify(|_, w| w.hall_phase_force().set_bit());
// Set power to SW power on
sensors
.sar_meas_wait2()
.modify(|_, w| unsafe { w.force_xpd_sar().bits(0b11) });
// disable AMP
sensors
.sar_meas_wait2()
.modify(|_, w| unsafe { w.force_xpd_amp().bits(0b10) });
sensors
.sar_meas_ctrl()
.modify(|_, w| unsafe { w.amp_rst_fb_fsm().bits(0) });
sensors
.sar_meas_ctrl()
.modify(|_, w| unsafe { w.amp_short_ref_fsm().bits(0) });
sensors
.sar_meas_ctrl()
.modify(|_, w| unsafe { w.amp_short_ref_gnd_fsm().bits(0) });
sensors
.sar_meas_wait1()
.modify(|_, w| unsafe { w.sar_amp_wait1().bits(1) });
sensors
.sar_meas_wait1()
.modify(|_, w| unsafe { w.sar_amp_wait2().bits(1) });
sensors
.sar_meas_wait2()
.modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
let adc = ADC {
_adc: adc_instance.into_ref(),
attenuations: config.attenuations,
active_channel: None,
};
Ok(adc)
}
}
impl<'d, ADC1> ADC<'d, ADC1> {
pub fn enable_hall_sensor() {
// Connect hall sensor
let rtcio = unsafe { &*RTC_IO::ptr() };
rtcio.hall_sens().modify(|_, w| w.xpd_hall().set_bit());
}
pub fn disable_hall_sensor() {
// Disconnect hall sensor
let rtcio = unsafe { &*RTC_IO::ptr() };
rtcio.hall_sens().modify(|_, w| w.xpd_hall().clear_bit());
}
}
impl<'d, ADCI, PIN> OneShot<ADCI, u16, AdcPin<PIN, ADCI>> for ADC<'d, ADCI>
where
PIN: Channel<ADCI, ID = u8>,
ADCI: RegisterAccess,
{
type Error = ();
fn read(&mut self, _pin: &mut AdcPin<PIN, ADCI>) -> nb::Result<u16, Self::Error> {
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
panic!(
"Channel {} is not configured reading!",
AdcPin::<PIN, ADCI>::channel()
);
}
if let Some(active_channel) = self.active_channel {
// There is conversion in progress:
// - if it's for a different channel try again later
// - if it's for the given channel, go ahead and check progress
if active_channel != AdcPin::<PIN, ADCI>::channel() {
return Err(nb::Error::WouldBlock);
}
} else {
// If no conversions are in progress, start a new one for given channel
self.active_channel = Some(AdcPin::<PIN, ADCI>::channel());
ADCI::set_en_pad(AdcPin::<PIN, ADCI>::channel() as u8);
ADCI::clear_start_sar();
ADCI::set_start_sar();
}
// Wait for ADC to finish conversion
let conversion_finished = ADCI::read_done_sar();
if !conversion_finished {
return Err(nb::Error::WouldBlock);
}
// Get converted value
let converted_value = ADCI::read_data_sar();
// Mark that no conversions are currently in progress
self.active_channel = None;
Ok(converted_value)
}
}
macro_rules! impl_adc_interface {
($adc:ident [
$( ($pin:ident, $channel:expr) ,)+
]) => {
$(
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
type ID = u8;
fn channel() -> u8 { $channel }
}
)+
}
}
pub use implementation::*;
mod implementation {
//! # Analog to digital (ADC) conversion support.
//!
//! ## Overview
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world
//! analog signals with high accuracy.
//!
//! This module provides functions for reading analog values from the
//! analog to digital converter available on the ESP32: `ADC1` and `ADC2`.
//!
//! The following pins can be configured for analog readout:
//!
//! | Channel | ADC1 | ADC2 |
//! |---------|----------------------|---------------|
//! | 0 | GPIO36 (SENSOR_VP) | GPIO4 |
//! | 1 | GPIO37 (SENSOR_CAPP) | GPIO0 |
//! | 2 | GPIO38 (SENSOR_CAPN) | GPIO2 |
//! | 3 | GPIO39 (SENSOR_VN) | GPIO15 (MTDO) |
//! | 4 | GPIO33 (32K_XP) | GPIO13 (MTCK) |
//! | 5 | GPIO32 (32K_XN) | GPIO12 (MTDI) |
//! | 6 | GPIO34 (VDET_1) | GPIO14 (MTMS) |
//! | 7 | GPIO35 (VDET_2) | GPIO27 |
//! | 8 | | GPIO25 |
//! | 9 | | GPIO26 |
//!
//! ## Example
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
use crate::analog::{ADC1, ADC2};
impl_adc_interface! {
ADC1 [
(Gpio36, 0), // Alt. name: SENSOR_VP
(Gpio37, 1), // Alt. name: SENSOR_CAPP
(Gpio38, 2), // Alt. name: SENSOR_CAPN
(Gpio39, 3), // Alt. name: SENSOR_VN
(Gpio33, 4), // Alt. name: 32K_XP
(Gpio32, 5), // Alt. name: 32K_XN
(Gpio34, 6), // Alt. name: VDET_1
(Gpio35, 7), // Alt. name: VDET_2
]
}
impl_adc_interface! {
ADC2 [
(Gpio4, 0),
(Gpio0, 1),
(Gpio2, 2),
(Gpio15, 3), // Alt. name: MTDO
(Gpio13, 4), // Alt. name: MTCK
(Gpio12, 5), // Alt. name: MTDI
(Gpio14, 6), // Alt. name: MTMS
(Gpio27, 7),
(Gpio25, 8),
(Gpio26, 9),
]
}
}

View File

@ -1,159 +0,0 @@
//! # Analog peripherals - Digital to Analog Converter
//!
//! ## Overview
//! The `DAC` module is part of the `Analog` driver designed for ESP
//! microcontrollers, providing functionalities for `digital-to-analog`
//! conversion.
//!
//! This module simplifies digital-to-analog conversion on ESP microcontrollers,
//! enabling precise control over analog output signals. Developers can choose
//! the `DAC` channel they want to use based on the GPIO pin assignments for
//! each channel. By providing a unified interface for DAC control, the module
//! makes it easier for users to generate accurate analog voltages in their
//! applications, such as audio generation, sensor calibration, and analog
//! signal synthesis.
use crate::peripherals::{RTC_IO, SENS};
pub trait DAC {
fn write(&mut self, value: u8);
}
trait DAC1Impl {
fn set_power(self) -> Self
where
Self: Sized,
{
#[cfg(esp32s2)]
{
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_dac_ctrl1()
.modify(|_, w| w.dac_clkgate_en().set_bit());
}
let rtcio = unsafe { &*RTC_IO::ptr() };
rtcio.pad_dac1().modify(|_, w| {
w.pdac1_dac_xpd_force().set_bit();
w.pdac1_xpd_dac().set_bit()
});
self
}
fn write(&mut self, value: u8) {
let rtcio = unsafe { &*RTC_IO::ptr() };
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_dac_ctrl2()
.modify(|_, w| w.dac_cw_en1().clear_bit());
rtcio
.pad_dac1()
.modify(|_, w| unsafe { w.pdac1_dac().bits(value) });
}
}
trait DAC2Impl {
fn set_power(self) -> Self
where
Self: Sized,
{
#[cfg(esp32s2)]
{
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_dac_ctrl1()
.modify(|_, w| w.dac_clkgate_en().set_bit());
}
let rtcio = unsafe { &*RTC_IO::ptr() };
rtcio.pad_dac2().modify(|_, w| {
w.pdac2_dac_xpd_force().set_bit();
w.pdac2_xpd_dac().set_bit()
});
self
}
fn write(&mut self, value: u8) {
let rtcio = unsafe { &*RTC_IO::ptr() };
let sensors = unsafe { &*SENS::ptr() };
sensors
.sar_dac_ctrl2()
.modify(|_, w| w.dac_cw_en2().clear_bit());
rtcio
.pad_dac2()
.modify(|_, w| unsafe { w.pdac2_dac().bits(value) });
}
}
macro_rules! impl_dac {
($($number:literal => $gpio:ident),+) => {
$(
paste::paste! {
use $crate::analog::dac::[<DAC $number Impl>];
#[doc = "DAC channel " $number]
pub struct [<DAC $number>]<'d, DAC> {
_dac: $crate::peripheral::PeripheralRef<'d, DAC>,
_private: ::core::marker::PhantomData<()>,
}
impl<'d, DAC> [<DAC $number Impl>] for [<DAC $number>]<'d, DAC> {}
impl<'d, DAC> [<DAC $number>]<'d, DAC> {
/// Constructs a new DAC instance
pub fn dac(
dac: impl $crate::peripheral::Peripheral<P = DAC> +'d,
_pin: $crate::gpio::$gpio<$crate::gpio::Analog>,
) -> Result<Self, ()> {
let dac = Self {
_dac: dac.into_ref(),
_private: ::core::marker::PhantomData,
}
.set_power();
Ok(dac)
}
/// Writes the given value
///
/// For each DAC channel, the output analog voltage can be calculated as follows:
/// DACn_OUT = VDD3P3_RTC * PDACn_DAC/256
pub fn write(&mut self, value: u8) {
[<DAC $number Impl>]::write(self, value)
}
}
}
)+
};
}
pub use implementation::*;
#[cfg(esp32)]
mod implementation {
//! Digital to analog (DAC) conversion.
//!
//! This module provides functions for controlling two digital to
//! analog converters, available on ESP32: `DAC1` and `DAC2`.
//!
//! The DAC1 is available on the GPIO pin 25, and DAC2 on pin 26.
impl_dac!(1 => Gpio25, 2 => Gpio26);
}
#[cfg(esp32s2)]
mod implementation {
//! Digital to analog (DAC) conversion.
//!
//! This module provides functions for controlling two digital to
//! analog converters, available on ESP32-S2: `DAC1` and `DAC2`.
//!
//! The DAC1 is available on the GPIO pin 17, and DAC2 on pin 18.
impl_dac!(1 => Gpio17, 2 => Gpio18);
}

View File

@ -1,260 +0,0 @@
//! # Analog peripherals
//!
//! ## Overview
//! The `Analog` Driver is a module designed for ESP microcontrollers, that
//! provides an interface to interact with analog peripherals on the chip. The
//! module includes support for `Analog-to-Digital Converters (ADC)` and
//! `Digital-to-Analog Converters (DAC)`, offering functionality for precise
//! analog measurements and generating analog output signals.
//!
//! The `ADC` module in the `analog` driver enables users to perform
//! analog-to-digital conversions, allowing them to measure real-world analog
//! signals with high accuracy. The module provides access to multiple ADC
//! units, such as `ADC1` and `ADC2`, which may differ based on the specific ESP
//! microcontroller being used.
//!
//! The `DAC` module in the `analog` driver enables users to generate
//! analog output signals with precise control over voltage levels. The module
//! supports multiple DAC units, such as `DAC1` and `DAC2`, which may vary
//! depending on the specific ESP microcontroller.
//!
//! #### Xtensa architecture
//! For ESP microcontrollers using the `Xtensa` architecture, the driver
//! provides access to the `SENS` peripheral, allowing users to split it into
//! independent parts using the [`AnalogExt`] trait. This extension trait
//! provides access to the following analog peripherals:
//! * ADC1
//! * ADC2
//! * DAC1
//! * DAC2
//!
//! #### RISC-V architecture
//! For ESP microcontrollers using the `RISC-V` architecture, the driver
//! provides access to the `APB_SARADC` peripheral. The `AnalogExt` trait allows
//! users to split this peripheral into independent parts, providing access to
//! the following analog peripheral:
//! * ADC1
//! * ADC2
//!
//! ## Examples
//! #### ADC on Risc-V architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.APB_SARADC.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
//! println!("PIN2 ADC reading = {}", pin_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
//! #### ADC on Xtensa architecture
//! ```no_run
//! // Create ADC instances
//! let analog = peripherals.SENS.split();
//!
//! let mut adc1_config = AdcConfig::new();
//!
//! let mut pin3 =
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
//!
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
//!
//! let mut delay = Delay::new(&clocks);
//!
//! loop {
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
//! println!("PIN3 ADC reading = {}", pin3_value);
//! delay.delay_ms(1500u32);
//! }
//! ```
#[cfg_attr(esp32, path = "adc/esp32.rs")]
#[cfg_attr(riscv, path = "adc/riscv.rs")]
#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")]
pub mod adc;
#[cfg(dac)]
pub mod dac;
/// A trait abstracting over calibration methods.
///
/// The methods in this trait are mostly for internal use. To get
/// calibrated ADC reads, all you need to do is call `enable_pin_with_cal`
/// and specify some implementor of this trait.
pub trait AdcCalScheme<ADCI>: Sized {
/// Create a new calibration scheme for the given attenuation.
fn new_cal(atten: adc::Attenuation) -> Self;
/// Return the basic ADC bias value. See [`adc::AdcCalBasic`] for
/// details.
fn adc_cal(&self) -> u16 {
0
}
/// Convert ADC value
fn adc_val(&self, val: u16) -> u16 {
val
}
}
impl<ADCI> AdcCalScheme<ADCI> for () {
fn new_cal(_atten: adc::Attenuation) -> Self {
()
}
}
/// A helper trait to get access to ADC calibration efuses
pub trait AdcCalEfuse {
/// Get ADC calibration init code
///
/// Returns digital value for zero voltage for a given attenuation
fn get_init_code(atten: adc::Attenuation) -> Option<u16>;
/// Get ADC calibration reference point voltage
///
/// Returns reference voltage (millivolts) for a given attenuation
fn get_cal_mv(atten: adc::Attenuation) -> u16;
/// Get ADC calibration reference point digital value
///
/// Returns digital value for reference voltage for a given attenuation
fn get_cal_code(atten: adc::Attenuation) -> Option<u16>;
}
pub struct ADC1 {
_private: (),
}
pub struct ADC2 {
_private: (),
}
pub struct DAC1 {
_private: (),
}
pub struct DAC2 {
_private: (),
}
impl core::ops::Deref for ADC1 {
type Target = ADC1;
fn deref(&self) -> &Self::Target {
self
}
}
impl core::ops::DerefMut for ADC1 {
fn deref_mut(&mut self) -> &mut Self::Target {
self
}
}
impl crate::peripheral::Peripheral for ADC1 {
type P = ADC1;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
ADC1 { _private: () }
}
}
impl crate::peripheral::sealed::Sealed for ADC1 {}
impl crate::peripheral::Peripheral for ADC2 {
type P = ADC2;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
ADC2 { _private: () }
}
}
impl crate::peripheral::sealed::Sealed for ADC2 {}
impl crate::peripheral::Peripheral for DAC1 {
type P = DAC1;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
DAC1 { _private: () }
}
}
impl crate::peripheral::sealed::Sealed for DAC1 {}
impl crate::peripheral::Peripheral for DAC2 {
type P = DAC2;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
DAC2 { _private: () }
}
}
impl crate::peripheral::sealed::Sealed for DAC2 {}
/// Extension trait to split a SENS peripheral in independent parts
pub trait AnalogExt {
fn split(self) -> AvailableAnalog;
}
cfg_if::cfg_if! {
if #[cfg(xtensa)] {
pub struct AvailableAnalog {
pub adc1: ADC1,
pub adc2: ADC2,
pub dac1: DAC1,
pub dac2: DAC2,
}
impl AnalogExt for crate::peripherals::SENS {
fn split(self) -> AvailableAnalog {
AvailableAnalog {
adc1: ADC1 {
_private: (),
},
adc2: ADC2 {
_private: (),
},
dac1: DAC1 {
_private: (),
},
dac2: DAC2 {
_private: (),
},
}
}
}
}
}
cfg_if::cfg_if! {
if #[cfg(riscv)] {
pub struct AvailableAnalog {
pub adc1: ADC1,
#[cfg(esp32c3)]
pub adc2: ADC2,
}
impl AnalogExt for crate::peripherals::APB_SARADC {
fn split(self) -> AvailableAnalog {
AvailableAnalog {
adc1: ADC1 {
_private: (),
},
#[cfg(esp32c3)]
adc2: ADC2 {
_private: (),
},
}
}
}
}
}

View File

@ -1,350 +0,0 @@
use crate::clock::{Clock, PllClock, XtalClock};
const REF_CLK_FREQ: u32 = 1000000;
const MHZ: u32 = 1000000;
const UINT16_MAX: u32 = 0xffff;
const RTC_CNTL_DBIAS_1V10: u32 = 4;
const RTC_CNTL_DBIAS_1V25: u32 = 7;
const DIG_DBIAS_80M_160M: u32 = RTC_CNTL_DBIAS_1V10;
const DIG_DBIAS_XTAL: u32 = RTC_CNTL_DBIAS_1V10;
const I2C_BBPLL: u32 = 0x66;
const I2C_BBPLL_HOSTID: u32 = 4;
const I2C_BBPLL_IR_CAL_DELAY: u32 = 0;
const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1;
const I2C_BBPLL_OC_ENB_FCAL: u32 = 4;
const I2C_BBPLL_OC_ENB_VCON: u32 = 10;
const I2C_BBPLL_BBADC_CAL_7_0: u32 = 12;
const BBPLL_IR_CAL_DELAY_VAL: u32 = 0x18;
const BBPLL_IR_CAL_EXT_CAP_VAL: u32 = 0x20;
const BBPLL_OC_ENB_FCAL_VAL: u32 = 0x9a;
const BBPLL_OC_ENB_VCON_VAL: u32 = 0x00;
const BBPLL_BBADC_CAL_7_0_VAL: u32 = 0x00;
const I2C_BBPLL_ENDIV5: u32 = 11;
const BBPLL_ENDIV5_VAL_320M: u32 = 0x43;
const BBPLL_BBADC_DSMP_VAL_320M: u32 = 0x84;
const BBPLL_ENDIV5_VAL_480M: u32 = 0xc3;
const BBPLL_BBADC_DSMP_VAL_480M: u32 = 0x74;
const I2C_BBPLL_BBADC_DSMP: u32 = 9;
const I2C_BBPLL_OC_LREF: u32 = 2;
const I2C_BBPLL_OC_DIV_7_0: u32 = 3;
const I2C_BBPLL_OC_DCUR: u32 = 5;
pub(crate) fn esp32_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) {
let efuse = unsafe { &*crate::peripherals::EFUSE::ptr() };
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
unsafe {
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
let div_ref: u32;
let div7_0: u32;
let div10_8: u32;
let lref: u32;
let dcur: u32;
let bw: u32;
let i2c_bbpll_lref: u32;
let i2c_bbpll_div_7_0: u32;
let i2c_bbpll_dcur: u32;
if matches!(pll_freq, PllClock::Pll320MHz) {
// Raise the voltage, if needed
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(DIG_DBIAS_80M_160M as u8));
// Configure 320M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 32;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}
XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::RtcXtalFreq24M => {
div_ref = 11;
div7_0 = 224;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_ENDIV5,
BBPLL_ENDIV5_VAL_320M,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_DSMP,
BBPLL_BBADC_DSMP_VAL_320M,
);
} else {
// Raise the voltage
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(dig_dbias_240_m as u8));
// Configure 480M PLL
match xtal_freq {
XtalClock::RtcXtalFreq40M => {
div_ref = 0;
div7_0 = 28;
div10_8 = 0;
lref = 0;
dcur = 6;
bw = 3;
}
XtalClock::RtcXtalFreq26M => {
div_ref = 12;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::RtcXtalFreq24M => {
div_ref = 11;
div7_0 = 144;
div10_8 = 4;
lref = 1;
dcur = 0;
bw = 1;
}
XtalClock::RtcXtalFreqOther(_) => {
div_ref = 12;
div7_0 = 224;
div10_8 = 4;
lref = 0;
dcur = 0;
bw = 0;
}
}
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_ENDIV5,
BBPLL_ENDIV5_VAL_480M,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_DSMP,
BBPLL_BBADC_DSMP_VAL_480M,
);
}
i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref);
i2c_bbpll_div_7_0 = div7_0;
i2c_bbpll_dcur = (bw << 6) | dcur;
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_LREF,
i2c_bbpll_lref,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV_7_0,
i2c_bbpll_div_7_0,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DCUR,
i2c_bbpll_dcur,
);
}
}
pub(crate) fn esp32_rtc_bbpll_enable() {
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
unsafe {
rtc_cntl.options0().modify(|_, w| {
w.bias_i2c_force_pd()
.clear_bit()
.bb_i2c_force_pd()
.clear_bit()
.bbpll_force_pd()
.clear_bit()
.bbpll_i2c_force_pd()
.clear_bit()
});
// reset BBPLL configuration
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_IR_CAL_DELAY,
BBPLL_IR_CAL_DELAY_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_IR_CAL_EXT_CAP,
BBPLL_IR_CAL_EXT_CAP_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_ENB_FCAL,
BBPLL_OC_ENB_FCAL_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_ENB_VCON,
BBPLL_OC_ENB_VCON_VAL,
);
i2c_writereg_rtc(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_BBADC_CAL_7_0,
BBPLL_BBADC_CAL_7_0_VAL,
);
}
}
#[inline(always)]
unsafe fn i2c_writereg_rtc(block: u32, block_hostid: u32, reg_add: u32, indata: u32) {
const ROM_I2C_WRITEREG: u32 = 0x400041a4;
// cast to usize is just needed because of the way we run clippy in CI
let rom_i2c_writereg: fn(block: u32, block_hostid: u32, reg_add: u32, indata: u32) -> i32 =
core::mem::transmute(ROM_I2C_WRITEREG as usize);
rom_i2c_writereg(block, block_hostid, reg_add, indata);
}
pub(crate) fn esp32_rtc_update_to_xtal(freq: XtalClock, _div: u32) {
let apb_cntl = unsafe { &*crate::peripherals::APB_CTRL::ptr() };
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
unsafe {
let value = (((freq.hz()) >> 12) & UINT16_MAX) | ((((freq.hz()) >> 12) & UINT16_MAX) << 16);
esp32_update_cpu_freq(freq.hz());
// set divider from XTAL to APB clock
apb_cntl.sysclk_conf().modify(|_, w| {
w.pre_div_cnt()
.bits(((freq.hz()) / REF_CLK_FREQ - 1) as u16)
});
// adjust ref_tick
apb_cntl.xtal_tick_conf().as_ptr().write_volatile(
((freq.hz()) / REF_CLK_FREQ - 1) | apb_cntl.xtal_tick_conf().as_ptr().read_volatile(),
); // TODO make it RW in SVD
// switch clock source
rtc_cntl.clk_conf().modify(|_, w| w.soc_clk_sel().xtal());
rtc_cntl
.store5()
.modify(|_, w| w.scratch5().bits(value as u32));
// lower the voltage
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(DIG_DBIAS_XTAL as u8));
}
}
pub(crate) fn set_cpu_freq(cpu_freq_mhz: crate::clock::CpuClock) {
let efuse = unsafe { &*crate::peripherals::EFUSE::ptr() };
let dport = unsafe { &*crate::peripherals::DPORT::ptr() };
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
unsafe {
const RTC_CNTL_DBIAS_1V25: u32 = 7;
let rtc_cntl_dbias_hp_volt: u32 =
RTC_CNTL_DBIAS_1V25 - efuse.blk0_rdata5().read().rd_vol_level_hp_inv().bits() as u32;
let dig_dbias_240_m: u32 = rtc_cntl_dbias_hp_volt;
const CPU_80M: u32 = 0;
const CPU_160M: u32 = 1;
const CPU_240M: u32 = 2;
let mut dbias = DIG_DBIAS_80M_160M;
let per_conf;
match cpu_freq_mhz {
crate::clock::CpuClock::Clock160MHz => {
per_conf = CPU_160M;
}
crate::clock::CpuClock::Clock240MHz => {
dbias = dig_dbias_240_m;
per_conf = CPU_240M;
}
crate::clock::CpuClock::Clock80MHz => {
per_conf = CPU_80M;
}
}
let value = (((80 * MHZ) >> 12) & UINT16_MAX) | ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
dport
.cpu_per_conf()
.write(|w| w.cpuperiod_sel().bits(per_conf as u8));
rtc_cntl
.reg()
.modify(|_, w| w.dig_dbias_wak().variant(dbias as u8));
rtc_cntl.clk_conf().modify(|_, w| w.soc_clk_sel().pll());
rtc_cntl
.store5()
.modify(|_, w| w.scratch5().bits(value as u32));
esp32_update_cpu_freq(cpu_freq_mhz.mhz());
}
}
/// Pass the CPU clock in MHz so that ets_delay_us
/// will be accurate. Call this function when CPU frequency is changed.
fn esp32_update_cpu_freq(mhz: u32) {
const G_TICKS_PER_US_PRO: u32 = 0x3ffe01e0;
unsafe {
// Update scale factors used by esp_rom_delay_us
(G_TICKS_PER_US_PRO as *mut u32).write_volatile(mhz);
}
}

View File

@ -1,369 +0,0 @@
use crate::clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock};
extern "C" {
fn ets_update_cpu_frequency(ticks_per_us: u32);
}
const I2C_BBPLL: u8 = 0x66;
const I2C_BBPLL_HOSTID: u8 = 0;
const I2C_BBPLL_OC_REF_DIV: u8 = 2;
const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4;
const I2C_BBPLL_OC_DIV_7_0: u8 = 3;
const I2C_BBPLL_OC_DR1: u8 = 5;
const I2C_BBPLL_OC_DR1_MSB: u8 = 2;
const I2C_BBPLL_OC_DR1_LSB: u8 = 0;
const I2C_BBPLL_OC_DR3: u8 = 5;
const I2C_BBPLL_OC_DR3_MSB: u8 = 6;
const I2C_BBPLL_OC_DR3_LSB: u8 = 4;
const I2C_BBPLL_OC_DCUR: u8 = 6;
const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4;
const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6;
const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9;
const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1;
const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0;
// Analog function control register
const I2C_MST_ANA_CONF0_REG: u32 = 0x600AF818;
const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2;
const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3;
const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24;
const MODEM_LPCON_CLK_CONF_FORCE_ON_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x1c;
const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2;
const MODEM_LPCON_I2C_MST_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x10;
const MODEM_LPCON_CLK_I2C_MST_SEL_160M: u32 = 1 << 0;
pub(crate) fn esp32c6_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) {
unsafe {
// enable i2c mst clk by force on temporarily
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile(
(MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).read_volatile()
| MODEM_LPCON_CLK_I2C_MST_FO,
);
(MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).write_volatile(
(MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).read_volatile()
| MODEM_LPCON_CLK_I2C_MST_SEL_160M,
);
let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32;
// BBPLL CALIBRATION START
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW,
);
let div_ref = 0u32;
let div7_0 = 8u32;
let dr1 = 0u32;
let dr3 = 0u32;
let dchgp = 5u32;
let dcur = 3u32;
let dbias = 2u32;
let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref;
let i2c_bbpll_div_7_0 = div7_0;
let i2c_bbpll_dcur =
(1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
regi2c_write(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_REF_DIV,
i2c_bbpll_lref as u8,
);
regi2c_write(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DIV_7_0,
i2c_bbpll_div_7_0 as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DR1,
I2C_BBPLL_OC_DR1_MSB,
I2C_BBPLL_OC_DR1_LSB,
dr1 as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DR3,
I2C_BBPLL_OC_DR3_MSB,
I2C_BBPLL_OC_DR3_LSB,
dr3 as u8,
);
regi2c_write(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_DCUR,
i2c_bbpll_dcur as u8,
);
regi2c_write_mask(
I2C_BBPLL,
I2C_BBPLL_HOSTID,
I2C_BBPLL_OC_VCO_DBIAS,
I2C_BBPLL_OC_VCO_DBIAS_MSB,
I2C_BBPLL_OC_VCO_DBIAS_LSB,
dbias as u8,
);
// WAIT CALIBRATION DONE
while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {}
// BBPLL CALIBRATION STOP
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH,
);
i2c_mst_ana_conf0_reg_ptr.write_volatile(
i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW,
);
}
}
pub(crate) fn esp32c6_rtc_bbpll_enable() {
let pmu = unsafe { &*crate::peripherals::PMU::PTR };
pmu.imm_hp_ck_power().modify(|_, w| {
w.tie_high_xpd_bb_i2c()
.set_bit()
.tie_high_xpd_bbpll()
.set_bit()
.tie_high_xpd_bbpll_i2c()
.set_bit()
});
pmu.imm_hp_ck_power()
.modify(|_, w| w.tie_high_global_bbpll_icg().set_bit());
}
pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) {
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
unsafe {
ets_update_cpu_frequency(freq.mhz());
// Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0)
// first.
pcr.apb_freq_conf()
.modify(|_, w| w.apb_div_num().bits(0).apb_div_num().bits(_div - 1));
// Switch clock source
pcr.sysclk_conf().modify(|_, w| w.soc_clk_sel().bits(0));
}
}
pub(crate) fn esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) {
// On ESP32C6, MSPI source clock's default HS divider leads to 120MHz, which is
// unusable before calibration Therefore, before switching SOC_ROOT_CLK to
// HS, we need to set MSPI source clock HS divider to make it run at
// 80MHz after the switch. PLL = 480MHz, so divider is 6.
clk_ll_mspi_fast_set_hs_divider(6);
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
unsafe {
pcr.cpu_freq_conf().modify(|_, w| {
w.cpu_hs_div_num()
.bits(((480 / cpu_clock_speed.mhz() / 3) - 1) as u8)
.cpu_hs_120m_force()
.clear_bit()
});
pcr.cpu_freq_conf()
.modify(|_, w| w.cpu_hs_120m_force().clear_bit());
pcr.sysclk_conf().modify(|_, w| {
w.soc_clk_sel().bits(1) // PLL = 1
});
ets_update_cpu_frequency(cpu_clock_speed.mhz());
}
}
pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) {
let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() };
let value = ((apb_freq.hz() >> 12) & u16::MAX as u32)
| (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16);
lp_aon
.store5()
.modify(|_, w| unsafe { w.lp_aon_store5().bits(value) });
}
fn clk_ll_mspi_fast_set_hs_divider(divider: u32) {
// SOC_ROOT_CLK ------> MSPI_FAST_CLK
// HS divider option: 4, 5, 6 (PCR_MSPI_FAST_HS_DIV_NUM=3, 4, 5)
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
unsafe {
match divider {
4 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(3)),
5 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(4)),
6 => pcr
.mspi_clk_conf()
.modify(|_, w| w.mspi_fast_hs_div_num().bits(5)),
_ => panic!("Unsupported HS MSPI_FAST divider"),
}
}
}
fn reg_set_bit(reg: u32, bit: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | bit);
}
}
fn reg_clr_bit(reg: u32, bit: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !bit);
}
}
fn reg_write(reg: u32, v: u32) {
unsafe {
(reg as *mut u32).write_volatile(v);
}
}
fn reg_get_bit(reg: u32, b: u32) -> u32 {
unsafe { (reg as *mut u32).read_volatile() & b }
}
fn reg_get_field(reg: u32, s: u32, v: u32) -> u32 {
unsafe { ((reg as *mut u32).read_volatile() >> s) & v }
}
const DR_REG_MODEM_LPCON_BASE: u32 = 0x600AF000;
const MODEM_LPCON_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x18;
const MODEM_LPCON_CLK_I2C_MST_EN: u32 = 1 << 2;
const DR_REG_LP_I2C_ANA_MST_BASE: u32 = 0x600B2400;
const LP_I2C_ANA_MST_DATE_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x3fc;
const LP_I2C_ANA_MST_I2C_MAT_CLK_EN: u32 = 1 << 28;
const REGI2C_BIAS: u8 = 0x6a;
const REGI2C_DIG_REG: u8 = 0x6d;
const REGI2C_ULP_CAL: u8 = 0x61;
const REGI2C_SAR_I2C: u8 = 0x69;
const LP_I2C_ANA_MST_DEVICE_EN_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x14;
const REGI2C_BBPLL_DEVICE_EN: u32 = 1 << 5;
const REGI2C_BIAS_DEVICE_EN: u32 = 1 << 4;
const REGI2C_DIG_REG_DEVICE_EN: u32 = 1 << 8;
const REGI2C_ULP_CAL_DEVICE_EN: u32 = 1 << 6;
const REGI2C_SAR_I2C_DEVICE_EN: u32 = 1 << 7;
const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF;
const REGI2C_RTC_SLAVE_ID_S: u8 = 0;
const REGI2C_RTC_ADDR_V: u8 = 0xFF;
const REGI2C_RTC_ADDR_S: u8 = 8;
const REGI2C_RTC_WR_CNTL_V: u8 = 0x1;
const REGI2C_RTC_WR_CNTL_S: u8 = 24;
const REGI2C_RTC_DATA_V: u8 = 0xFF;
const REGI2C_RTC_DATA_S: u8 = 16;
const LP_I2C_ANA_MST_I2C0_CTRL_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x0;
const LP_I2C_ANA_MST_I2C0_BUSY: u32 = 1 << 25;
const LP_I2C_ANA_MST_I2C0_DATA_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x8;
const LP_I2C_ANA_MST_I2C0_RDATA_V: u32 = 0x000000FF;
const LP_I2C_ANA_MST_I2C0_RDATA_S: u32 = 0;
const REGI2C_BBPLL: u8 = 0x66;
fn regi2c_enable_block(block: u8) {
reg_set_bit(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
reg_set_bit(LP_I2C_ANA_MST_DATE_REG, LP_I2C_ANA_MST_I2C_MAT_CLK_EN);
// Before config I2C register, enable corresponding slave.
match block {
REGI2C_BBPLL => {
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN);
}
REGI2C_BIAS => {
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN);
}
REGI2C_DIG_REG => {
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN);
}
REGI2C_ULP_CAL => {
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN);
}
REGI2C_SAR_I2C => {
reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN);
}
_ => (),
}
}
fn regi2c_disable_block(block: u8) {
match block {
REGI2C_BBPLL => {
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN);
}
REGI2C_BIAS => {
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN);
}
REGI2C_DIG_REG => {
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN);
}
REGI2C_ULP_CAL => {
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN);
}
REGI2C_SAR_I2C => {
reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN);
}
_ => (),
}
}
pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) {
regi2c_enable_block(block);
let temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32)
| ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32)
| ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32) // 0: READ I2C register; 1: Write I2C register;
| (((data as u32) & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32);
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
regi2c_disable_block(block);
}
pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
assert!(msb - lsb < 8);
regi2c_enable_block(block);
// Read the i2c bus register
let mut temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32)
<< REGI2C_RTC_SLAVE_ID_S as u32)
| (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32;
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
temp = reg_get_field(
LP_I2C_ANA_MST_I2C0_DATA_REG,
LP_I2C_ANA_MST_I2C0_RDATA_S,
LP_I2C_ANA_MST_I2C0_RDATA_V,
);
// Write the i2c bus register
temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1));
temp =
((data as u32 & (!(0xFFFFFFFF << (msb as u32 - lsb as u32 + 1)))) << (lsb as u32)) | temp;
temp = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32)
| ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32)
| ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32)
| ((temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32);
reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp);
while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {}
regi2c_disable_block(block);
}

View File

@ -1,677 +0,0 @@
//! # Clock Control
//!
//! ## Overview
//! This `Clock` driver provides an interface for configuring and managing
//! various clocks present on the `ESP` microcontrollers.
//!
//! Proper clock configuration is essential for the correct functioning of the
//! microcontroller and its peripherals.
//!
//! The `Clock` driver supports configuring multiple clocks, including:
//! * CPU clock
//! * APB (Advanced Peripheral Bus) clock
//! * XTAL clock
//! * PLL clock
//!
//! and other specific clocks based on the ESP microcontroller's architecture.
//!
//! The `CPU clock` is responsible for defining the speed at which the central
//! processing unit (CPU) operates. This driver provides predefined options for
//! different CPU clock speeds, such
//! * 80 MHz
//! * 96 MHz
//! * 120 MHz
//! * 160 MHz
//! * 240 MHz
//!
//! and others, depending on the microcontroller model.
//!
//! #### Clock Control
//! The `ClockControl` struct allows users to configure the desired clock
//! frequencies before applying them. It offers flexibility in selecting
//! appropriate clock frequencies based on specific application requirements.
//!
//! #### Frozen clock frequencies
//! Once the clock configuration is applied using the `freeze` function of the
//! ClockControl struct, the clock frequencies become `frozen` and cannot be
//! changed. The `Clocks` struct is returned after freezing, providing read-only
//! access to the configured clock frequencies.
//!
//! ## Examples
//!
//! #### Initialize with default clock frequency for this chip
//! ```no_run
//! let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//! ```
//!
//! #### Initialize with the highest possible frequency for this chip
//! ```no_run
//! let clocks = ClockControl::max(system.clock_control).freeze();
//! ```
//!
//! #### Initialize with custom clock frequency
//! ```no_run
//! let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze();
//! ```
use fugit::HertzU32;
use crate::{
peripheral::{Peripheral, PeripheralRef},
system::SystemClockControl,
};
#[cfg_attr(esp32, path = "clocks_ll/esp32.rs")]
#[cfg_attr(esp32c2, path = "clocks_ll/esp32c2.rs")]
#[cfg_attr(esp32c3, path = "clocks_ll/esp32c3.rs")]
#[cfg_attr(esp32c6, path = "clocks_ll/esp32c6.rs")]
#[cfg_attr(esp32h2, path = "clocks_ll/esp32h2.rs")]
#[cfg_attr(esp32s2, path = "clocks_ll/esp32s2.rs")]
#[cfg_attr(esp32s3, path = "clocks_ll/esp32s3.rs")]
pub(crate) mod clocks_ll;
pub trait Clock {
fn frequency(&self) -> HertzU32;
fn mhz(&self) -> u32 {
self.frequency().to_MHz()
}
fn hz(&self) -> u32 {
self.frequency().to_Hz()
}
}
/// CPU clock speed
#[derive(Debug, Clone, Copy)]
pub enum CpuClock {
#[cfg(not(esp32h2))]
Clock80MHz,
#[cfg(esp32h2)]
Clock96MHz,
#[cfg(esp32c2)]
Clock120MHz,
#[cfg(not(any(esp32c2, esp32h2)))]
Clock160MHz,
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
Clock240MHz,
}
#[allow(dead_code)]
impl Clock for CpuClock {
fn frequency(&self) -> HertzU32 {
match self {
#[cfg(not(esp32h2))]
CpuClock::Clock80MHz => HertzU32::MHz(80),
#[cfg(esp32h2)]
CpuClock::Clock96MHz => HertzU32::MHz(96),
#[cfg(esp32c2)]
CpuClock::Clock120MHz => HertzU32::MHz(120),
#[cfg(not(any(esp32c2, esp32h2)))]
CpuClock::Clock160MHz => HertzU32::MHz(160),
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
CpuClock::Clock240MHz => HertzU32::MHz(240),
}
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum XtalClock {
#[cfg(esp32)]
RtcXtalFreq24M,
#[cfg(any(esp32, esp32c2))]
RtcXtalFreq26M,
#[cfg(any(esp32c3, esp32h2, esp32s3))]
RtcXtalFreq32M,
#[cfg(not(esp32h2))]
RtcXtalFreq40M,
RtcXtalFreqOther(u32),
}
impl Clock for XtalClock {
fn frequency(&self) -> HertzU32 {
match self {
#[cfg(esp32)]
XtalClock::RtcXtalFreq24M => HertzU32::MHz(24),
#[cfg(any(esp32, esp32c2))]
XtalClock::RtcXtalFreq26M => HertzU32::MHz(26),
#[cfg(any(esp32c3, esp32h2, esp32s3))]
XtalClock::RtcXtalFreq32M => HertzU32::MHz(32),
#[cfg(not(esp32h2))]
XtalClock::RtcXtalFreq40M => HertzU32::MHz(40),
XtalClock::RtcXtalFreqOther(mhz) => HertzU32::MHz(*mhz),
}
}
}
#[allow(unused)]
#[derive(Debug, Clone, Copy)]
pub(crate) enum PllClock {
#[cfg(esp32h2)]
Pll8MHz,
#[cfg(any(esp32c6, esp32h2))]
Pll48MHz,
#[cfg(esp32h2)]
Pll64MHz,
#[cfg(esp32c6)]
Pll80MHz,
#[cfg(esp32h2)]
Pll96MHz,
#[cfg(esp32c6)]
Pll120MHz,
#[cfg(esp32c6)]
Pll160MHz,
#[cfg(esp32c6)]
Pll240MHz,
#[cfg(not(any(esp32c2, esp32c6, esp32h2)))]
Pll320MHz,
#[cfg(not(esp32h2))]
Pll480MHz,
}
#[allow(unused)]
#[derive(Debug, Clone, Copy)]
pub(crate) enum ApbClock {
#[cfg(esp32h2)]
ApbFreq32MHz,
#[cfg(not(esp32h2))]
ApbFreq40MHz,
#[cfg(not(esp32h2))]
ApbFreq80MHz,
ApbFreqOther(u32),
}
impl Clock for ApbClock {
fn frequency(&self) -> HertzU32 {
match self {
#[cfg(esp32h2)]
ApbClock::ApbFreq32MHz => HertzU32::MHz(32),
#[cfg(not(esp32h2))]
ApbClock::ApbFreq40MHz => HertzU32::MHz(40),
#[cfg(not(esp32h2))]
ApbClock::ApbFreq80MHz => HertzU32::MHz(80),
ApbClock::ApbFreqOther(mhz) => HertzU32::MHz(*mhz),
}
}
}
/// Frozen clock frequencies
///
/// The existence of this value indicates that the clock configuration can no
/// longer be changed
pub struct Clocks<'d> {
_private: PeripheralRef<'d, SystemClockControl>,
pub cpu_clock: HertzU32,
pub apb_clock: HertzU32,
pub xtal_clock: HertzU32,
#[cfg(esp32)]
pub i2c_clock: HertzU32,
#[cfg(esp32)]
pub pwm_clock: HertzU32,
#[cfg(esp32s3)]
pub crypto_pwm_clock: HertzU32,
#[cfg(any(esp32c6, esp32h2))]
pub crypto_clock: HertzU32,
#[cfg(esp32h2)]
pub pll_48m_clock: HertzU32,
#[cfg(esp32h2)]
pub pll_96m_clock: HertzU32,
// TODO chip specific additional ones as needed
}
#[doc(hidden)]
impl<'d> Clocks<'d> {
/// This should not be used in user code.
/// The whole point this exists is make it possible to have other crates
/// (i.e. esp-wifi) create `Clocks`
#[doc(hidden)]
pub fn from_raw_clocks(
system_clock_control: PeripheralRef<'d, SystemClockControl>,
raw_clocks: RawClocks,
) -> Clocks<'d> {
Self {
_private: system_clock_control,
cpu_clock: raw_clocks.cpu_clock,
apb_clock: raw_clocks.apb_clock,
xtal_clock: raw_clocks.xtal_clock,
#[cfg(esp32)]
i2c_clock: raw_clocks.i2c_clock,
#[cfg(esp32)]
pwm_clock: raw_clocks.pwm_clock,
#[cfg(esp32s3)]
crypto_pwm_clock: raw_clocks.crypto_pwm_clock,
#[cfg(any(esp32c6, esp32h2))]
crypto_clock: raw_clocks.crypto_clock,
#[cfg(esp32h2)]
pll_48m_clock: raw_clocks.pll_48m_clock,
#[cfg(esp32h2)]
pll_96m_clock: raw_clocks.pll_96m_clock,
}
}
}
#[doc(hidden)]
pub struct RawClocks {
pub cpu_clock: HertzU32,
pub apb_clock: HertzU32,
pub xtal_clock: HertzU32,
#[cfg(esp32)]
pub i2c_clock: HertzU32,
#[cfg(esp32)]
pub pwm_clock: HertzU32,
#[cfg(esp32s3)]
pub crypto_pwm_clock: HertzU32,
#[cfg(any(esp32c6, esp32h2))]
pub crypto_clock: HertzU32,
#[cfg(esp32h2)]
pub pll_48m_clock: HertzU32,
#[cfg(esp32h2)]
pub pll_96m_clock: HertzU32,
// TODO chip specific additional ones as needed
}
/// Used to configure the frequencies of the clocks present in the chip.
///
/// After setting all frequencies, call the freeze function to apply the
/// configuration.
pub struct ClockControl<'d> {
_private: PeripheralRef<'d, SystemClockControl>,
desired_rates: RawClocks,
}
impl<'d> ClockControl<'d> {
/// Applies the clock configuration and returns a Clocks struct that
/// signifies that the clocks are frozen, and contains the frequencies
/// used. After this function is called, the clocks can not change
pub fn freeze(self) -> Clocks<'d> {
Clocks::from_raw_clocks(self._private, self.desired_rates)
}
}
#[cfg(esp32)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
#[cfg(feature = "xtal-40mhz")]
return ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
i2c_clock: HertzU32::MHz(80),
pwm_clock: HertzU32::MHz(160),
},
};
#[cfg(feature = "xtal-26mhz")]
return ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(26),
i2c_clock: HertzU32::MHz(80),
pwm_clock: HertzU32::MHz(160),
},
};
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
// like NuttX use 40M hardcoded - if it turns out to be a problem
// we will take care then
#[cfg(feature = "xtal-40mhz")]
let xtal_freq = XtalClock::RtcXtalFreq40M;
#[cfg(feature = "xtal-26mhz")]
let xtal_freq = XtalClock::RtcXtalFreq26M;
let pll_freq = match cpu_clock_speed {
CpuClock::Clock80MHz => PllClock::Pll320MHz,
CpuClock::Clock160MHz => PllClock::Pll320MHz,
CpuClock::Clock240MHz => PllClock::Pll480MHz,
};
clocks_ll::esp32_rtc_update_to_xtal(xtal_freq, 1);
clocks_ll::esp32_rtc_bbpll_enable();
clocks_ll::esp32_rtc_bbpll_configure(xtal_freq, pll_freq);
clocks_ll::set_cpu_freq(cpu_clock_speed);
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
i2c_clock: HertzU32::MHz(40),
// The docs are unclear here. pwm_clock seems to be tied to clocks.apb_clock
// while simultaneously being fixed at 160 MHz.
// Testing showed 160 MHz to be correct for current clock configurations.
pwm_clock: HertzU32::MHz(160),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock240MHz)
}
}
#[cfg(esp32c2)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
#[cfg(feature = "xtal-40mhz")]
return ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(40),
xtal_clock: HertzU32::MHz(40),
},
};
#[cfg(feature = "xtal-26mhz")]
return ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(40),
xtal_clock: HertzU32::MHz(26),
},
};
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
let apb_freq;
#[cfg(feature = "xtal-40mhz")]
let xtal_freq = XtalClock::RtcXtalFreq40M;
#[cfg(feature = "xtal-26mhz")]
let xtal_freq = XtalClock::RtcXtalFreq26M;
let pll_freq = PllClock::Pll480MHz;
if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
clocks_ll::esp32c2_rtc_update_to_xtal(xtal_freq, 1);
clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq);
} else {
apb_freq = ApbClock::ApbFreq40MHz;
clocks_ll::esp32c2_rtc_bbpll_enable();
clocks_ll::esp32c2_rtc_bbpll_configure(xtal_freq, pll_freq);
clocks_ll::esp32c2_rtc_freq_to_pll_mhz(cpu_clock_speed);
clocks_ll::esp32c2_rtc_apb_freq_update(apb_freq);
}
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock120MHz)
}
}
#[cfg(esp32c3)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
},
}
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
let apb_freq;
let xtal_freq = XtalClock::RtcXtalFreq40M;
let pll_freq = PllClock::Pll480MHz;
if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
clocks_ll::esp32c3_rtc_update_to_xtal(xtal_freq, 1);
clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq);
} else {
apb_freq = ApbClock::ApbFreq80MHz;
clocks_ll::esp32c3_rtc_bbpll_enable();
clocks_ll::esp32c3_rtc_bbpll_configure(xtal_freq, pll_freq);
clocks_ll::esp32c3_rtc_freq_to_pll_mhz(cpu_clock_speed);
clocks_ll::esp32c3_rtc_apb_freq_update(apb_freq);
}
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock160MHz)
}
}
#[cfg(esp32c6)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
crypto_clock: HertzU32::MHz(160),
},
}
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
let apb_freq;
let xtal_freq = XtalClock::RtcXtalFreq40M;
let pll_freq = PllClock::Pll480MHz;
if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
clocks_ll::esp32c6_rtc_update_to_xtal(xtal_freq, 1);
clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq);
} else {
apb_freq = ApbClock::ApbFreq80MHz;
clocks_ll::esp32c6_rtc_bbpll_enable();
clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq);
clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed);
clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq);
}
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
crypto_clock: HertzU32::MHz(160),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock160MHz)
}
}
#[cfg(esp32h2)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(96),
apb_clock: HertzU32::MHz(32),
xtal_clock: HertzU32::MHz(32),
pll_48m_clock: HertzU32::MHz(48),
crypto_clock: HertzU32::MHz(96),
pll_96m_clock: HertzU32::MHz(96),
},
}
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
let apb_freq;
let xtal_freq = XtalClock::RtcXtalFreq32M;
let pll_freq = PllClock::Pll96MHz;
if cpu_clock_speed.mhz() <= xtal_freq.mhz() {
apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz());
clocks_ll::esp32h2_rtc_update_to_xtal(xtal_freq, 1);
clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
} else {
apb_freq = ApbClock::ApbFreq32MHz;
clocks_ll::esp32h2_rtc_bbpll_enable();
clocks_ll::esp32h2_rtc_bbpll_configure(xtal_freq, pll_freq);
clocks_ll::esp32h2_rtc_freq_to_pll_mhz(cpu_clock_speed);
clocks_ll::esp32h2_rtc_apb_freq_update(apb_freq);
}
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
pll_48m_clock: HertzU32::MHz(48),
crypto_clock: HertzU32::MHz(96),
pll_96m_clock: HertzU32::MHz(96),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock96MHz)
}
}
#[cfg(esp32s2)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
},
}
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
clocks_ll::set_cpu_clock(cpu_clock_speed);
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock240MHz)
}
}
#[cfg(esp32s3)]
impl<'d> ClockControl<'d> {
/// Use what is considered the default settings after boot.
pub fn boot_defaults(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
) -> ClockControl<'d> {
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: HertzU32::MHz(80),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
crypto_pwm_clock: HertzU32::MHz(160),
},
}
}
/// Configure the CPU clock speed.
pub fn configure(
clock_control: impl Peripheral<P = SystemClockControl> + 'd,
cpu_clock_speed: CpuClock,
) -> ClockControl<'d> {
clocks_ll::set_cpu_clock(cpu_clock_speed);
ClockControl {
_private: clock_control.into_ref(),
desired_rates: RawClocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(40),
crypto_pwm_clock: HertzU32::MHz(160),
},
}
}
/// Use the highest possible frequency for a particular chip
pub fn max(clock_control: impl Peripheral<P = SystemClockControl> + 'd) -> ClockControl<'d> {
Self::configure(clock_control, CpuClock::Clock240MHz)
}
}

View File

@ -1,122 +0,0 @@
//! # Delay driver
//!
//! ## Overview
//! The Delay driver provides blocking delay functionalities using the
//! `SYSTIMER` peripheral for RISC-V devices and the built-in Xtensa timer for
//! Xtensa devices. This module implements the blocking [DelayMs] and [DelayUs]
//! traits from [embedded-hal].
//!
//! The delays are implemented in a "best-effort" way, meaning that the CPU will
//! block for at least the amount of time specified, but accuracy can be
//! affected by many factors, including interrupt usage.
//!
//! ## Example
//! ```no_run
//! let mut clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//! let mut delay = Delay::new(&clocks);
//!
//! delay.delay_ms(1000 as u32);
//! ```
//!
//! [DelayMs]: embedded_hal::blocking::delay::DelayMs
//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
use fugit::HertzU64;
/// Delay driver
///
/// Uses the `SYSTIMER` peripheral internally for RISC-V devices, and the
/// built-in Xtensa timer for Xtensa devices.
#[derive(Clone, Copy)]
pub struct Delay {
freq: HertzU64,
}
impl<T> embedded_hal::blocking::delay::DelayMs<T> for Delay
where
T: Into<u32>,
{
fn delay_ms(&mut self, ms: T) {
for _ in 0..ms.into() {
self.delay_micros(1000u32);
}
}
}
impl<T> embedded_hal::blocking::delay::DelayUs<T> for Delay
where
T: Into<u32>,
{
fn delay_us(&mut self, us: T) {
self.delay_micros(us.into());
}
}
#[cfg(feature = "eh1")]
impl embedded_hal_1::delay::DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
self.delay_nanos(ns);
}
}
#[cfg(riscv)]
mod delay {
use super::*;
use crate::{clock::Clocks, systimer::SystemTimer};
impl Delay {
/// Create a new `Delay` instance
pub fn new(clocks: &Clocks) -> Self {
// The counters and comparators are driven using `XTAL_CLK`.
// The average clock frequency is fXTAL_CLK/2.5, which is 16 MHz.
// The timer counting is incremented by 1/16 μs on each `CNT_CLK` cycle.
Self {
freq: HertzU64::MHz(clocks.xtal_clock.to_MHz() as u64 * 10 / 25),
}
}
/// Delay for the specified number of microseconds
pub fn delay_micros(&self, us: u32) {
let t0 = SystemTimer::now();
let clocks = us as u64 * (self.freq / HertzU64::MHz(1));
while SystemTimer::now().wrapping_sub(t0) & SystemTimer::BIT_MASK <= clocks {}
}
/// Delay for the specified number of nanoseconds
pub fn delay_nanos(&self, ns: u32) {
let t0 = SystemTimer::now();
let clocks = ns as u64 * (self.freq / HertzU64::MHz(1)) / 1000;
while SystemTimer::now().wrapping_sub(t0) & SystemTimer::BIT_MASK <= clocks {}
}
}
}
#[cfg(xtensa)]
mod delay {
use super::*;
use crate::clock::Clocks;
impl Delay {
/// Create a new `Delay` instance
pub fn new(clocks: &Clocks) -> Self {
Self {
freq: clocks.cpu_clock.into(),
}
}
/// Delay for the specified number of microseconds
pub fn delay_micros(&self, us: u32) {
let clocks = us as u64 * (self.freq / HertzU64::MHz(1));
xtensa_lx::timer::delay(clocks as u32);
}
/// Delay for the specified number of nanoseconds
pub fn delay_nanos(&self, ns: u32) {
let clocks = ns as u64 * (self.freq / HertzU64::MHz(1)) / 1000;
xtensa_lx::timer::delay(clocks as u32);
}
}
}

View File

@ -1,692 +0,0 @@
//! # Direct Memory Access
//!
//! ## Overview
//!
//! The GDMA (General DMA) module is a part of the DMA (Direct Memory Access)
//! driver for ESP chips. Of the Espressif chip range, every chip except of
//! `ESP32` and `ESP32-S2` uses the `GDMA` type of direct memory access.
//!
//! DMA is a hardware feature that allows data transfer between memory and
//! peripherals without involving the CPU, resulting in efficient data movement
//! and reduced CPU overhead. The `GDMA` module provides multiple DMA channels,
//! each capable of managing data transfer for various peripherals.
//!
//! This module implements DMA channels, such as `channel0`, `channel1` and so
//! on. Each channel struct implements the `ChannelTypes` trait, which provides
//! associated types for peripheral configuration.
//!
//! GDMA peripheral can be initializes using the `new` function, which requires
//! a DMA peripheral instance and a clock control reference.
//!
//! ```no_run
//! let dma = Gdma::new(peripherals.DMA);
//! ```
//!
//! <em>PS: Note that the number of DMA channels is chip-specific.</em>
use crate::{
dma::*,
peripheral::PeripheralRef,
system::{Peripheral, PeripheralClockControl},
};
#[cold]
fn on_tx_descriptor_not_divisible_by_3() {
panic!("The number of tx descriptors must be a multiple of 3");
}
#[cold]
fn on_rx_descriptor_not_divisible_by_3() {
panic!("The number of rx descriptors must be a multiple of 3");
}
macro_rules! impl_channel {
($num: literal) => {
paste::paste! {
#[non_exhaustive]
pub struct [<Channel $num>] {}
impl ChannelTypes for [<Channel $num>] {
type P = [<SuitablePeripheral $num>];
type Tx<'a> = ChannelTx<'a, [<Channel $num TxImpl>], [<Channel $num>]>;
type Rx<'a> = ChannelRx<'a, [<Channel $num RxImpl>], [<Channel $num>]>;
}
impl RegisterAccess for [<Channel $num>] {
fn init_channel() {
// nothing special to be done here
}
fn set_out_burstmode(burst_mode: bool) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_conf0_ch($num).modify(|_,w| {
w.out_data_burst_en().bit(burst_mode)
.outdscr_burst_en().bit(burst_mode)
});
}
fn set_out_priority(priority: DmaPriority) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_pri_ch($num).write(|w| {
w.tx_pri().variant(priority as u8)
});
}
fn clear_out_interrupts() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
dma.int_clr_ch($num).write(|w| {
w.out_eof()
.set_bit()
.out_dscr_err()
.set_bit()
.out_done()
.set_bit()
.out_total_eof()
.set_bit()
.outfifo_ovf()
.set_bit()
.outfifo_udf()
.set_bit()
});
#[cfg(any(esp32c6, esp32h2))]
dma.out_int_clr_ch($num).write(|w| {
w.out_eof()
.set_bit()
.out_dscr_err()
.set_bit()
.out_done()
.set_bit()
.out_total_eof()
.set_bit()
.outfifo_ovf()
.set_bit()
.outfifo_udf()
.set_bit()
});
#[cfg(esp32s3)]
dma.out_int_clr_ch($num).write(|w| {
w.out_eof()
.set_bit()
.out_dscr_err()
.set_bit()
.out_done()
.set_bit()
.out_total_eof()
.set_bit()
.outfifo_ovf_l1()
.set_bit()
.outfifo_ovf_l3()
.set_bit()
.outfifo_udf_l1()
.set_bit()
.outfifo_udf_l3()
.set_bit()
});
}
fn reset_out() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_conf0_ch($num).modify(|_, w| w.out_rst().set_bit());
dma.out_conf0_ch($num).modify(|_, w| w.out_rst().clear_bit());
}
fn set_out_descriptors(address: u32) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_link_ch($num).modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().out_dscr_err().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.out_int_raw_ch($num).read().out_dscr_err().bit();
ret
}
fn set_out_peripheral(peripheral: u8) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_peri_sel_ch($num).modify(|_, w| w.peri_out_sel().variant(peripheral));
}
fn start_out() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_link_ch($num).modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
dma.int_clr_ch($num).write(|w| w.out_done().set_bit());
#[cfg(any(esp32c6, esp32h2, esp32s3))]
dma.out_int_clr_ch($num).write(|w| w.out_done().set_bit());
}
fn is_ch_out_done_set() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().out_done().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.out_int_raw_ch($num).read().out_done().bit();
ret
}
fn listen_ch_out_done() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).modify(|_, w| w.out_done().set_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.out_done().set_bit())
}
}
}
fn unlisten_ch_out_done() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).modify(|_, w| w.out_done().clear_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.out_done().clear_bit())
}
}
}
fn is_listening_ch_out_done() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).read().out_done().bit()
} else {
dma.int_ena_ch($num).read().out_done().bit()
}
}
}
fn is_out_done() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().out_total_eof().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.out_int_raw_ch($num).read().out_total_eof().bit();
ret
}
fn last_out_dscr_address() -> usize {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_eof_des_addr_ch($num).read().out_eof_des_addr().bits() as usize
}
fn is_out_eof_interrupt_set() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().out_eof().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.out_int_raw_ch($num).read().out_eof().bit();
ret
}
fn reset_out_eof_interrupt() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
dma.int_clr_ch($num).write(|w| {
w.out_eof()
.set_bit()
});
#[cfg(any(esp32c6, esp32h2, esp32s3))]
dma.out_int_clr_ch($num).write(|w| {
w.out_eof()
.set_bit()
});
}
fn set_in_burstmode(burst_mode: bool) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_conf0_ch($num).modify(|_,w| {
w.in_data_burst_en().bit(burst_mode).indscr_burst_en().bit(burst_mode)
});
}
fn set_in_priority(priority: DmaPriority) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_pri_ch($num).write(|w| {
w.rx_pri().variant(priority as u8)
});
}
fn clear_in_interrupts() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
dma.int_clr_ch($num).write(|w| {
w.in_suc_eof()
.set_bit()
.in_err_eof()
.set_bit()
.in_dscr_err()
.set_bit()
.in_dscr_empty()
.set_bit()
.in_done()
.set_bit()
.infifo_ovf()
.set_bit()
.infifo_udf()
.set_bit()
});
#[cfg(any(esp32c6, esp32h2))]
dma.in_int_clr_ch($num).write(|w| {
w.in_suc_eof()
.set_bit()
.in_err_eof()
.set_bit()
.in_dscr_err()
.set_bit()
.in_dscr_empty()
.set_bit()
.in_done()
.set_bit()
.infifo_ovf()
.set_bit()
.infifo_udf()
.set_bit()
});
#[cfg(esp32s3)]
dma.in_int_clr_ch($num).write(|w| {
w.in_suc_eof()
.set_bit()
.in_err_eof()
.set_bit()
.in_dscr_err()
.set_bit()
.in_dscr_empty()
.set_bit()
.in_done()
.set_bit()
.infifo_ovf_l1()
.set_bit()
.infifo_ovf_l3()
.set_bit()
.infifo_udf_l1()
.set_bit()
.infifo_udf_l3()
.set_bit()
});
}
fn reset_in() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_conf0_ch($num).modify(|_, w| w.in_rst().set_bit());
dma.in_conf0_ch($num).modify(|_, w| w.in_rst().clear_bit());
}
fn set_in_descriptors(address: u32) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_link_ch($num).modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().in_dscr_err().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.in_int_raw_ch($num).read().in_dscr_err().bit();
ret
}
fn has_in_descriptor_error_dscr_empty() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().in_dscr_empty().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.in_int_raw_ch($num).read().in_dscr_empty().bit();
ret
}
fn has_in_descriptor_error_err_eof() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().in_err_eof().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.in_int_raw_ch($num).read().in_err_eof().bit();
ret
}
fn set_in_peripheral(peripheral: u8) {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_peri_sel_ch($num).modify(|_, w| w.peri_in_sel().variant(peripheral));
}
fn start_in() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_link_ch($num).modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().in_suc_eof().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.in_int_raw_ch($num).read().in_suc_eof().bit();
ret
}
fn last_in_dscr_address() -> usize {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_dscr_bf0_ch($num).read().inlink_dscr_bf0().bits() as usize
}
fn is_listening_in_eof() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).read().in_suc_eof().bit_is_set()
} else {
dma.int_ena_ch($num).read().in_suc_eof().bit_is_set()
}
}
}
fn is_listening_out_eof() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).read().out_total_eof().bit_is_set()
} else {
dma.int_ena_ch($num).read().out_total_eof().bit_is_set()
}
}
}
fn listen_in_eof() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).modify(|_, w| w.in_suc_eof().set_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.in_suc_eof().set_bit())
}
}
}
fn listen_out_eof() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).modify(|_, w| w.out_total_eof().set_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.out_total_eof().set_bit())
}
}
}
fn unlisten_in_eof() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).modify(|_, w| w.in_suc_eof().clear_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.in_suc_eof().clear_bit())
}
}
}
fn unlisten_out_eof() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.out_int_ena_ch($num).modify(|_, w| w.out_total_eof().clear_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.out_total_eof().clear_bit())
}
}
}
fn listen_ch_in_done(){
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).modify(|_, w| w.in_done().set_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.in_done().set_bit())
}
}
}
fn clear_ch_in_done(){
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
dma.int_clr_ch($num).write(|w| w.in_done().set_bit());
#[cfg(any(esp32c6, esp32h2, esp32s3))]
dma.in_int_clr_ch($num).write(|w| w.in_done().set_bit());
}
fn is_ch_in_done_set() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
#[cfg(not(any(esp32c6, esp32h2, esp32s3)))]
let ret = dma.int_raw_ch($num).read().in_done().bit();
#[cfg(any(esp32c6, esp32h2, esp32s3))]
let ret = dma.in_int_raw_ch($num).read().in_done().bit();
ret
}
fn unlisten_ch_in_done() {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).modify(|_, w| w.in_done().clear_bit())
} else {
dma.int_ena_ch($num).modify(|_, w| w.in_done().clear_bit())
}
}
}
fn is_listening_ch_in_done() -> bool {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, esp32s3))] {
dma.in_int_ena_ch($num).read().in_done().bit()
} else {
dma.int_ena_ch($num).read().in_done().bit()
}
}
}
}
#[non_exhaustive]
pub struct [<Channel $num TxImpl>] {}
impl<'a> TxChannel<[<Channel $num>]> for [<Channel $num TxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
#[non_exhaustive]
pub struct [<Channel $num RxImpl>] {}
impl<'a> RxChannel<[<Channel $num>]> for [<Channel $num RxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
#[non_exhaustive]
pub struct [<ChannelCreator $num>] {}
impl [<ChannelCreator $num>] {
/// Configure the channel for use
///
/// Descriptors should be sized as `((CHUNK_SIZE + 4091) / 4092) * 3`. I.e., to
/// transfer buffers of size `1..=4092`, you need 3 descriptors. The number of
/// descriptors must be a multiple of 3.
pub fn configure<'a>(
self,
burst_mode: bool,
tx_descriptors: &'a mut [u32],
rx_descriptors: &'a mut [u32],
priority: DmaPriority,
) -> Channel<'a, [<Channel $num>]> {
if tx_descriptors.len() % 3 != 0 {
on_tx_descriptor_not_divisible_by_3();
}
if rx_descriptors.len() % 3 != 0 {
on_rx_descriptor_not_divisible_by_3();
}
let mut tx_impl = [<Channel $num TxImpl>] {};
tx_impl.init(burst_mode, priority);
let tx_channel = ChannelTx {
descriptors: tx_descriptors,
burst_mode,
tx_impl: tx_impl,
write_offset: 0,
write_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
buffer_start: core::ptr::null(),
buffer_len: 0,
_phantom: PhantomData::default(),
};
let mut rx_impl = [<Channel $num RxImpl>] {};
rx_impl.init(burst_mode, priority);
let rx_channel = ChannelRx {
descriptors: rx_descriptors,
burst_mode,
rx_impl: rx_impl,
read_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
read_buffer_start: core::ptr::null(),
_phantom: PhantomData::default(),
};
Channel {
tx: tx_channel,
rx: rx_channel,
}
}
}
#[non_exhaustive]
pub struct [<SuitablePeripheral $num>] {}
impl PeripheralMarker for [<SuitablePeripheral $num>] {}
// with GDMA every channel can be used for any peripheral
impl SpiPeripheral for [<SuitablePeripheral $num>] {}
impl Spi2Peripheral for [<SuitablePeripheral $num>] {}
#[cfg(esp32s3)]
impl Spi3Peripheral for [<SuitablePeripheral $num>] {}
impl I2sPeripheral for [<SuitablePeripheral $num>] {}
impl I2s0Peripheral for [<SuitablePeripheral $num>] {}
impl I2s1Peripheral for [<SuitablePeripheral $num>] {}
#[cfg(parl_io)]
impl ParlIoPeripheral for [<SuitablePeripheral $num>] {}
#[cfg(aes)]
impl AesPeripheral for [<SuitablePeripheral $num>] {}
}
};
}
impl_channel!(0);
#[cfg(not(esp32c2))]
impl_channel!(1);
#[cfg(not(esp32c2))]
impl_channel!(2);
#[cfg(esp32s3)]
impl_channel!(3);
#[cfg(esp32s3)]
impl_channel!(4);
/// GDMA Peripheral
///
/// This offers the available DMA channels.
pub struct Gdma<'d> {
_inner: PeripheralRef<'d, crate::peripherals::DMA>,
pub channel0: ChannelCreator0,
#[cfg(not(esp32c2))]
pub channel1: ChannelCreator1,
#[cfg(not(esp32c2))]
pub channel2: ChannelCreator2,
#[cfg(esp32s3)]
pub channel3: ChannelCreator3,
#[cfg(esp32s3)]
pub channel4: ChannelCreator4,
}
impl<'d> Gdma<'d> {
/// Create a DMA instance.
pub fn new(
dma: impl crate::peripheral::Peripheral<P = crate::peripherals::DMA> + 'd,
) -> Gdma<'d> {
crate::into_ref!(dma);
PeripheralClockControl::enable(Peripheral::Gdma);
dma.misc_conf().modify(|_, w| w.ahbm_rst_inter().set_bit());
dma.misc_conf()
.modify(|_, w| w.ahbm_rst_inter().clear_bit());
dma.misc_conf().modify(|_, w| w.clk_en().set_bit());
Gdma {
_inner: dma,
channel0: ChannelCreator0 {},
#[cfg(not(esp32c2))]
channel1: ChannelCreator1 {},
#[cfg(not(esp32c2))]
channel2: ChannelCreator2 {},
#[cfg(esp32s3)]
channel3: ChannelCreator3 {},
#[cfg(esp32s3)]
channel4: ChannelCreator4 {},
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,742 +0,0 @@
//! # Direct Memory Access
//!
//! ## Overview
//!
//! The `pdma` module is part of the DMA (Direct Memory Access) driver of
//! `ESP32` and `ESP32-S2`.
//!
//! This module provides efficient direct data transfer capabilities between
//! peripherals and memory without involving the CPU. It enables bidirectional
//! data transfers through DMA channels, making it particularly useful for
//! high-speed data transfers, such as [SPI] and [I2S] communication.
//!
//! [SPI]: ../spi/index.html
//! [I2S]: ../i2s/index.html
use crate::{
dma::*,
peripheral::PeripheralRef,
system::{Peripheral, PeripheralClockControl},
};
#[cold]
fn on_tx_descriptor_not_divisible_by_3() {
panic!("The number of tx descriptors must be a multiple of 3");
}
#[cold]
fn on_rx_descriptor_not_divisible_by_3() {
panic!("The number of rx descriptors must be a multiple of 3");
}
macro_rules! ImplSpiChannel {
($num: literal) => {
paste::paste! {
#[non_exhaustive]
pub struct [<Spi $num DmaChannel>] {}
impl ChannelTypes for [<Spi $num DmaChannel>] {
type P = [<Spi $num DmaSuitablePeripheral>];
type Tx<'a> = ChannelTx<'a,[<Spi $num DmaChannelTxImpl>], [<Spi $num DmaChannel>]>;
type Rx<'a> = ChannelRx<'a,[<Spi $num DmaChannelRxImpl>], [<Spi $num DmaChannel>]>;
}
impl RegisterAccess for [<Spi $num DmaChannel>] {
fn init_channel() {
// (only) on ESP32 we need to configure DPORT for the SPI DMA channels
#[cfg(esp32)]
{
let dport = unsafe { &*crate::peripherals::DPORT::PTR };
match $num {
2 => {
dport
.spi_dma_chan_sel()
.modify(|_, w| w.spi2_dma_chan_sel().variant(1));
},
3 => {
dport
.spi_dma_chan_sel()
.modify(|_, w| w.spi3_dma_chan_sel().variant(2));
},
_ => panic!("Only SPI2 and SPI3 supported"),
}
}
}
fn set_out_burstmode(burst_mode: bool) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_conf()
.modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
}
fn set_out_priority(_priority: DmaPriority) {}
fn clear_out_interrupts() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| {
w.out_done_int_clr()
.set_bit()
.out_eof_int_clr()
.set_bit()
.out_total_eof_int_clr()
.set_bit()
.outlink_dscr_error_int_clr()
.set_bit()
});
}
fn reset_out() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_conf().modify(|_, w| w.out_rst().set_bit());
spi.dma_conf().modify(|_, w| w.out_rst().clear_bit());
}
fn set_out_descriptors(address: u32) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_out_link()
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().outlink_dscr_error_int_raw().bit()
}
fn set_out_peripheral(_peripheral: u8) {
// no-op
}
fn start_out() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_out_link().modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| w.out_done_int_clr().set_bit());
}
fn is_ch_out_done_set() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().out_done_int_raw().bit()
}
fn listen_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_done_int_ena().set_bit());
}
fn unlisten_ch_out_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_done_int_ena().clear_bit());
}
fn is_listening_ch_out_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().out_done_int_ena().bit()
}
fn is_out_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
// FIXME this should be out_total_eof_int_raw? but on esp32 this interrupt doesn't seem to fire
spi.dma_int_raw().read().out_eof_int_raw().bit()
}
fn last_out_dscr_address() -> usize {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize
}
fn is_out_eof_interrupt_set() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().out_eof_int_raw().bit()
}
fn reset_out_eof_interrupt() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| {
w.out_eof_int_clr()
.set_bit()
});
}
fn set_in_burstmode(burst_mode: bool) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_conf()
.modify(|_, w| w.indscr_burst_en().bit(burst_mode));
}
fn set_in_priority(_priority: DmaPriority) {}
fn clear_in_interrupts() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| {
w.in_done_int_clr()
.set_bit()
.in_err_eof_int_clr()
.set_bit()
.in_suc_eof_int_clr()
.set_bit()
.inlink_dscr_error_int_clr()
.set_bit()
});
}
fn reset_in() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_conf().modify(|_, w| w.in_rst().set_bit());
spi.dma_conf().modify(|_, w| w.in_rst().clear_bit());
}
fn set_in_descriptors(address: u32) {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_in_link()
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().inlink_dscr_error_int_raw().bit()
}
fn has_in_descriptor_error_dscr_empty() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().inlink_dscr_empty_int_raw().bit()
}
fn has_in_descriptor_error_err_eof() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_err_eof_int_raw().bit()
}
fn set_in_peripheral(_peripheral: u8) {
// no-op
}
fn start_in() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_in_link().modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_done_int_raw().bit()
}
fn last_in_dscr_address() -> usize {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.inlink_dscr_bf0().read().dma_inlink_dscr_bf0().bits() as usize
}
fn is_listening_in_eof() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().in_suc_eof_int_ena().bit_is_set()
}
fn is_listening_out_eof() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().out_total_eof_int_ena().bit_is_set()
}
fn listen_in_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_suc_eof_int_ena().set_bit());
}
fn listen_out_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_total_eof_int_ena().set_bit());
}
fn unlisten_in_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_suc_eof_int_ena().clear_bit());
}
fn unlisten_out_eof() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.out_total_eof_int_ena().clear_bit());
}
fn listen_ch_in_done(){
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_done_int_ena().set_bit());
}
fn clear_ch_in_done(){
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_clr().write(|w| w.in_done_int_clr().set_bit());
}
fn is_ch_in_done_set() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_raw().read().in_done_int_raw().bit()
}
fn unlisten_ch_in_done() {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().modify(|_, w| w.in_done_int_ena().clear_bit());
}
fn is_listening_ch_in_done() -> bool {
let spi = unsafe { &*crate::peripherals::[<SPI $num>]::PTR };
spi.dma_int_ena().read().in_done_int_ena().bit()
}
}
#[non_exhaustive]
pub struct [<Spi $num DmaChannelTxImpl>] {}
impl<'a> TxChannel<[<Spi $num DmaChannel>]> for [<Spi $num DmaChannelTxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
#[non_exhaustive]
pub struct [<Spi $num DmaChannelRxImpl>] {}
impl<'a> RxChannel<[<Spi $num DmaChannel>]> for [<Spi $num DmaChannelRxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
#[non_exhaustive]
pub struct [<Spi $num DmaChannelCreator>] {}
impl [<Spi $num DmaChannelCreator>] {
/// Configure the channel for use
///
/// Descriptors should be sized as `((CHUNK_SIZE + 4091) / 4092) * 3`. I.e., to
/// transfer buffers of size `1..=4092`, you need 3 descriptors. The number of
/// descriptors must be a multiple of 3.
pub fn configure<'a>(
self,
burst_mode: bool,
tx_descriptors: &'a mut [u32],
rx_descriptors: &'a mut [u32],
priority: DmaPriority,
) -> Channel<'a, [<Spi $num DmaChannel>]> {
if tx_descriptors.len() % 3 != 0 {
on_tx_descriptor_not_divisible_by_3();
}
if rx_descriptors.len() % 3 != 0 {
on_rx_descriptor_not_divisible_by_3();
}
let mut tx_impl = [<Spi $num DmaChannelTxImpl>] {};
tx_impl.init(burst_mode, priority);
let tx_channel = ChannelTx {
descriptors: tx_descriptors,
burst_mode,
tx_impl: tx_impl,
write_offset: 0,
write_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
buffer_start: core::ptr::null(),
buffer_len: 0,
_phantom: PhantomData::default(),
};
let mut rx_impl = [<Spi $num DmaChannelRxImpl>] {};
rx_impl.init(burst_mode, priority);
let rx_channel = ChannelRx {
descriptors: rx_descriptors,
burst_mode,
rx_impl: rx_impl,
read_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
read_buffer_start: core::ptr::null(),
_phantom: PhantomData::default(),
};
Channel {
tx: tx_channel,
rx: rx_channel,
}
}
}
}
};
}
macro_rules! ImplI2sChannel {
($num: literal, $peripheral: literal) => {
paste::paste! {
pub struct [<I2s $num DmaChannel>] {}
impl ChannelTypes for [<I2s $num DmaChannel>] {
type P = [<I2s $num DmaSuitablePeripheral>];
type Tx<'a> = ChannelTx<'a,[<I2s $num DmaChannelTxImpl>], [<I2s $num DmaChannel>]>;
type Rx<'a> = ChannelRx<'a,[<I2s $num DmaChannelRxImpl>], [<I2s $num DmaChannel>]>;
}
impl RegisterAccess for [<I2s $num DmaChannel>] {
fn init_channel() {
// nothing to do
}
fn set_out_burstmode(burst_mode: bool) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.lc_conf()
.modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
}
fn set_out_priority(_priority: DmaPriority) {}
fn clear_out_interrupts() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| {
w.out_done_int_clr()
.set_bit()
.out_eof_int_clr()
.set_bit()
.out_total_eof_int_clr()
.set_bit()
.out_dscr_err_int_clr()
.set_bit()
});
}
fn reset_out() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.lc_conf().modify(|_, w| w.out_rst().set_bit());
reg_block.lc_conf().modify(|_, w| w.out_rst().clear_bit());
}
fn set_out_descriptors(address: u32) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.out_link()
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn has_out_descriptor_error() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_dscr_err_int_raw().bit()
}
fn set_out_peripheral(_peripheral: u8) {
// no-op
}
fn start_out() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.out_link().modify(|_, w| w.outlink_start().set_bit());
}
fn clear_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| w.out_done_int_clr().set_bit());
}
fn is_ch_out_done_set() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_done_int_raw().bit()
}
fn listen_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_done_int_ena().set_bit());
}
fn unlisten_ch_out_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.out_done_int_ena().clear_bit());
}
fn is_listening_ch_out_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().out_done_int_ena().bit()
}
fn is_out_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_eof_int_raw().bit()
}
fn last_out_dscr_address() -> usize {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.out_eof_des_addr().read().out_eof_des_addr().bits() as usize
}
fn is_out_eof_interrupt_set() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().out_eof_int_raw().bit()
}
fn reset_out_eof_interrupt() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| {
w.out_eof_int_clr()
.set_bit()
});
}
fn set_in_burstmode(burst_mode: bool) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.lc_conf()
.modify(|_, w| w.indscr_burst_en().bit(burst_mode));
}
fn set_in_priority(_priority: DmaPriority) {}
fn clear_in_interrupts() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| {
w.in_done_int_clr()
.set_bit()
.in_err_eof_int_clr()
.set_bit()
.in_suc_eof_int_clr()
.set_bit()
.in_dscr_err_int_clr()
.set_bit()
});
}
fn reset_in() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.lc_conf().modify(|_, w| w.in_rst().set_bit());
reg_block.lc_conf().modify(|_, w| w.in_rst().clear_bit());
}
fn set_in_descriptors(address: u32) {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.in_link()
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn has_in_descriptor_error() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_dscr_err_int_raw().bit()
}
fn has_in_descriptor_error_dscr_empty() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_dscr_empty_int_raw().bit()
}
fn has_in_descriptor_error_err_eof() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_err_eof_int_raw().bit()
}
fn set_in_peripheral(_peripheral: u8) {
// no-op
}
fn start_in() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.in_link().modify(|_, w| w.inlink_start().set_bit());
}
fn is_in_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_done_int_raw().bit()
}
fn last_in_dscr_address() -> usize {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.inlink_dscr_bf0().read().inlink_dscr_bf0().bits() as usize
}
fn is_listening_in_eof() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_suc_eof_int_ena().bit()
}
fn is_listening_out_eof() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().out_eof_int_ena().bit()
}
fn listen_in_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.in_suc_eof_int_ena().set_bit() );
}
fn listen_out_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.out_eof_int_ena().set_bit() );
}
fn unlisten_in_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.in_suc_eof_int_ena().clear_bit() );
}
fn unlisten_out_eof() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_,w| w.out_eof_int_ena().clear_bit() );
}
fn listen_ch_in_done(){
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_done_int_ena().set_bit());
}
fn clear_ch_in_done(){
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_clr().write(|w| w.in_done_int_clr().set_bit());
}
fn is_ch_in_done_set() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_raw().read().in_done_int_raw().bit()
}
fn unlisten_ch_in_done() {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().modify(|_, w| w.in_done_int_ena().clear_bit());
}
fn is_listening_ch_in_done() -> bool {
let reg_block = unsafe { &*crate::peripherals::[<$peripheral>]::PTR };
reg_block.int_ena().read().in_done_int_ena().bit()
}
}
pub struct [<I2s $num DmaChannelTxImpl>] {}
impl<'a> TxChannel<[<I2s $num DmaChannel>]> for [<I2s $num DmaChannelTxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
pub struct [<I2s $num DmaChannelRxImpl>] {}
impl<'a> RxChannel<[<I2s $num DmaChannel>]> for [<I2s $num DmaChannelRxImpl>] {
#[cfg(feature = "async")]
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
}
pub struct [<I2s $num DmaChannelCreator>] {}
impl [<I2s $num DmaChannelCreator>] {
/// Configure the channel for use
///
/// Descriptors should be sized as `((CHUNK_SIZE + 4091) / 4092) * 3`. I.e., to
/// transfer buffers of size `1..=4092`, you need 3 descriptors.
pub fn configure<'a>(
self,
burst_mode: bool,
tx_descriptors: &'a mut [u32],
rx_descriptors: &'a mut [u32],
priority: DmaPriority,
) -> Channel<'a, [<I2s $num DmaChannel>]> {
let mut tx_impl = [<I2s $num DmaChannelTxImpl>] {};
tx_impl.init(burst_mode, priority);
let tx_channel = ChannelTx {
descriptors: tx_descriptors,
burst_mode,
tx_impl: tx_impl,
write_offset: 0,
write_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
buffer_start: core::ptr::null(),
buffer_len: 0,
_phantom: PhantomData::default(),
};
let mut rx_impl = [<I2s $num DmaChannelRxImpl>] {};
rx_impl.init(burst_mode, priority);
let rx_channel = ChannelRx {
descriptors: rx_descriptors,
burst_mode,
rx_impl: rx_impl,
read_descr_ptr: core::ptr::null(),
available: 0,
last_seen_handled_descriptor_ptr: core::ptr::null(),
read_buffer_start: core::ptr::null(),
_phantom: PhantomData::default(),
};
Channel {
tx: tx_channel,
rx: rx_channel,
}
}
}
}
};
}
#[non_exhaustive]
pub struct Spi2DmaSuitablePeripheral {}
impl PeripheralMarker for Spi2DmaSuitablePeripheral {}
impl SpiPeripheral for Spi2DmaSuitablePeripheral {}
impl Spi2Peripheral for Spi2DmaSuitablePeripheral {}
#[non_exhaustive]
pub struct Spi3DmaSuitablePeripheral {}
impl PeripheralMarker for Spi3DmaSuitablePeripheral {}
impl SpiPeripheral for Spi3DmaSuitablePeripheral {}
impl Spi3Peripheral for Spi3DmaSuitablePeripheral {}
ImplSpiChannel!(2);
ImplSpiChannel!(3);
#[non_exhaustive]
pub struct I2s0DmaSuitablePeripheral {}
impl PeripheralMarker for I2s0DmaSuitablePeripheral {}
impl I2sPeripheral for I2s0DmaSuitablePeripheral {}
impl I2s0Peripheral for I2s0DmaSuitablePeripheral {}
ImplI2sChannel!(0, "I2S0");
#[non_exhaustive]
pub struct I2s1DmaSuitablePeripheral {}
impl PeripheralMarker for I2s1DmaSuitablePeripheral {}
impl I2sPeripheral for I2s1DmaSuitablePeripheral {}
impl I2s1Peripheral for I2s1DmaSuitablePeripheral {}
#[cfg(esp32)]
ImplI2sChannel!(1, "I2S1");
/// DMA Peripheral
///
/// This offers the available DMA channels.
pub struct Dma<'d> {
_inner: PeripheralRef<'d, crate::system::Dma>,
pub spi2channel: Spi2DmaChannelCreator,
pub spi3channel: Spi3DmaChannelCreator,
pub i2s0channel: I2s0DmaChannelCreator,
#[cfg(esp32)]
pub i2s1channel: I2s1DmaChannelCreator,
}
impl<'d> Dma<'d> {
/// Create a DMA instance.
pub fn new(dma: impl crate::peripheral::Peripheral<P = crate::system::Dma> + 'd) -> Dma<'d> {
PeripheralClockControl::enable(Peripheral::Dma);
Dma {
_inner: dma.into_ref(),
spi2channel: Spi2DmaChannelCreator {},
spi3channel: Spi3DmaChannelCreator {},
i2s0channel: I2s0DmaChannelCreator {},
#[cfg(esp32)]
i2s1channel: I2s1DmaChannelCreator {},
}
}
}

View File

@ -1,178 +0,0 @@
//! Interrupt-mode executor.
use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit};
use embassy_executor::{raw, SendSpawner};
#[cfg(any(esp32c6, esp32h2))]
use peripherals::INTPRI as SystemPeripheral;
#[cfg(not(any(esp32c6, esp32h2)))]
use peripherals::SYSTEM as SystemPeripheral;
use portable_atomic::{AtomicUsize, Ordering};
use crate::{get_core, interrupt, peripherals};
static FROM_CPU_IRQ_USED: AtomicUsize = AtomicUsize::new(0);
pub trait SwPendableInterrupt {
fn enable(priority: interrupt::Priority);
fn number() -> usize;
fn pend();
fn clear();
}
macro_rules! from_cpu {
($irq:literal) => {
paste::paste! {
pub struct [<FromCpu $irq>];
impl [<FromCpu $irq>] {
fn set_bit(value: bool) {
let system = unsafe { &*SystemPeripheral::PTR };
system
.[<cpu_intr_from_cpu_ $irq>]()
.write(|w| w.[<cpu_intr_from_cpu_ $irq>]().bit(value));
}
}
impl SwPendableInterrupt for [<FromCpu $irq>] {
fn enable(priority: interrupt::Priority) {
let mask = 1 << $irq;
// We don't allow using the same interrupt for multiple executors.
if FROM_CPU_IRQ_USED.fetch_or(mask, Ordering::SeqCst) & mask != 0 {
panic!("FROM_CPU_{} is already used by a different executor.", $irq);
}
// unsafe block because of direct-vectoring on riscv
#[allow(unused_unsafe)]
unsafe {
unwrap!(interrupt::enable(peripherals::Interrupt::[<FROM_CPU_INTR $irq>], priority));
}
}
fn number() -> usize {
$irq
}
fn pend() {
Self::set_bit(true);
}
fn clear() {
Self::set_bit(false);
}
}
}
};
}
// from_cpu!(0); // reserve 0 for thread mode & multi-core
from_cpu!(1);
from_cpu!(2);
from_cpu!(3);
/// Interrupt mode executor.
///
/// This executor runs tasks in interrupt mode. The interrupt handler is set up
/// to poll tasks, and when a task is woken the interrupt is pended from
/// software.
///
/// # Interrupt requirements
///
/// You must write the interrupt handler yourself, and make it call
/// [`Self::on_interrupt()`]
///
/// ```rust,ignore
/// #[interrupt]
/// fn FROM_CPU_INTR1() {
/// unsafe { INT_EXECUTOR.on_interrupt() }
/// }
/// ```
pub struct InterruptExecutor<SWI>
where
SWI: SwPendableInterrupt,
{
core: AtomicUsize,
executor: UnsafeCell<MaybeUninit<raw::Executor>>,
_interrupt: PhantomData<SWI>,
}
unsafe impl<SWI: SwPendableInterrupt> Send for InterruptExecutor<SWI> {}
unsafe impl<SWI: SwPendableInterrupt> Sync for InterruptExecutor<SWI> {}
impl<SWI> InterruptExecutor<SWI>
where
SWI: SwPendableInterrupt,
{
/// Create a new `InterruptExecutor`.
#[inline]
pub const fn new() -> Self {
Self {
core: AtomicUsize::new(usize::MAX),
executor: UnsafeCell::new(MaybeUninit::uninit()),
_interrupt: PhantomData,
}
}
/// Executor interrupt callback.
///
/// # Safety
///
/// You MUST call this from the interrupt handler, and from nowhere else.
// TODO: it would be pretty sweet if we could register our own interrupt handler
// when vectoring is enabled. The user shouldn't need to provide the handler for
// us.
pub unsafe fn on_interrupt(&'static self) {
SWI::clear();
let executor = unsafe { (*self.executor.get()).assume_init_ref() };
executor.poll();
}
/// Start the executor at the given priority level.
///
/// This initializes the executor, enables the interrupt, and returns.
/// The executor keeps running in the background through the interrupt.
///
/// This returns a [`SendSpawner`] you can use to spawn tasks on it. A
/// [`SendSpawner`] is returned instead of a [`Spawner`] because the
/// executor effectively runs in a different "thread" (the interrupt),
/// so spawning tasks on it is effectively sending them.
///
/// To obtain a [`Spawner`] for this executor, use
/// [`Spawner::for_current_executor()`] from a task running in it.
///
/// # Interrupt requirements
///
/// You must write the interrupt handler yourself, and make it call
/// [`Self::on_interrupt()`]
///
/// This method already enables (unmasks) the interrupt, you must NOT do it
/// yourself.
///
/// [`Spawner`]: embassy_executor::Spawner
/// [`Spawner::for_current_executor()`]: embassy_executor::Spawner::for_current_executor()
pub fn start(&'static self, priority: interrupt::Priority) -> SendSpawner {
if self
.core
.compare_exchange(
usize::MAX,
get_core() as usize,
Ordering::Acquire,
Ordering::Relaxed,
)
.is_err()
{
panic!("InterruptExecutor::start() called multiple times on the same executor.");
}
unsafe {
(*self.executor.get())
.as_mut_ptr()
.write(raw::Executor::new(SWI::number() as *mut ()))
}
SWI::enable(priority);
let executor = unsafe { (*self.executor.get()).assume_init_ref() };
executor.spawner().make_send()
}
}

View File

@ -1,35 +0,0 @@
#[cfg(feature = "embassy-executor-thread")]
pub mod thread;
#[cfg(feature = "embassy-executor-thread")]
pub use thread::*;
#[cfg(feature = "embassy-executor-interrupt")]
pub mod interrupt;
#[cfg(feature = "embassy-executor-interrupt")]
pub use interrupt::*;
#[cfg(any(
feature = "embassy-executor-thread",
feature = "embassy-executor-interrupt",
))]
#[export_name = "__pender"]
fn __pender(context: *mut ()) {
let context = (context as usize).to_le_bytes();
cfg_if::cfg_if! {
if #[cfg(feature = "embassy-executor-interrupt")] {
match context[0] {
#[cfg(feature = "embassy-executor-thread")]
0 => thread::pend_thread_mode(context[1] as usize),
1 => FromCpu1::pend(),
2 => FromCpu2::pend(),
3 => FromCpu3::pend(),
_ => {}
}
} else {
pend_thread_mode(context[1] as usize);
}
}
}

View File

@ -1,159 +0,0 @@
//! Multicore-aware thread-mode embassy executor.
use core::marker::PhantomData;
use embassy_executor::{raw, Spawner};
use portable_atomic::{AtomicBool, Ordering};
use crate::{get_core, prelude::interrupt};
#[cfg(multi_core)]
use crate::{
interrupt,
peripherals::{self, SYSTEM},
};
/// global atomic used to keep track of whether there is work to do since sev()
/// is not available on either Xtensa or RISC-V
#[cfg(not(multi_core))]
static SIGNAL_WORK_THREAD_MODE: [AtomicBool; 1] = [AtomicBool::new(false)];
#[cfg(multi_core)]
static SIGNAL_WORK_THREAD_MODE: [AtomicBool; 2] = [AtomicBool::new(false), AtomicBool::new(false)];
#[interrupt]
fn FROM_CPU_INTR0() {
#[cfg(multi_core)]
{
// This interrupt is fired when the thread-mode executor's core needs to be
// woken. It doesn't matter which core handles this interrupt first, the
// point is just to wake up the core that is currently executing
// `waiti`.
let system = unsafe { &*SYSTEM::PTR };
system
.cpu_intr_from_cpu_0()
.write(|w| w.cpu_intr_from_cpu_0().bit(false));
}
}
pub(crate) fn pend_thread_mode(core: usize) {
// Signal that there is work to be done.
SIGNAL_WORK_THREAD_MODE[core].store(true, Ordering::SeqCst);
// If we are pending a task on the current core, we're done. Otherwise, we
// need to make sure the other core wakes up.
#[cfg(multi_core)]
if core != crate::get_core() as usize {
// We need to clear the interrupt from software. We don't actually
// need it to trigger and run the interrupt handler, we just need to
// kick waiti to return.
let system = unsafe { &*SYSTEM::PTR };
system
.cpu_intr_from_cpu_0()
.write(|w| w.cpu_intr_from_cpu_0().bit(true));
}
}
/// Multi-core Xtensa Executor
pub struct Executor {
inner: raw::Executor,
not_send: PhantomData<*mut ()>,
}
impl Executor {
/// Create a new Executor.
pub fn new() -> Self {
#[cfg(multi_core)]
unwrap!(interrupt::enable(
peripherals::Interrupt::FROM_CPU_INTR0,
interrupt::Priority::Priority1,
));
Self {
inner: raw::Executor::new(usize::from_le_bytes([0, get_core() as u8, 0, 0]) as *mut ()),
not_send: PhantomData,
}
}
/// Run the executor.
///
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
/// this executor. Use it to spawn the initial task(s). After `init`
/// returns, the executor starts running the tasks.
///
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is
/// `Copy`), for example by passing it as an argument to the initial
/// tasks.
///
/// This function requires `&'static mut self`. This means you have to store
/// the Executor instance in a place where it'll live forever and grants
/// you mutable access. There's a few ways to do this:
///
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main()
/// -> !`), upgrading its lifetime with `transmute`. (unsafe)
///
/// This function never returns.
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
init(self.inner.spawner());
let cpu = get_core() as usize;
loop {
unsafe {
self.inner.poll();
Self::wait_impl(cpu);
}
}
}
#[cfg(xtensa)]
pub fn wait_impl(cpu: usize) {
// Manual critical section implementation that only masks interrupts handlers.
// We must not acquire the cross-core on dual-core systems because that would
// prevent the other core from doing useful work while this core is sleeping.
let token: critical_section::RawRestoreState;
unsafe { core::arch::asm!("rsil {0}, 5", out(reg) token) };
// we do not care about race conditions between the load and store operations,
// interrupts will only set this value to true.
if SIGNAL_WORK_THREAD_MODE[cpu].load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE[cpu].store(false, Ordering::SeqCst);
// if there is work to do, exit critical section and loop back to polling
unsafe {
core::arch::asm!(
"wsr.ps {0}",
"rsync",
in(reg) token
);
}
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing
// PS.INTLEVEL the critical section ends here
// take care not add code after `waiti` if it needs to be inside the CS
unsafe { core::arch::asm!("waiti 0") }; // critical section ends
// here
}
}
#[cfg(riscv)]
pub fn wait_impl(cpu: usize) {
// we do not care about race conditions between the load and store operations,
// interrupts will only set this value to true.
critical_section::with(|_| {
// if there is work to do, loop back to polling
// TODO can we relax this?
if SIGNAL_WORK_THREAD_MODE[cpu].load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE[cpu].store(false, Ordering::SeqCst);
}
// if not, wait for interrupt
else {
unsafe { core::arch::asm!("wfi") };
}
});
// if an interrupt occurred while waiting, it will be serviced
// here
}
}

View File

@ -1,218 +0,0 @@
//! # Embassy driver
//!
//! ## Overview
//! The `embassy` driver for ESP chips is an essential part of the Embassy
//! embedded async/await runtime and is used by applications to perform
//! time-based operations and schedule asynchronous tasks. It provides a
//! high-level API for handling timers and alarms, abstracting the underlying
//! hardware details, and allowing users to focus on application logic rather
//! than low-level timer management.
//!
//! Here are important details about the module:
//! * `time_driver` module (`time_driver_systimer` or `time_driver_timg`,
//! depends on enabled feature)
//! - This module contains the implementations of the timer drivers for
//! different ESP chips.<br> It includes the `EmbassyTimer` struct, which
//! is responsible for handling alarms and timer events.
//! - `EmbassyTimer` struct represents timer driver for ESP chips. It
//! contains `alarms` - an array of `AlarmState` structs, which describe
//! the state of alarms associated with the timer driver.
//! * `AlarmState` struct
//! - This struct represents the state of an alarm. It contains information
//! about the alarm's timestamp, a callback function to be executed when
//! the alarm triggers, and a context pointer for passing user-defined
//! data to the callback.
//! * `executor` module
//! - This module contains the implementations of a multi-core safe
//! thread-mode and an interrupt-mode executor for Xtensa-based ESP chips.
//!
//! ## Example
//! The following example demonstrates how to use the `embassy` driver to
//! schedule asynchronous tasks.<br> In this example, we use the `embassy`
//! driver to wait for a GPIO 9 pin state to change.
//!
//! ```no_run
//! #[cfg(feature = "embassy-time-systick")]
//! embassy::init(
//! &clocks,
//! esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
//! );
//!
//! #[cfg(feature = "embassy-time-timg0")]
//! embassy::init(&clocks, timer_group0.timer0);
//!
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! // GPIO 9 as input
//! let input = io.pins.gpio9.into_pull_down_input();
//!
//! // Async requires the GPIO interrupt to wake futures
//! esp32c6_hal::interrupt::enable(
//! esp32c6_hal::peripherals::Interrupt::GPIO,
//! esp32c6_hal::interrupt::Priority::Priority1,
//! )
//! .unwrap();
//!
//! let executor = make_static!(Executor::new());
//! executor.run(|spawner| {
//! spawner.spawn(ping(input)).ok();
//! });
//! ```
//!
//! Where `ping` defined as:
//! ```no_run
//! async fn ping(mut pin: Gpio9<Input<PullDown>>) {
//! loop {
//! esp_println::println!("Waiting...");
//! pin.wait_for_rising_edge().await.unwrap();
//! esp_println::println!("Ping!");
//! Timer::after(Duration::from_millis(100)).await;
//! }
//! }
//! ```
//! For more embassy-related examples check out the [examples repo](https://github.com/esp-rs/esp-hal/tree/main/esp32-hal/examples)
//! for a corresponding board.
#[cfg(any(
feature = "embassy-executor-interrupt",
feature = "embassy-executor-thread"
))]
pub mod executor;
use core::cell::Cell;
use embassy_time::driver::{AlarmHandle, Driver};
use crate::{interrupt::Priority, peripherals::Interrupt};
#[cfg_attr(
all(systimer, feature = "embassy-time-systick"),
path = "time_driver_systimer.rs"
)]
#[cfg_attr(
all(timg0, feature = "embassy-time-timg0"),
path = "time_driver_timg.rs"
)]
mod time_driver;
use time_driver::EmbassyTimer;
use crate::clock::Clocks;
/// Initialise embassy, including setting up interrupts for the DMA and async
/// enabled peripherals.
pub fn init(clocks: &Clocks, td: time_driver::TimerType) {
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_IN_CH0, Priority::max()).unwrap();
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_OUT_CH0, Priority::max()).unwrap();
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_IN_CH1, Priority::max()).unwrap();
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_OUT_CH1, Priority::max()).unwrap();
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_IN_CH2, Priority::max()).unwrap();
#[cfg(any(esp32s3, esp32c6, esp32h2))]
crate::interrupt::enable(Interrupt::DMA_OUT_CH2, Priority::max()).unwrap();
#[cfg(esp32s3)]
crate::interrupt::enable(Interrupt::DMA_IN_CH3, Priority::max()).unwrap();
#[cfg(esp32s3)]
crate::interrupt::enable(Interrupt::DMA_OUT_CH3, Priority::max()).unwrap();
#[cfg(any(esp32c3, esp32c2))]
crate::interrupt::enable(Interrupt::DMA_CH0, Priority::max()).unwrap();
#[cfg(esp32c3)]
crate::interrupt::enable(Interrupt::DMA_CH1, Priority::max()).unwrap();
#[cfg(esp32c3)]
crate::interrupt::enable(Interrupt::DMA_CH2, Priority::max()).unwrap();
#[cfg(any(esp32))]
crate::interrupt::enable(Interrupt::SPI1_DMA, Priority::max()).unwrap();
#[cfg(any(esp32, esp32s2))]
crate::interrupt::enable(Interrupt::SPI2_DMA, Priority::max()).unwrap();
#[cfg(any(esp32, esp32s2))]
crate::interrupt::enable(Interrupt::SPI3_DMA, Priority::max()).unwrap();
#[cfg(esp32s2)]
crate::interrupt::enable(Interrupt::SPI4_DMA, Priority::max()).unwrap();
#[cfg(i2s0)]
crate::interrupt::enable(Interrupt::I2S0, Priority::min()).unwrap();
#[cfg(i2s1)]
crate::interrupt::enable(Interrupt::I2S1, Priority::min()).unwrap();
#[cfg(rmt)]
crate::interrupt::enable(Interrupt::RMT, Priority::min()).unwrap();
#[cfg(usb_device)]
crate::interrupt::enable(Interrupt::USB_DEVICE, Priority::min()).unwrap();
#[cfg(all(parl_io, not(esp32h2)))]
crate::interrupt::enable(Interrupt::PARL_IO, Priority::min()).unwrap();
#[cfg(all(parl_io, esp32h2))]
crate::interrupt::enable(Interrupt::PARL_IO_RX, Priority::min()).unwrap();
#[cfg(all(parl_io, esp32h2))]
crate::interrupt::enable(Interrupt::PARL_IO_TX, Priority::min()).unwrap();
#[cfg(uart0)]
crate::interrupt::enable(Interrupt::UART0, Priority::min()).unwrap();
#[cfg(uart1)]
crate::interrupt::enable(Interrupt::UART1, Priority::min()).unwrap();
crate::interrupt::enable(Interrupt::I2C_EXT0, Priority::min()).unwrap();
crate::interrupt::enable(Interrupt::GPIO, Priority::min()).unwrap();
EmbassyTimer::init(clocks, td)
}
pub struct AlarmState {
pub callback: Cell<Option<(fn(*mut ()), *mut ())>>,
pub allocated: Cell<bool>,
}
unsafe impl Send for AlarmState {}
impl AlarmState {
pub const fn new() -> Self {
Self {
callback: Cell::new(None),
allocated: Cell::new(false),
}
}
}
impl Driver for EmbassyTimer {
fn now(&self) -> u64 {
EmbassyTimer::now()
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
critical_section::with(|cs| {
for (i, alarm) in self.alarms.borrow(cs).iter().enumerate() {
if !alarm.allocated.get() {
// set alarm so it is not overwritten
alarm.allocated.set(true);
self.on_alarm_allocated(i);
return Some(AlarmHandle::new(i as u8));
}
}
None
})
}
fn set_alarm_callback(
&self,
alarm: embassy_time::driver::AlarmHandle,
callback: fn(*mut ()),
ctx: *mut (),
) {
let n = alarm.id() as usize;
critical_section::with(|cs| {
let alarm = &self.alarms.borrow(cs)[n];
alarm.callback.set(Some((callback, ctx)));
})
}
fn set_alarm(&self, alarm: embassy_time::driver::AlarmHandle, timestamp: u64) -> bool {
self.set_alarm(alarm, timestamp)
}
}

View File

@ -1,127 +0,0 @@
use critical_section::{CriticalSection, Mutex};
use super::AlarmState;
use crate::{
clock::Clocks,
peripherals,
systimer::{Alarm, SystemTimer, Target},
};
pub const ALARM_COUNT: usize = 3;
pub type TimerType = SystemTimer<'static>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
pub(crate) alarm0: Alarm<Target, 0>,
pub(crate) alarm1: Alarm<Target, 1>,
pub(crate) alarm2: Alarm<Target, 2>,
}
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]),
alarm0: unsafe { Alarm::<_, 0>::conjure() },
alarm1: unsafe { Alarm::<_, 1>::conjure() },
alarm2: unsafe { Alarm::<_, 2>::conjure() },
});
impl EmbassyTimer {
pub(crate) fn now() -> u64 {
SystemTimer::now()
}
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
let alarm = &self.alarms.borrow(cs)[n];
if let Some((f, ctx)) = alarm.callback.get() {
f(ctx);
}
}
pub(super) fn on_alarm_allocated(&self, n: usize) {
match n {
0 => self.alarm0.enable_interrupt(true),
1 => self.alarm1.enable_interrupt(true),
2 => self.alarm2.enable_interrupt(true),
_ => {}
}
}
fn on_interrupt(&self, id: usize) {
critical_section::with(|cs| {
self.clear_interrupt(id);
self.trigger_alarm(id, cs);
})
}
pub fn init(_clocks: &Clocks, _systimer: TimerType) {
use crate::{interrupt, interrupt::Priority, macros::interrupt};
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET0,
Priority::max()
));
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET1,
Priority::max()
));
unwrap!(interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET2,
Priority::max()
));
#[interrupt]
fn SYSTIMER_TARGET0() {
DRIVER.on_interrupt(0);
}
#[interrupt]
fn SYSTIMER_TARGET1() {
DRIVER.on_interrupt(1);
}
#[interrupt]
fn SYSTIMER_TARGET2() {
DRIVER.on_interrupt(2);
}
}
pub(crate) fn set_alarm(
&self,
alarm: embassy_time::driver::AlarmHandle,
timestamp: u64,
) -> bool {
critical_section::with(|_cs| {
let n = alarm.id() as usize;
// The hardware fires the alarm even if timestamp is lower than the current
// time. In this case the interrupt handler will pend a wakeup when we exit the
// critical section.
self.arm(n, timestamp);
});
// In theory, the above comment is true. However, in practice, we seem to be
// missing interrupt for very short timeouts, so let's make sure and catch
// timestamps that already passed. Returning `false` means embassy will
// run one more poll loop.
Self::now() < timestamp
}
fn clear_interrupt(&self, id: usize) {
match id {
0 => self.alarm0.clear_interrupt(),
1 => self.alarm1.clear_interrupt(),
2 => self.alarm2.clear_interrupt(),
_ => {}
}
}
fn arm(&self, id: usize, timestamp: u64) {
match id {
0 => self.alarm0.set_target(timestamp),
1 => self.alarm1.set_target(timestamp),
2 => self.alarm2.set_target(timestamp),
_ => {}
}
}
}

View File

@ -1,117 +0,0 @@
use critical_section::{CriticalSection, Mutex};
use peripherals::TIMG0;
use super::AlarmState;
#[cfg(any(esp32, esp32s2, esp32s3))]
use crate::timer::Timer1;
use crate::{
clock::Clocks,
peripherals,
prelude::*,
timer::{Instance, Timer, Timer0},
};
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
pub const ALARM_COUNT: usize = 1;
#[cfg(any(esp32, esp32s2, esp32s3))]
pub const ALARM_COUNT: usize = 2;
pub type TimerType = Timer<Timer0<TIMG0>>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
}
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]),
});
impl EmbassyTimer {
pub(crate) fn now() -> u64 {
unsafe { Timer0::<TIMG0>::steal() }.now()
}
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
let alarm = &self.alarms.borrow(cs)[n];
if let Some((f, ctx)) = alarm.callback.get() {
f(ctx);
}
}
pub(super) fn on_alarm_allocated(&self, _n: usize) {}
fn on_interrupt<Timer: Instance>(&self, id: u8, mut timer: Timer) {
critical_section::with(|cs| {
timer.clear_interrupt();
self.trigger_alarm(id as usize, cs);
});
}
pub fn init(clocks: &Clocks, mut timer: TimerType) {
use crate::{interrupt, interrupt::Priority};
// set divider to get a 1mhz clock. APB (80mhz) / 80 = 1mhz...
// TODO: assert APB clock is the source and its at the correct speed for the
// divider
timer.set_divider(clocks.apb_clock.to_MHz() as u16);
timer.set_counter_active(true);
unwrap!(interrupt::enable(
peripherals::Interrupt::TG0_T0_LEVEL,
Priority::max()
));
#[cfg(any(esp32, esp32s2, esp32s3))]
unwrap!(interrupt::enable(
peripherals::Interrupt::TG0_T1_LEVEL,
Priority::max()
));
#[interrupt]
fn TG0_T0_LEVEL() {
let timer = unsafe { Timer0::<TIMG0>::steal() };
DRIVER.on_interrupt(0, timer);
}
#[cfg(any(esp32, esp32s2, esp32s3))]
#[interrupt]
fn TG0_T1_LEVEL() {
let timer = unsafe { Timer1::<TIMG0>::steal() };
DRIVER.on_interrupt(1, timer);
}
}
pub(crate) fn set_alarm(
&self,
_alarm: embassy_time::driver::AlarmHandle,
timestamp: u64,
) -> bool {
critical_section::with(|_cs| {
// The hardware fires the alarm even if timestamp is lower than the current
// time. In this case the interrupt handler will pend a wakeup when we exit the
// critical section.
#[cfg(any(esp32, esp32s2, esp32s3))]
if _alarm.id() == 1 {
let mut tg = unsafe { Timer1::<TIMG0>::steal() };
Self::arm(&mut tg, timestamp);
return;
}
let mut tg = unsafe { Timer0::<TIMG0>::steal() };
Self::arm(&mut tg, timestamp);
});
true
}
fn arm<Timer: Instance>(tg: &mut Timer, timestamp: u64) {
tg.load_alarm_value(timestamp);
tg.listen();
tg.set_counter_decrementing(false);
tg.set_auto_reload(false);
tg.set_alarm_active(true);
}
}

View File

@ -1,282 +0,0 @@
//! # Event Task Matrix (ETM)
//!
//! ## Overview
//!
//! Normally, if a peripheral X needs to notify peripheral Y of a particular
//! event, this could only be done via a CPU interrupt from peripheral X, where
//! the CPU notifies peripheral Y on behalf of peripheral X. However, in
//! time-critical applications, the latency introduced by CPU interrupts is
//! non-negligible.
//!
//! With the help of the Event Task Matrix (ETM) module, some peripherals can
//! directly notify other peripherals of events through pre-set connections
//! without the intervention of CPU interrupts. This allows precise and low
//! latency synchronization between peripherals, and lessens the CPUs workload
//! as the CPU no longer needs to handle these events.
//!
//! The ETM module has multiple programmable channels, they are used to connect
//! a particular Event to a particular Task. When an event is activated, the ETM
//! channel will trigger the corresponding task automatically.
//!
//! More information: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/etm.html
//!
//! ## Example
//! ```no_run
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut led = io.pins.gpio1.into_push_pull_output();
//! let button = io.pins.gpio9.into_pull_down_input();
//!
//! // setup ETM
//! let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);
//! let led_task = gpio_ext.channel0_task.toggle(&mut led);
//! let button_event = gpio_ext.channel0_event.falling_edge(button);
//!
//! let etm = Etm::new(peripherals.SOC_ETM);
//! let channel0 = etm.channel0;
//!
//! // make sure the configured channel doesn't get dropped - dropping it will
//! // disable the channel
//! let _configured_channel = channel0.setup(&button_event, &led_task);
//!
//! // the LED is controlled by the button without involving the CPU
//! loop {}
//! ```
use crate::{
peripheral::{Peripheral, PeripheralRef},
system::PeripheralClockControl,
};
/// Unconfigured EtmChannel.
#[non_exhaustive]
pub struct EtmChannel<const C: u8> {}
macro_rules! impl_etm_channel {
($channel: literal, $bank: literal) => {
paste::paste! {
impl EtmChannel<$channel> {
/// Setup the channel
///
/// Enabled the channel and configures the assigned event and task.
pub fn setup<'a, E, T>(self, event: &'a E, task: &'a T) -> EtmConfiguredChannel<'a, E,T,$channel>
where
E: EtmEvent,
T: EtmTask,
{
let etm = unsafe { crate::peripherals::SOC_ETM::steal() };
etm.[< ch $channel _evt_id >]().modify(|_, w| w.[< ch $channel _evt_id >]().variant(event.id()));
etm.[< ch $channel _task_id >]().modify(|_, w| w.[< ch $channel _task_id >]().variant(task.id()));
etm.[< ch_ena_ad $bank _set >]().write(|w| w.[< ch_set $channel >]().set_bit());
EtmConfiguredChannel {
_event: event,
_task: task,
}
}
}
}
};
}
impl_etm_channel!(0, 0);
impl_etm_channel!(1, 0);
impl_etm_channel!(2, 0);
impl_etm_channel!(3, 0);
impl_etm_channel!(4, 0);
impl_etm_channel!(5, 0);
impl_etm_channel!(6, 0);
impl_etm_channel!(7, 0);
impl_etm_channel!(8, 0);
impl_etm_channel!(9, 0);
impl_etm_channel!(10, 0);
impl_etm_channel!(11, 0);
impl_etm_channel!(12, 0);
impl_etm_channel!(13, 0);
impl_etm_channel!(14, 0);
impl_etm_channel!(15, 0);
impl_etm_channel!(16, 0);
impl_etm_channel!(17, 0);
impl_etm_channel!(18, 0);
impl_etm_channel!(19, 0);
impl_etm_channel!(20, 0);
impl_etm_channel!(21, 0);
impl_etm_channel!(22, 0);
impl_etm_channel!(23, 0);
impl_etm_channel!(24, 0);
impl_etm_channel!(25, 0);
impl_etm_channel!(26, 0);
impl_etm_channel!(27, 0);
impl_etm_channel!(28, 0);
impl_etm_channel!(29, 0);
impl_etm_channel!(30, 0);
impl_etm_channel!(31, 0);
impl_etm_channel!(32, 1);
impl_etm_channel!(33, 1);
impl_etm_channel!(34, 1);
impl_etm_channel!(35, 1);
impl_etm_channel!(36, 1);
impl_etm_channel!(37, 1);
impl_etm_channel!(38, 1);
impl_etm_channel!(39, 1);
impl_etm_channel!(40, 1);
impl_etm_channel!(41, 1);
impl_etm_channel!(42, 1);
impl_etm_channel!(43, 1);
impl_etm_channel!(44, 1);
impl_etm_channel!(45, 1);
impl_etm_channel!(46, 1);
impl_etm_channel!(47, 1);
impl_etm_channel!(48, 1);
impl_etm_channel!(49, 1);
macro_rules! impl_disable_helper {
($(($channel:literal, $bank:literal)),+) => {
paste::paste! {
fn disable_channel(channel: u8) {
let etm = unsafe { crate::peripherals::SOC_ETM::steal() };
match channel {
$(
$channel => {etm.[< ch_ena_ad $bank _clr>]().write(|w| w.[< ch_clr $channel >]().set_bit());},
)+
_ => panic!("Unknown channel {}", channel),
}
}
}
};
}
impl_disable_helper!(
(0, 0),
(1, 0),
(2, 0),
(3, 0),
(4, 0),
(5, 0),
(6, 0),
(7, 0),
(8, 0),
(9, 0),
(10, 0),
(11, 0),
(12, 0),
(13, 0),
(14, 0),
(15, 0),
(16, 0),
(17, 0),
(18, 0),
(19, 0),
(20, 0),
(21, 0),
(22, 0),
(23, 0),
(24, 0),
(25, 0),
(26, 0),
(27, 0),
(28, 0),
(29, 0),
(30, 0),
(31, 0),
(32, 1),
(33, 1),
(34, 1),
(35, 1),
(36, 1),
(37, 1),
(38, 1),
(39, 1),
(40, 1),
(41, 1),
(42, 1),
(43, 1),
(44, 1),
(45, 1),
(46, 1),
(47, 1),
(48, 1),
(49, 1)
);
/// A readily configured channel
///
/// The channel is enabled and event and task are configured.
#[non_exhaustive]
pub struct EtmConfiguredChannel<'a, E, T, const C: u8>
where
E: EtmEvent,
T: EtmTask,
{
_event: &'a E,
_task: &'a T,
}
impl<'a, E, T, const C: u8> Drop for EtmConfiguredChannel<'a, E, T, C>
where
E: EtmEvent,
T: EtmTask,
{
fn drop(&mut self) {
debug!("drop {}", C);
disable_channel(C);
}
}
macro_rules! create_etm_struct {
($($num:literal),+) => {
paste::paste! {
/// ETM Instance
///
/// Provides access to all the [EtmChannel]
pub struct Etm<'d> {
_peripheral: PeripheralRef<'d, crate::peripherals::SOC_ETM>,
$(pub [< channel $num >]: EtmChannel<$num>,)+
}
}
};
}
macro_rules! create_etm_constructor {
($($num:literal),+) => {
paste::paste! {
impl<'d> Etm<'d> {
pub fn new(peripheral: impl Peripheral<P = crate::peripherals::SOC_ETM> + 'd) -> Self {
crate::into_ref!(peripheral);
PeripheralClockControl::enable(crate::system::Peripheral::Etm);
Self {
_peripheral: peripheral,
$([< channel $num >]: EtmChannel {},)+
}
}
}
}
};
}
create_etm_struct!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
);
create_etm_constructor!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
);
#[doc(hidden)]
pub trait EtmEvent: private::Sealed {
fn id(&self) -> u8;
}
#[doc(hidden)]
pub trait EtmTask: private::Sealed {
fn id(&self) -> u8;
}
pub(crate) mod private {
pub trait Sealed {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +0,0 @@
//! # Interrupt support
//!
//! ## Overview
//! The `interrupt` driver is a crucial module for ESP chips. Its primary
//! purpose is to manage and handle interrupts, which are asynchronous events
//! requiring immediate attention from the CPU. Interrupts are essential in
//! various applications, such as real-time tasks, I/O communications, and
//! handling external events like hardware signals.
//!
//! The core functionality of the `interrupt` driver revolves around the
//! management of interrupts. When an interrupt occurs, it temporarily stops the
//! ongoing CPU operations, saves its current state, and starts executing the
//! corresponding interrupt service routine (ISR). The interrupt service routine
//! is a user-defined function that performs the necessary actions to handle the
//! specific interrupt. Once the ISR is executed, the driver restores the saved
//! CPU state and resumes normal program execution.
//!
//! In scenarios where multiple interrupts may occur simultaneously, the
//! interrupt driver determines the `priority` of each interrupt. This
//! prioritization ensures that critical or high-priority tasks are handled
//! first. It helps prevent delays in time-sensitive applications and allows the
//! system to allocate resources efficiently. This functionality is provided and
//! implemented by the `priority` enum.
//!
//!
//! ## Example
//! ```no_run
//! #[entry]
//! fn main() -> ! {
//! ...
//! critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int));
//!
//! interrupt::enable(
//! peripherals::Interrupt::FROM_CPU_INTR0,
//! interrupt::Priority::Priority1,
//! )
//! .unwrap();
//!
//! loop {}
//! }
//!
//! #[interrupt]
//! fn FROM_CPU_INTR0() {
//! esp_println::println!("SW interrupt0");
//! critical_section::with(|cs| {
//! SWINT
//! .borrow_ref_mut(cs)
//! .as_mut()
//! .unwrap()
//! .reset(SoftwareInterrupt::SoftwareInterrupt0);
//! });
//! }
//! ```
#[cfg(riscv)]
pub use riscv::*;
#[cfg(xtensa)]
pub use xtensa::*;
#[cfg(riscv)]
mod riscv;
#[cfg(xtensa)]
mod xtensa;

View File

@ -1,801 +0,0 @@
//! Interrupt handling - RISC-V
//!
//! When the `vectored` feature is enabled, CPU interrupts 1 through 15 are
//! reserved for each of the possible interrupt priorities.
//!
//! On chips with a PLIC CPU interrupts 1,2,5,6,9 .. 19 are used.
//!
//! ```rust
//! interrupt1() => Priority::Priority1
//! interrupt2() => Priority::Priority2
//! ...
//! interrupt15() => Priority::Priority15
//! ```
use esp_riscv_rt::riscv::register::{mcause, mtvec};
pub use esp_riscv_rt::TrapFrame;
#[cfg(not(plic))]
pub use self::classic::*;
#[cfg(plic)]
pub use self::plic::*;
use crate::{
peripherals::{self, Interrupt},
Cpu,
};
/// Interrupt kind
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InterruptKind {
/// Level interrupt
Level,
/// Edge interrupt
Edge,
}
/// Enumeration of available CPU interrupts.
/// It is possible to create a handler for each of the interrupts. (e.g.
/// `interrupt3`)
#[repr(u32)]
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CpuInterrupt {
Interrupt1 = 1,
Interrupt2,
Interrupt3,
Interrupt4,
Interrupt5,
Interrupt6,
Interrupt7,
Interrupt8,
Interrupt9,
Interrupt10,
Interrupt11,
Interrupt12,
Interrupt13,
Interrupt14,
Interrupt15,
Interrupt16,
Interrupt17,
Interrupt18,
Interrupt19,
Interrupt20,
Interrupt21,
Interrupt22,
Interrupt23,
Interrupt24,
Interrupt25,
Interrupt26,
Interrupt27,
Interrupt28,
Interrupt29,
Interrupt30,
Interrupt31,
}
/// Interrupt priority levels.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum Priority {
None = 0,
Priority1,
Priority2,
Priority3,
Priority4,
Priority5,
Priority6,
Priority7,
Priority8,
Priority9,
Priority10,
Priority11,
Priority12,
Priority13,
Priority14,
Priority15,
}
impl Priority {
pub fn max() -> Priority {
Priority::Priority15
}
pub fn min() -> Priority {
Priority::Priority1
}
}
#[cfg(feature = "vectored")]
pub use vectored::*;
#[cfg(feature = "vectored")]
mod vectored {
use procmacros::ram;
use super::*;
// Setup interrupts ready for vectoring
#[doc(hidden)]
pub(crate) unsafe fn init_vectoring() {
for (prio, num) in PRIORITY_TO_INTERRUPT.iter().enumerate() {
set_kind(
crate::get_core(),
core::mem::transmute(*num as u32),
InterruptKind::Level,
);
set_priority(
crate::get_core(),
core::mem::transmute(*num as u32),
core::mem::transmute((prio as u8) + 1),
);
enable_cpu_interrupt(core::mem::transmute(*num as u32));
}
}
/// Get the interrupts configured for the core
#[inline]
fn get_configured_interrupts(_core: Cpu, mut status: u128) -> [u128; 16] {
unsafe {
let mut prios = [0u128; 16];
while status != 0 {
let interrupt_nr = status.trailing_zeros() as u16;
// safety: cast is safe because of repr(u16)
let cpu_interrupt: CpuInterrupt =
get_assigned_cpu_interrupt(core::mem::transmute(interrupt_nr as u16));
let prio = get_priority(cpu_interrupt);
prios[prio as usize] |= 1 << (interrupt_nr as usize);
status &= !(1u128 << interrupt_nr);
}
prios
}
}
/// Interrupt Error
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
InvalidInterruptPriority,
}
/// Enables a interrupt at a given priority
///
/// Note that interrupts still need to be enabled globally for interrupts
/// to be serviced.
#[cfg(not(feature = "direct-vectoring"))]
pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> {
if matches!(level, Priority::None) {
return Err(Error::InvalidInterruptPriority);
}
unsafe {
let cpu_interrupt =
core::mem::transmute(PRIORITY_TO_INTERRUPT[(level as usize) - 1] as u32);
map(crate::get_core(), interrupt, cpu_interrupt);
enable_cpu_interrupt(cpu_interrupt);
}
Ok(())
}
/// Enables an interrupt at a given priority, maps it to the given CPU
/// interrupt and assigns the given priority.
///
/// This can be side-effectful since no guarantees can be made about the
/// CPU interrupt not already being in use.
///
/// Note that interrupts still need to be enabled globally for interrupts
/// to be serviced.
#[cfg(feature = "direct-vectoring")]
pub unsafe fn enable(
interrupt: Interrupt,
level: Priority,
cpu_interrupt: CpuInterrupt,
) -> Result<(), Error> {
if matches!(level, Priority::None) {
return Err(Error::InvalidInterruptPriority);
}
unsafe {
map(crate::get_core(), interrupt, cpu_interrupt);
set_priority(crate::get_core(), cpu_interrupt, level);
enable_cpu_interrupt(cpu_interrupt);
}
Ok(())
}
#[ram]
unsafe fn handle_interrupts(cpu_intr: CpuInterrupt, context: &mut TrapFrame) {
let status = get_status(crate::get_core());
// this has no effect on level interrupts, but the interrupt may be an edge one
// so we clear it anyway
clear(crate::get_core(), cpu_intr);
let configured_interrupts = get_configured_interrupts(crate::get_core(), status);
let mut interrupt_mask =
status & configured_interrupts[INTERRUPT_TO_PRIORITY[cpu_intr as usize - 1]];
while interrupt_mask != 0 {
let interrupt_nr = interrupt_mask.trailing_zeros();
// Interrupt::try_from can fail if interrupt already de-asserted:
// silently ignore
if let Ok(interrupt) = peripherals::Interrupt::try_from(interrupt_nr as u8) {
handle_interrupt(interrupt, context)
}
interrupt_mask &= !(1u128 << interrupt_nr);
}
}
#[ram]
unsafe fn handle_interrupt(interrupt: Interrupt, save_frame: &mut TrapFrame) {
extern "C" {
// defined in each hal
fn EspDefaultHandler(interrupt: Interrupt);
}
let handler = peripherals::__EXTERNAL_INTERRUPTS[interrupt as usize]._handler;
if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() {
EspDefaultHandler(interrupt);
} else {
let handler: fn(&mut TrapFrame) = core::mem::transmute(handler);
handler(save_frame);
}
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt1(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt1, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt2(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt2, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt3(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt3, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt4(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt4, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt5(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt5, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt6(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt6, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt7(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt7, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt8(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt8, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt9(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt9, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt10(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt10, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt11(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt11, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt12(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt12, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt13(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt13, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt14(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt14, context)
}
#[no_mangle]
#[ram]
pub unsafe fn interrupt15(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt15, context)
}
#[cfg(plic)]
#[no_mangle]
#[ram]
pub unsafe fn interrupt16(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt16, context)
}
#[cfg(plic)]
#[no_mangle]
#[ram]
pub unsafe fn interrupt17(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt17, context)
}
#[cfg(plic)]
#[no_mangle]
#[ram]
pub unsafe fn interrupt18(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt18, context)
}
#[cfg(plic)]
#[no_mangle]
#[ram]
pub unsafe fn interrupt19(context: &mut TrapFrame) {
handle_interrupts(CpuInterrupt::Interrupt19, context)
}
}
/// # Safety
///
/// This function is called from an assembly trap handler.
#[doc(hidden)]
#[link_section = ".trap.rust"]
#[export_name = "_start_trap_rust_hal"]
pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) {
// User code shouldn't usually take the mutable TrapFrame or the TrapFrame in
// general. However this makes things like preemtive multitasking easier in
// future
extern "C" {
fn interrupt1(frame: &mut TrapFrame);
fn interrupt2(frame: &mut TrapFrame);
fn interrupt3(frame: &mut TrapFrame);
fn interrupt4(frame: &mut TrapFrame);
fn interrupt5(frame: &mut TrapFrame);
fn interrupt6(frame: &mut TrapFrame);
fn interrupt7(frame: &mut TrapFrame);
fn interrupt8(frame: &mut TrapFrame);
fn interrupt9(frame: &mut TrapFrame);
fn interrupt10(frame: &mut TrapFrame);
fn interrupt11(frame: &mut TrapFrame);
fn interrupt12(frame: &mut TrapFrame);
fn interrupt13(frame: &mut TrapFrame);
fn interrupt14(frame: &mut TrapFrame);
fn interrupt15(frame: &mut TrapFrame);
fn interrupt16(frame: &mut TrapFrame);
fn interrupt17(frame: &mut TrapFrame);
fn interrupt18(frame: &mut TrapFrame);
fn interrupt19(frame: &mut TrapFrame);
fn interrupt20(frame: &mut TrapFrame);
fn interrupt21(frame: &mut TrapFrame);
fn interrupt22(frame: &mut TrapFrame);
fn interrupt23(frame: &mut TrapFrame);
fn interrupt24(frame: &mut TrapFrame);
fn interrupt25(frame: &mut TrapFrame);
fn interrupt26(frame: &mut TrapFrame);
fn interrupt27(frame: &mut TrapFrame);
fn interrupt28(frame: &mut TrapFrame);
fn interrupt29(frame: &mut TrapFrame);
fn interrupt30(frame: &mut TrapFrame);
fn interrupt31(frame: &mut TrapFrame);
// Defined in `esp-riscv-rt`
pub fn DefaultHandler();
}
let cause = mcause::read();
if cause.is_exception() {
extern "C" {
fn ExceptionHandler(tf: *mut TrapFrame);
}
ExceptionHandler(trap_frame);
} else {
#[cfg(feature = "interrupt-preemption")]
let interrupt_priority = _handle_priority();
let code = mcause::read().code();
match code {
1 => interrupt1(trap_frame.as_mut().unwrap()),
2 => interrupt2(trap_frame.as_mut().unwrap()),
3 => interrupt3(trap_frame.as_mut().unwrap()),
4 => interrupt4(trap_frame.as_mut().unwrap()),
5 => interrupt5(trap_frame.as_mut().unwrap()),
6 => interrupt6(trap_frame.as_mut().unwrap()),
7 => interrupt7(trap_frame.as_mut().unwrap()),
8 => interrupt8(trap_frame.as_mut().unwrap()),
9 => interrupt9(trap_frame.as_mut().unwrap()),
10 => interrupt10(trap_frame.as_mut().unwrap()),
11 => interrupt11(trap_frame.as_mut().unwrap()),
12 => interrupt12(trap_frame.as_mut().unwrap()),
13 => interrupt13(trap_frame.as_mut().unwrap()),
14 => interrupt14(trap_frame.as_mut().unwrap()),
15 => interrupt15(trap_frame.as_mut().unwrap()),
16 => interrupt16(trap_frame.as_mut().unwrap()),
17 => interrupt17(trap_frame.as_mut().unwrap()),
18 => interrupt18(trap_frame.as_mut().unwrap()),
19 => interrupt19(trap_frame.as_mut().unwrap()),
20 => interrupt20(trap_frame.as_mut().unwrap()),
21 => interrupt21(trap_frame.as_mut().unwrap()),
22 => interrupt22(trap_frame.as_mut().unwrap()),
23 => interrupt23(trap_frame.as_mut().unwrap()),
24 => interrupt24(trap_frame.as_mut().unwrap()),
25 => interrupt25(trap_frame.as_mut().unwrap()),
26 => interrupt26(trap_frame.as_mut().unwrap()),
27 => interrupt27(trap_frame.as_mut().unwrap()),
28 => interrupt28(trap_frame.as_mut().unwrap()),
29 => interrupt29(trap_frame.as_mut().unwrap()),
30 => interrupt30(trap_frame.as_mut().unwrap()),
31 => interrupt31(trap_frame.as_mut().unwrap()),
_ => DefaultHandler(),
};
#[cfg(feature = "interrupt-preemption")]
_restore_priority(interrupt_priority);
}
}
#[doc(hidden)]
#[no_mangle]
pub fn _setup_interrupts() {
extern "C" {
static _vector_table: *const u32;
}
unsafe {
// disable all known interrupts
// at least after the 2nd stage bootloader there are some interrupts enabled
// (e.g. UART)
for peripheral_interrupt in 0..255 {
crate::soc::peripherals::Interrupt::try_from(peripheral_interrupt)
.map(|intr| {
#[cfg(multi_core)]
disable(Cpu::AppCpu, intr);
disable(Cpu::ProCpu, intr);
})
.ok();
}
let vec_table = &_vector_table as *const _ as usize;
mtvec::write(vec_table, mtvec::TrapMode::Vectored);
#[cfg(feature = "vectored")]
crate::interrupt::init_vectoring();
};
#[cfg(plic)]
unsafe {
core::arch::asm!("csrw mie, {0}", in(reg) u32::MAX);
}
}
/// Disable the given peripheral interrupt.
pub fn disable(_core: Cpu, interrupt: Interrupt) {
unsafe {
let interrupt_number = interrupt as isize;
let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32;
// set to 0 to disable the peripheral interrupt
intr_map_base.offset(interrupt_number).write_volatile(0);
}
}
/// Get status of peripheral interrupts
#[inline]
pub fn get_status(_core: Cpu) -> u128 {
#[cfg(large_intr_status)]
unsafe {
((*crate::peripherals::INTERRUPT_CORE0::PTR)
.intr_status_reg_0()
.read()
.bits() as u128)
| ((*crate::peripherals::INTERRUPT_CORE0::PTR)
.intr_status_reg_1()
.read()
.bits() as u128)
<< 32
| ((*crate::peripherals::INTERRUPT_CORE0::PTR)
.int_status_reg_2()
.read()
.bits() as u128)
<< 64
}
#[cfg(not(large_intr_status))]
unsafe {
((*crate::peripherals::INTERRUPT_CORE0::PTR)
.intr_status_reg_0()
.read()
.bits() as u128)
| ((*crate::peripherals::INTERRUPT_CORE0::PTR)
.intr_status_reg_1()
.read()
.bits() as u128)
<< 32
}
}
/// Assign a peripheral interrupt to an CPU interrupt.
///
/// Great care must be taken when using the `vectored` feature (enabled by
/// default). Avoid interrupts 1 - 15 when interrupt vectoring is enabled.
pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
let interrupt_number = interrupt as isize;
let cpu_interrupt_number = which as isize;
let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32;
intr_map_base
.offset(interrupt_number)
.write_volatile(cpu_interrupt_number as u32);
}
/// Get cpu interrupt assigned to peripheral interrupt
#[inline]
unsafe fn get_assigned_cpu_interrupt(interrupt: Interrupt) -> CpuInterrupt {
let interrupt_number = interrupt as isize;
let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32;
let cpu_intr = intr_map_base.offset(interrupt_number).read_volatile();
core::mem::transmute(cpu_intr)
}
#[cfg(not(plic))]
mod classic {
use super::{CpuInterrupt, InterruptKind, Priority};
use crate::Cpu;
pub(super) const PRIORITY_TO_INTERRUPT: [usize; 15] =
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
pub(super) const INTERRUPT_TO_PRIORITY: [usize; 15] =
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
/// Enable a CPU interrupt
pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) {
let cpu_interrupt_number = which as isize;
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
intr.cpu_int_enable()
.modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits()));
}
/// Set the interrupt kind (i.e. level or edge) of an CPU interrupt
///
/// This is safe to call when the `vectored` feature is enabled. The
/// vectored interrupt handler will take care of clearing edge interrupt
/// bits.
pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) {
unsafe {
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
let cpu_interrupt_number = which as isize;
let interrupt_type = match kind {
InterruptKind::Level => 0,
InterruptKind::Edge => 1,
};
intr.cpu_int_type().modify(|r, w| {
w.bits(
r.bits() & !(1 << cpu_interrupt_number)
| (interrupt_type << cpu_interrupt_number),
)
});
}
}
/// Set the priority level of an CPU interrupt
///
/// Great care must be taken when using the `vectored` feature (enabled by
/// default). Avoid changing the priority of interrupts 1 - 15 when
/// interrupt vectoring is enabled.
pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) {
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
let cpu_interrupt_number = which as isize;
let intr_prio_base = intr.cpu_int_pri_0().as_ptr();
intr_prio_base
.offset(cpu_interrupt_number)
.write_volatile(priority as u32);
}
/// Clear a CPU interrupt
#[inline]
pub fn clear(_core: Cpu, which: CpuInterrupt) {
unsafe {
let cpu_interrupt_number = which as isize;
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
intr.cpu_int_clear()
.write(|w| w.bits(1 << cpu_interrupt_number));
}
}
/// Get interrupt priority
#[inline]
pub(super) unsafe extern "C" fn get_priority(cpu_interrupt: CpuInterrupt) -> Priority {
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
let intr_prio_base = intr.cpu_int_pri_0().as_ptr();
let prio = intr_prio_base
.offset(cpu_interrupt as isize)
.read_volatile();
core::mem::transmute(prio as u8)
}
#[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))]
#[no_mangle]
#[link_section = ".trap"]
pub(super) unsafe extern "C" fn _handle_priority() -> u32 {
use super::mcause;
use crate::riscv;
let interrupt_id: usize = mcause::read().code(); // MSB is whether its exception or interrupt.
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
let interrupt_priority = intr
.cpu_int_pri_0()
.as_ptr()
.offset(interrupt_id as isize)
.read_volatile();
let prev_interrupt_priority = intr.cpu_int_thresh().read().bits();
if interrupt_priority < 15 {
// leave interrupts disabled if interrupt is of max priority.
intr.cpu_int_thresh()
.write(|w| w.bits(interrupt_priority + 1)); // set the prio threshold to 1 more than current interrupt prio
unsafe {
riscv::interrupt::enable();
}
}
prev_interrupt_priority
}
#[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))]
#[no_mangle]
#[link_section = ".trap"]
pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) {
use crate::riscv;
unsafe {
riscv::interrupt::disable();
}
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
intr.cpu_int_thresh().write(|w| w.bits(stored_prio));
}
}
#[cfg(plic)]
mod plic {
use super::{CpuInterrupt, InterruptKind, Priority};
use crate::Cpu;
// don't use interrupts reserved for CLIC (0,3,4,7)
// for some reason also CPU interrupt 8 doesn't work by default since it's
// disabled after reset - so don't use that, too
pub(super) const PRIORITY_TO_INTERRUPT: [usize; 15] =
[1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
pub(super) const INTERRUPT_TO_PRIORITY: [usize; 19] = [
1, 2, 0, 0, 3, 4, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
];
const DR_REG_PLIC_MX_BASE: u32 = 0x20001000;
const PLIC_MXINT_ENABLE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x0;
const PLIC_MXINT_TYPE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x4;
const PLIC_MXINT_CLEAR_REG: u32 = DR_REG_PLIC_MX_BASE + 0x8;
const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10;
#[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))]
const PLIC_MXINT_THRESH_REG: u32 = DR_REG_PLIC_MX_BASE + 0x90;
/// Enable a CPU interrupt
pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) {
let cpu_interrupt_number = which as isize;
let mxint_enable = PLIC_MXINT_ENABLE_REG as *mut u32;
unsafe {
mxint_enable.write_volatile(mxint_enable.read_volatile() | 1 << cpu_interrupt_number);
}
}
/// Set the interrupt kind (i.e. level or edge) of an CPU interrupt
///
/// This is safe to call when the `vectored` feature is enabled. The
/// vectored interrupt handler will take care of clearing edge interrupt
/// bits.
pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) {
unsafe {
let intr = PLIC_MXINT_TYPE_REG as *mut u32;
let cpu_interrupt_number = which as isize;
let interrupt_type = match kind {
InterruptKind::Level => 0,
InterruptKind::Edge => 1,
};
intr.write_volatile(
intr.read_volatile() & !(1 << cpu_interrupt_number)
| (interrupt_type << cpu_interrupt_number),
);
}
}
/// Set the priority level of an CPU interrupt
///
/// Great care must be taken when using the `vectored` feature (enabled by
/// default). Avoid changing the priority of interrupts 1 - 15 when
/// interrupt vectoring is enabled.
pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) {
let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32;
let cpu_interrupt_number = which as isize;
plic_mxint_pri_ptr
.offset(cpu_interrupt_number)
.write_volatile(priority as u32);
}
/// Clear a CPU interrupt
#[inline]
pub fn clear(_core: Cpu, which: CpuInterrupt) {
unsafe {
let cpu_interrupt_number = which as isize;
let intr = PLIC_MXINT_CLEAR_REG as *mut u32;
intr.write_volatile(1 << cpu_interrupt_number);
}
}
/// Get interrupt priority
#[inline]
pub(super) unsafe extern "C" fn get_priority(cpu_interrupt: CpuInterrupt) -> Priority {
let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32;
let cpu_interrupt_number = cpu_interrupt as isize;
let prio = plic_mxint_pri_ptr
.offset(cpu_interrupt_number)
.read_volatile();
core::mem::transmute(prio as u8)
}
#[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))]
#[no_mangle]
#[link_section = ".trap"]
pub(super) unsafe extern "C" fn _handle_priority() -> u32 {
use super::mcause;
use crate::riscv;
let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32;
let interrupt_id: isize = mcause::read().code().try_into().unwrap(); // MSB is whether its exception or interrupt.
let interrupt_priority = plic_mxint_pri_ptr.offset(interrupt_id).read_volatile();
let thresh_reg = PLIC_MXINT_THRESH_REG as *mut u32;
let prev_interrupt_priority = thresh_reg.read_volatile() & 0x000000FF;
// this is a u8 according to esp-idf, so mask everything else.
if interrupt_priority < 15 {
// leave interrupts disabled if interrupt is of max priority.
thresh_reg.write_volatile(interrupt_priority + 1);
unsafe {
riscv::interrupt::enable();
}
}
prev_interrupt_priority
}
#[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))]
#[no_mangle]
#[link_section = ".trap"]
pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) {
use crate::riscv;
unsafe {
riscv::interrupt::disable();
}
let thresh_reg = PLIC_MXINT_THRESH_REG as *mut u32;
thresh_reg.write_volatile(stored_prio);
}
}

View File

@ -1,570 +0,0 @@
use xtensa_lx::interrupt::{self, InterruptNumber};
use xtensa_lx_rt::exception::Context;
use crate::{
peripherals::{self, Interrupt},
Cpu,
};
/// Enumeration of available CPU interrupts
///
/// It's possible to create one handler per priority level. (e.g
/// `level1_interrupt`)
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u32)]
pub enum CpuInterrupt {
Interrupt0LevelPriority1 = 0,
Interrupt1LevelPriority1,
Interrupt2LevelPriority1,
Interrupt3LevelPriority1,
Interrupt4LevelPriority1,
Interrupt5LevelPriority1,
Interrupt6Timer0Priority1,
Interrupt7SoftwarePriority1,
Interrupt8LevelPriority1,
Interrupt9LevelPriority1,
Interrupt10EdgePriority1,
Interrupt11ProfilingPriority3,
Interrupt12LevelPriority1,
Interrupt13LevelPriority1,
Interrupt14NmiPriority7,
Interrupt15Timer1Priority3,
Interrupt16Timer2Priority5,
Interrupt17LevelPriority1,
Interrupt18LevelPriority1,
Interrupt19LevelPriority2,
Interrupt20LevelPriority2,
Interrupt21LevelPriority2,
Interrupt22EdgePriority3,
Interrupt23LevelPriority3,
Interrupt24LevelPriority4,
Interrupt25LevelPriority4,
Interrupt26LevelPriority5,
Interrupt27LevelPriority3,
Interrupt28EdgePriority4,
Interrupt29SoftwarePriority3,
Interrupt30EdgePriority4,
Interrupt31EdgePriority5,
}
/// Assign a peripheral interrupt to an CPU interrupt
///
/// Great care **must** be taken when using this function with interrupt
/// vectoring (enabled by default). Avoid the following CPU interrupts:
/// - Interrupt1LevelPriority1
/// - Interrupt19LevelPriority2
/// - Interrupt23LevelPriority3
/// - Interrupt10EdgePriority1
/// - Interrupt22EdgePriority3
/// As they are preallocated for interrupt vectoring.
///
/// Note: this only maps the interrupt to the CPU interrupt. The CPU interrupt
/// still needs to be enabled afterwards
pub unsafe fn map(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
let interrupt_number = interrupt as isize;
let cpu_interrupt_number = which as isize;
let intr_map_base = match core {
Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map().as_ptr(),
#[cfg(multi_core)]
Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map().as_ptr(),
};
intr_map_base
.offset(interrupt_number)
.write_volatile(cpu_interrupt_number as u32);
}
/// Disable the given peripheral interrupt
pub fn disable(core: Cpu, interrupt: Interrupt) {
unsafe {
let interrupt_number = interrupt as isize;
let intr_map_base = match core {
Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map().as_ptr(),
#[cfg(multi_core)]
Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map().as_ptr(),
};
// To disable an interrupt, map it to a CPU peripheral interrupt
intr_map_base
.offset(interrupt_number)
.write_volatile(CpuInterrupt::Interrupt16Timer2Priority5 as _);
}
}
/// Clear the given CPU interrupt
pub fn clear(_core: Cpu, which: CpuInterrupt) {
unsafe {
xtensa_lx::interrupt::clear(1 << which as u32);
}
}
/// Get status of peripheral interrupts
pub fn get_status(core: Cpu) -> u128 {
unsafe {
#[allow(unused_mut)]
let mut status = match core {
Cpu::ProCpu => {
((*core0_interrupt_peripheral())
.pro_intr_status_0()
.read()
.bits() as u128)
| ((*core0_interrupt_peripheral())
.pro_intr_status_1()
.read()
.bits() as u128)
<< 32
| ((*core0_interrupt_peripheral())
.pro_intr_status_2()
.read()
.bits() as u128)
<< 64
}
#[cfg(multi_core)]
Cpu::AppCpu => {
((*core1_interrupt_peripheral())
.app_intr_status_0()
.read()
.bits() as u128)
| ((*core1_interrupt_peripheral())
.app_intr_status_1()
.read()
.bits() as u128)
<< 32
| ((*core1_interrupt_peripheral())
.app_intr_status_2()
.read()
.bits() as u128)
<< 64
}
};
#[cfg(feature = "esp32s3")]
match core {
Cpu::ProCpu => {
status |= ((*core0_interrupt_peripheral())
.pro_intr_status_3()
.read()
.bits() as u128)
<< 96;
}
#[cfg(multi_core)]
Cpu::AppCpu => {
status |= ((*core1_interrupt_peripheral())
.app_intr_status_3()
.read()
.bits() as u128)
<< 96;
}
}
status
}
}
#[cfg(esp32)]
unsafe fn core0_interrupt_peripheral() -> *const crate::peripherals::dport::RegisterBlock {
crate::peripherals::DPORT::PTR
}
#[cfg(esp32)]
unsafe fn core1_interrupt_peripheral() -> *const crate::peripherals::dport::RegisterBlock {
crate::peripherals::DPORT::PTR
}
#[cfg(any(esp32s2, esp32s3))]
unsafe fn core0_interrupt_peripheral() -> *const crate::peripherals::interrupt_core0::RegisterBlock
{
crate::peripherals::INTERRUPT_CORE0::PTR
}
#[cfg(esp32s3)]
unsafe fn core1_interrupt_peripheral() -> *const crate::peripherals::interrupt_core1::RegisterBlock
{
crate::peripherals::INTERRUPT_CORE1::PTR
}
#[cfg(feature = "vectored")]
pub use vectored::*;
#[cfg(feature = "vectored")]
mod vectored {
use procmacros::ram;
use super::*;
use crate::get_core;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
InvalidInterrupt,
}
/// Interrupt priority levels.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum Priority {
None = 0,
Priority1,
Priority2,
Priority3,
}
impl Priority {
pub fn max() -> Priority {
Priority::Priority3
}
pub fn min() -> Priority {
Priority::Priority1
}
}
impl CpuInterrupt {
#[inline]
fn level(&self) -> Priority {
match self {
CpuInterrupt::Interrupt0LevelPriority1
| CpuInterrupt::Interrupt1LevelPriority1
| CpuInterrupt::Interrupt2LevelPriority1
| CpuInterrupt::Interrupt3LevelPriority1
| CpuInterrupt::Interrupt4LevelPriority1
| CpuInterrupt::Interrupt5LevelPriority1
| CpuInterrupt::Interrupt6Timer0Priority1
| CpuInterrupt::Interrupt7SoftwarePriority1
| CpuInterrupt::Interrupt8LevelPriority1
| CpuInterrupt::Interrupt9LevelPriority1
| CpuInterrupt::Interrupt10EdgePriority1
| CpuInterrupt::Interrupt12LevelPriority1
| CpuInterrupt::Interrupt13LevelPriority1
| CpuInterrupt::Interrupt17LevelPriority1
| CpuInterrupt::Interrupt18LevelPriority1 => Priority::Priority1,
CpuInterrupt::Interrupt19LevelPriority2
| CpuInterrupt::Interrupt20LevelPriority2
| CpuInterrupt::Interrupt21LevelPriority2 => Priority::Priority2,
CpuInterrupt::Interrupt11ProfilingPriority3
| CpuInterrupt::Interrupt15Timer1Priority3
| CpuInterrupt::Interrupt22EdgePriority3
| CpuInterrupt::Interrupt27LevelPriority3
| CpuInterrupt::Interrupt29SoftwarePriority3
| CpuInterrupt::Interrupt23LevelPriority3 => Priority::Priority3,
// we direct these to None because we do not support interrupts at this level
// through Rust
CpuInterrupt::Interrupt24LevelPriority4
| CpuInterrupt::Interrupt25LevelPriority4
| CpuInterrupt::Interrupt28EdgePriority4
| CpuInterrupt::Interrupt30EdgePriority4
| CpuInterrupt::Interrupt31EdgePriority5
| CpuInterrupt::Interrupt16Timer2Priority5
| CpuInterrupt::Interrupt26LevelPriority5
| CpuInterrupt::Interrupt14NmiPriority7 => Priority::None,
}
}
}
/// Get the interrupts configured for the core
#[inline]
fn get_configured_interrupts(core: Cpu, mut status: u128) -> [u128; 8] {
unsafe {
let intr_map_base = match core {
Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map().as_ptr(),
#[cfg(multi_core)]
Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map().as_ptr(),
};
let mut levels = [0u128; 8];
while status != 0 {
let interrupt_nr = status.trailing_zeros();
let i = interrupt_nr as isize;
let cpu_interrupt = intr_map_base.offset(i).read_volatile();
// safety: cast is safe because of repr(u32)
let cpu_interrupt: CpuInterrupt = core::mem::transmute(cpu_interrupt);
let level = cpu_interrupt.level() as u8 as usize;
levels[level] |= 1 << i;
status &= !(1u128 << interrupt_nr);
}
levels
}
}
/// Enable the given peripheral interrupt
pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> {
let cpu_interrupt =
interrupt_level_to_cpu_interrupt(level, chip_specific::interrupt_is_edge(interrupt))?;
unsafe {
map(get_core(), interrupt, cpu_interrupt);
xtensa_lx::interrupt::enable_mask(
xtensa_lx::interrupt::get_mask() | 1 << cpu_interrupt as u32,
);
}
Ok(())
}
fn interrupt_level_to_cpu_interrupt(
level: Priority,
is_edge: bool,
) -> Result<CpuInterrupt, Error> {
Ok(if is_edge {
match level {
Priority::None => return Err(Error::InvalidInterrupt),
Priority::Priority1 => CpuInterrupt::Interrupt10EdgePriority1,
Priority::Priority2 => return Err(Error::InvalidInterrupt),
Priority::Priority3 => CpuInterrupt::Interrupt22EdgePriority3,
}
} else {
match level {
Priority::None => return Err(Error::InvalidInterrupt),
Priority::Priority1 => CpuInterrupt::Interrupt1LevelPriority1,
Priority::Priority2 => CpuInterrupt::Interrupt19LevelPriority2,
Priority::Priority3 => CpuInterrupt::Interrupt23LevelPriority3,
}
})
}
// TODO use CpuInterrupt::LevelX.mask() // TODO make it const
const CPU_INTERRUPT_LEVELS: [u32; 8] = [
0b_0000_0000_0000_0000_0000_0000_0000_0000, // Dummy level 0
0b_0000_0000_0000_0110_0011_0111_1111_1111, // Level_1
0b_0000_0000_0011_1000_0000_0000_0000_0000, // Level 2
0b_0010_1000_1100_0000_1000_1000_0000_0000, // Level 3
0b_0101_0011_0000_0000_0000_0000_0000_0000, // Level 4
0b_1000_0100_0000_0001_0000_0000_0000_0000, // Level 5
0b_0000_0000_0000_0000_0000_0000_0000_0000, // Level 6
0b_0000_0000_0000_0000_0100_0000_0000_0000, // Level 7
];
const CPU_INTERRUPT_INTERNAL: u32 = 0b_0010_0000_0000_0001_1000_1000_1100_0000;
const CPU_INTERRUPT_EDGE: u32 = 0b_0111_0000_0100_0000_0000_1100_1000_0000;
#[inline]
fn cpu_interrupt_nr_to_cpu_interrupt_handler(
number: u32,
) -> Option<unsafe extern "C" fn(u32, save_frame: &mut Context)> {
use xtensa_lx_rt::*;
// we're fortunate that all esp variants use the same CPU interrupt layout
Some(match number {
6 => Timer0,
7 => Software0,
11 => Profiling,
14 => NMI,
15 => Timer1,
16 => Timer2,
29 => Software1,
_ => return None,
})
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_1_interrupt(level: u32, save_frame: &mut Context) {
handle_interrupts(level, save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_2_interrupt(level: u32, save_frame: &mut Context) {
handle_interrupts(level, save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_3_interrupt(level: u32, save_frame: &mut Context) {
handle_interrupts(level, save_frame)
}
#[ram]
unsafe fn handle_interrupts(level: u32, save_frame: &mut Context) {
let cpu_interrupt_mask =
interrupt::get() & interrupt::get_mask() & CPU_INTERRUPT_LEVELS[level as usize];
if cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL != 0 {
let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL;
let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros();
if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
interrupt::clear(1 << cpu_interrupt_nr);
}
if let Some(handler) = cpu_interrupt_nr_to_cpu_interrupt_handler(cpu_interrupt_nr) {
handler(level, save_frame);
}
} else {
if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_EDGE;
let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros();
interrupt::clear(1 << cpu_interrupt_nr);
// for edge interrupts cannot rely on the interrupt status
// register, therefore call all registered
// handlers for current level
let interrupt_levels =
get_configured_interrupts(crate::get_core(), chip_specific::INTERRUPT_EDGE);
let interrupt_mask = interrupt_levels[level as usize];
let mut interrupt_mask = interrupt_mask & chip_specific::INTERRUPT_EDGE;
loop {
let interrupt_nr = interrupt_mask.trailing_zeros();
if let Ok(interrupt) = peripherals::Interrupt::try_from(interrupt_nr as u16) {
handle_interrupt(level, interrupt, save_frame)
} else {
break;
}
interrupt_mask &= !(1u128 << interrupt_nr);
}
} else {
// finally check periperal sources and fire of handlers from pac
// peripheral mapped interrupts are cleared by the peripheral
let status = get_status(crate::get_core());
let interrupt_levels = get_configured_interrupts(crate::get_core(), status);
let interrupt_mask = status & interrupt_levels[level as usize];
let interrupt_nr = interrupt_mask.trailing_zeros();
// Interrupt::try_from can fail if interrupt already de-asserted:
// silently ignore
if let Ok(interrupt) = peripherals::Interrupt::try_from(interrupt_nr as u16) {
handle_interrupt(level, interrupt, save_frame);
}
}
}
}
#[ram]
unsafe fn handle_interrupt(level: u32, interrupt: Interrupt, save_frame: &mut Context) {
extern "C" {
// defined in each hal
fn EspDefaultHandler(level: u32, interrupt: Interrupt);
}
let handler = peripherals::__INTERRUPTS[interrupt.number() as usize]._handler;
if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() {
EspDefaultHandler(level, interrupt);
} else {
let handler: fn(&mut Context) = core::mem::transmute(handler);
handler(save_frame);
}
}
#[cfg(esp32)]
mod chip_specific {
use super::*;
pub const INTERRUPT_EDGE: u128 =
0b_0000_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0011_1111_1100_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0000;
#[inline]
pub fn interrupt_is_edge(interrupt: Interrupt) -> bool {
use peripherals::Interrupt::*;
[
TG0_T0_EDGE,
TG0_T1_EDGE,
TG0_WDT_EDGE,
TG0_LACT_EDGE,
TG1_T0_EDGE,
TG1_T1_EDGE,
TG1_WDT_EDGE,
TG1_LACT_EDGE,
]
.contains(&interrupt)
}
}
#[cfg(esp32s2)]
mod chip_specific {
use super::*;
pub const INTERRUPT_EDGE: u128 =
0b_0000_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0011_1011_1111_1100_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0000;
#[inline]
pub fn interrupt_is_edge(interrupt: Interrupt) -> bool {
use peripherals::Interrupt::*;
[
TG0_T0_EDGE,
TG0_T1_EDGE,
TG0_WDT_EDGE,
TG0_LACT_EDGE,
TG1_T0_EDGE,
TG1_T1_EDGE,
TG1_WDT_EDGE,
TG1_LACT_EDGE,
SYSTIMER_TARGET0,
SYSTIMER_TARGET1,
SYSTIMER_TARGET2,
]
.contains(&interrupt)
}
}
#[cfg(esp32s3)]
mod chip_specific {
use super::*;
pub const INTERRUPT_EDGE: u128 = 0;
#[inline]
pub fn interrupt_is_edge(_interrupt: Interrupt) -> bool {
false
}
}
}
mod raw {
use super::*;
extern "C" {
#[cfg(not(feature = "vectored"))]
fn level1_interrupt(save_frame: &mut Context);
#[cfg(not(feature = "vectored"))]
fn level2_interrupt(save_frame: &mut Context);
#[cfg(not(feature = "vectored"))]
fn level3_interrupt(save_frame: &mut Context);
fn level4_interrupt(save_frame: &mut Context);
fn level5_interrupt(save_frame: &mut Context);
fn level6_interrupt(save_frame: &mut Context);
fn level7_interrupt(save_frame: &mut Context);
}
#[no_mangle]
#[link_section = ".rwtext"]
#[cfg(not(feature = "vectored"))]
unsafe fn __level_1_interrupt(_level: u32, save_frame: &mut Context) {
level1_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
#[cfg(not(feature = "vectored"))]
unsafe fn __level_2_interrupt(_level: u32, save_frame: &mut Context) {
level2_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
#[cfg(not(feature = "vectored"))]
unsafe fn __level_3_interrupt(_level: u32, save_frame: &mut Context) {
level3_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_4_interrupt(_level: u32, save_frame: &mut Context) {
level4_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_5_interrupt(_level: u32, save_frame: &mut Context) {
level5_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_6_interrupt(_level: u32, save_frame: &mut Context) {
level6_interrupt(save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe fn __level_7_interrupt(_level: u32, save_frame: &mut Context) {
level7_interrupt(save_frame)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +0,0 @@
//! # LEDC (LED PWM Controller) peripheral control
//!
//! Currently only supports fixed-frequency output. Interrupts are not currently
//! implemented. High Speed channels are available for the ESP32 only, while Low
//! Speed channels are available for all supported chips.
//!
//! # LowSpeed Example:
//!
//! The following will configure the Low Speed Channel0 to 24kHz output with
//! 10% duty using the ABPClock
//!
//! ```no_run
//! let mut ledc = LEDC::new(peripherals.LEDC, &clock_control);
//! ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
//!
//! let mut lstimer0 = ledc.get_timer::<LowSpeed>(timer::Number::Timer0);
//! lstimer0
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::LSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//!
//! let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
//! channel0
//! .configure(channel::config::Config {
//! timer: &lstimer0,
//! duty: 10,
//! })
//! .unwrap();
//! ```
//!
//! # HighSpeed Example (ESP32 only):
//!
//! The following will configure the High Speed Channel0 to 24kHz output with
//! 10% duty using the ABPClock
//!
//! ```no_run
//! let ledc = LEDC::new(peripherals.LEDC, &clock_control);
//!
//! let mut hstimer0 = ledc.get_timer::<HighSpeed>(timer::Number::Timer0);
//! hstimer0
//! .configure(timer::config::Config {
//! duty: timer::config::Duty::Duty5Bit,
//! clock_source: timer::HSClockSource::APBClk,
//! frequency: 24u32.kHz(),
//! })
//! .unwrap();
//!
//! let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
//! channel0
//! .configure(channel::config::Config {
//! timer: &hstimer0,
//! duty: 10,
//! })
//! .unwrap();
//! ```
//!
//! # TODO
//!
//! - Source clock selection
//! - Interrupts
use self::{
channel::Channel,
timer::{Timer, TimerSpeed},
};
use crate::{
clock::Clocks,
gpio::OutputPin,
peripheral::{Peripheral, PeripheralRef},
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
};
pub mod channel;
pub mod timer;
/// Global slow clock source
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum LSGlobalClkSource {
APBClk,
}
/// LEDC (LED PWM Controller)
pub struct LEDC<'d> {
_instance: PeripheralRef<'d, crate::peripherals::LEDC>,
ledc: &'d crate::peripherals::ledc::RegisterBlock,
clock_control_config: &'d Clocks<'d>,
}
#[cfg(esp32)]
/// Used to specify HighSpeed Timer/Channel
pub struct HighSpeed {}
/// Used to specify LowSpeed Timer/Channel
pub struct LowSpeed {}
pub trait Speed {}
#[cfg(esp32)]
impl Speed for HighSpeed {}
impl Speed for LowSpeed {}
impl<'d> LEDC<'d> {
/// Return a new LEDC
pub fn new(
_instance: impl Peripheral<P = crate::peripherals::LEDC> + 'd,
clock_control_config: &'d Clocks,
) -> Self {
crate::into_ref!(_instance);
PeripheralClockControl::enable(PeripheralEnable::Ledc);
let ledc = unsafe { &*crate::peripherals::LEDC::ptr() };
LEDC {
_instance,
ledc,
clock_control_config,
}
}
/// Set global slow clock source
#[cfg(esp32)]
pub fn set_global_slow_clock(&mut self, _clock_source: LSGlobalClkSource) {
self.ledc.conf().write(|w| w.apb_clk_sel().set_bit());
self.ledc
.lstimer0_conf()
.modify(|_, w| w.para_up().set_bit());
}
#[cfg(not(esp32))]
/// Set global slow clock source
pub fn set_global_slow_clock(&mut self, clock_source: LSGlobalClkSource) {
#[cfg(any(esp32c6, esp32h2))]
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
#[cfg(any(esp32c6, esp32h2))]
pcr.ledc_sclk_conf().write(|w| w.ledc_sclk_en().set_bit());
match clock_source {
LSGlobalClkSource::APBClk => {
#[cfg(not(any(esp32c6, esp32h2)))]
self.ledc
.conf()
.write(|w| unsafe { w.apb_clk_sel().bits(1) });
#[cfg(esp32c6)]
pcr.ledc_sclk_conf()
.write(|w| unsafe { w.ledc_sclk_sel().bits(1) });
#[cfg(esp32h2)]
pcr.ledc_sclk_conf()
.write(|w| unsafe { w.ledc_sclk_sel().bits(0) });
}
}
self.ledc.timer0_conf().modify(|_, w| w.para_up().set_bit());
}
/// Return a new timer
pub fn get_timer<S: TimerSpeed>(&self, number: timer::Number) -> Timer<S> {
Timer::new(self.ledc, self.clock_control_config, number)
}
/// Return a new channel
pub fn get_channel<S: TimerSpeed, O: OutputPin>(
&self,
number: channel::Number,
output_pin: impl Peripheral<P = O> + 'd,
) -> Channel<S, O> {
Channel::new(number, output_pin)
}
}

View File

@ -1,476 +0,0 @@
//! # LEDC timer
//!
//! ## Overview
//! The `LEDC Timer` module is a part of the `LED Controller (LEDC)` driver
//! designed for ESP microcontrollers. It provides a high-level interface to
//! configure and control individual timers of the `LEDC` peripheral.
//!
//! The module allows precise and flexible control over timer configurations,
//! duty cycles and frequencies, making it ideal for Pulse-Width Modulation
//! (PWM) applications and LED lighting control.
use fugit::HertzU32;
#[cfg(esp32)]
use super::HighSpeed;
use super::{LowSpeed, Speed};
use crate::{clock::Clocks, peripherals::ledc};
const LEDC_TIMER_DIV_NUM_MAX: u64 = 0x3FFFF;
/// Timer errors
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
/// Invalid Divisor
Divisor,
}
#[cfg(esp32)]
/// Clock source for HS Timers
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HSClockSource {
APBClk,
// TODO RefTick,
}
/// Clock source for LS Timers
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum LSClockSource {
APBClk,
// TODO SLOWClk
}
/// Timer number
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Number {
Timer0,
Timer1,
Timer2,
Timer3,
}
/// Timer configuration
pub mod config {
use fugit::HertzU32;
/// Number of bits reserved for duty cycle adjustment
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Duty {
Duty1Bit = 1,
Duty2Bit,
Duty3Bit,
Duty4Bit,
Duty5Bit,
Duty6Bit,
Duty7Bit,
Duty8Bit,
Duty9Bit,
Duty10Bit,
Duty11Bit,
Duty12Bit,
Duty13Bit,
Duty14Bit,
#[cfg(esp32)]
Duty15Bit,
#[cfg(esp32)]
Duty16Bit,
#[cfg(esp32)]
Duty17Bit,
#[cfg(esp32)]
Duty18Bit,
#[cfg(esp32)]
Duty19Bit,
#[cfg(esp32)]
Duty20Bit,
}
/// Timer configuration
#[derive(Copy, Clone)]
pub struct Config<CS> {
pub duty: Duty,
pub clock_source: CS,
pub frequency: HertzU32,
}
}
/// Trait defining the type of timer source
pub trait TimerSpeed: Speed {
type ClockSourceType;
}
/// Timer source type for LowSpeed timers
impl TimerSpeed for LowSpeed {
type ClockSourceType = LSClockSource;
}
#[cfg(esp32)]
/// Timer source type for HighSpeed timers
impl TimerSpeed for HighSpeed {
type ClockSourceType = HSClockSource;
}
/// Interface for Timers
pub trait TimerIFace<S: TimerSpeed> {
/// Return the frequency of the timer
fn get_freq(&self) -> Option<HertzU32>;
/// Configure the timer
fn configure(&mut self, config: config::Config<S::ClockSourceType>) -> Result<(), Error>;
/// Check if the timer has been configured
fn is_configured(&self) -> bool;
/// Return the duty resolution of the timer
fn get_duty(&self) -> Option<config::Duty>;
/// Return the timer number
fn get_number(&self) -> Number;
/// Return the timer frequency, or 0 if not configured
fn get_frequency(&self) -> u32;
}
/// Interface for HW configuration of timer
pub trait TimerHW<S: TimerSpeed> {
/// Get the current source timer frequency from the HW
fn get_freq_hw(&self) -> Option<HertzU32>;
/// Configure the HW for the timer
fn configure_hw(&self, divisor: u32);
/// Update the timer in HW
fn update_hw(&self);
}
/// Timer struct
pub struct Timer<'a, S: TimerSpeed> {
ledc: &'a crate::peripherals::ledc::RegisterBlock,
clock_control_config: &'a Clocks<'a>,
number: Number,
duty: Option<config::Duty>,
frequency: u32,
configured: bool,
use_ref_tick: bool,
clock_source: Option<S::ClockSourceType>,
}
impl<'a, S: TimerSpeed> TimerIFace<S> for Timer<'a, S>
where
Timer<'a, S>: TimerHW<S>,
{
/// Return the frequency of the timer
fn get_freq(&self) -> Option<HertzU32> {
self.get_freq_hw()
}
/// Configure the timer
fn configure(&mut self, config: config::Config<S::ClockSourceType>) -> Result<(), Error> {
self.duty = Some(config.duty);
self.clock_source = Some(config.clock_source);
// TODO: we should return some error here if `unwrap()` fails
let src_freq: u32 = self.get_freq().unwrap().to_Hz();
let precision = 1 << config.duty as u32;
let frequency: u32 = config.frequency.raw();
self.frequency = frequency;
let mut divisor = ((src_freq as u64) << 8) / frequency as u64 / precision as u64;
if divisor > LEDC_TIMER_DIV_NUM_MAX {
// APB_CLK results in divisor which too high. Try using REF_TICK as clock
// source.
self.use_ref_tick = true;
divisor = ((1_000_000 as u64) << 8) / frequency as u64 / precision as u64;
}
if divisor >= LEDC_TIMER_DIV_NUM_MAX || divisor < 256 {
return Err(Error::Divisor);
}
self.configure_hw(divisor as u32);
self.update_hw();
self.configured = true;
Ok(())
}
/// Check if the timer has been configured
fn is_configured(&self) -> bool {
self.configured
}
/// Return the duty resolution of the timer
fn get_duty(&self) -> Option<config::Duty> {
self.duty
}
/// Return the timer number
fn get_number(&self) -> Number {
self.number
}
/// Return the timer frequency
fn get_frequency(&self) -> u32 {
self.frequency
}
}
impl<'a, S: TimerSpeed> Timer<'a, S> {
/// Create a new intance of a timer
pub fn new(
ledc: &'a ledc::RegisterBlock,
clock_control_config: &'a Clocks,
number: Number,
) -> Self {
Timer {
ledc,
clock_control_config,
number,
duty: None,
frequency: 0u32,
configured: false,
use_ref_tick: false,
clock_source: None,
}
}
}
/// Timer HW implementation for LowSpeed timers
impl<'a> TimerHW<LowSpeed> for Timer<'a, LowSpeed> {
/// Get the current source timer frequency from the HW
fn get_freq_hw(&self) -> Option<fugit::HertzU32> {
self.clock_source.map(|cs| match cs {
LSClockSource::APBClk => self.clock_control_config.apb_clock,
})
}
#[cfg(esp32)]
/// Configure the HW for the timer
fn configure_hw(&self, divisor: u32) {
let duty = unwrap!(self.duty) as u8;
let use_apb = !self.use_ref_tick;
match self.number {
Number::Timer0 => self.ledc.lstimer0_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_apb)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer1 => self.ledc.lstimer1_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_apb)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer2 => self.ledc.lstimer2_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_apb)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer3 => self.ledc.lstimer3_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_apb)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
};
}
#[cfg(not(esp32))]
/// Configure the HW for the timer
fn configure_hw(&self, divisor: u32) {
let duty = unwrap!(self.duty) as u8;
let use_ref_tick = self.use_ref_tick;
match self.number {
Number::Timer0 => self.ledc.timer0_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_ref_tick)
.rst()
.clear_bit()
.pause()
.clear_bit()
.clk_div()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer1 => self.ledc.timer1_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_ref_tick)
.rst()
.clear_bit()
.pause()
.clear_bit()
.clk_div()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer2 => self.ledc.timer2_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_ref_tick)
.rst()
.clear_bit()
.pause()
.clear_bit()
.clk_div()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer3 => self.ledc.timer3_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(use_ref_tick)
.rst()
.clear_bit()
.pause()
.clear_bit()
.clk_div()
.bits(divisor)
.duty_res()
.bits(duty)
}),
};
}
#[cfg(esp32)]
/// Update the timer in HW
fn update_hw(&self) {
match self.number {
Number::Timer0 => self
.ledc
.lstimer0_conf()
.modify(|_, w| w.para_up().set_bit()),
Number::Timer1 => self
.ledc
.lstimer1_conf()
.modify(|_, w| w.para_up().set_bit()),
Number::Timer2 => self
.ledc
.lstimer2_conf()
.modify(|_, w| w.para_up().set_bit()),
Number::Timer3 => self
.ledc
.lstimer3_conf()
.modify(|_, w| w.para_up().set_bit()),
};
}
#[cfg(not(esp32))]
/// Update the timer in HW
fn update_hw(&self) {
match self.number {
Number::Timer0 => self.ledc.timer0_conf().modify(|_, w| w.para_up().set_bit()),
Number::Timer1 => self.ledc.timer1_conf().modify(|_, w| w.para_up().set_bit()),
Number::Timer2 => self.ledc.timer2_conf().modify(|_, w| w.para_up().set_bit()),
Number::Timer3 => self.ledc.timer3_conf().modify(|_, w| w.para_up().set_bit()),
};
}
}
#[cfg(esp32)]
/// Timer HW implementation for HighSpeed timers
impl<'a> TimerHW<HighSpeed> for Timer<'a, HighSpeed> {
/// Get the current source timer frequency from the HW
fn get_freq_hw(&self) -> Option<HertzU32> {
self.clock_source.map(|cs| match cs {
// TODO RefTick HSClockSource::RefTick => self.clock_control_config.apb_clock,
HSClockSource::APBClk => self.clock_control_config.apb_clock,
})
}
/// Configure the HW for the timer
fn configure_hw(&self, divisor: u32) {
let duty = unwrap!(self.duty) as u8;
let sel_hstimer = self.clock_source == Some(HSClockSource::APBClk);
match self.number {
Number::Timer0 => self.ledc.hstimer0_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(sel_hstimer)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer1 => self.ledc.hstimer1_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(sel_hstimer)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer2 => self.ledc.hstimer2_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(sel_hstimer)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
Number::Timer3 => self.ledc.hstimer3_conf().modify(|_, w| unsafe {
w.tick_sel()
.bit(sel_hstimer)
.rst()
.clear_bit()
.pause()
.clear_bit()
.div_num()
.bits(divisor)
.duty_res()
.bits(duty)
}),
};
}
/// Update the timer in HW
fn update_hw(&self) {
// Nothing to do for HS timers
}
}

View File

@ -1,447 +0,0 @@
//! `no_std` HAL implementations for the peripherals which are common among
//! Espressif devices. Implements a number of the traits defined by
//! [embedded-hal].
//!
//! This crate should not be used directly; you should use one of the
//! device-specific HAL crates instead:
//!
//! - [esp32-hal]
//! - [esp32c2-hal]
//! - [esp32c3-hal]
//! - [esp32c6-hal]
//! - [esp32h2-hal]
//! - [esp32s2-hal]
//! - [esp32s3-hal]
//!
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
//! [esp32-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32-hal
//! [esp32c2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c2-hal
//! [esp32c3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c3-hal
//! [esp32c6-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-hal
//! [esp32h2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32h2-hal
//! [esp32s2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s2-hal
//! [esp32s3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s3-hal
#![no_std]
#![cfg_attr(xtensa, feature(asm_experimental_arch))]
#![cfg_attr(
feature = "async",
allow(incomplete_features, stable_features, unknown_lints, async_fn_in_trait),
feature(async_fn_in_trait),
feature(impl_trait_projections)
)]
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
// MUST be the first module
mod fmt;
#[cfg(riscv)]
pub use esp_riscv_rt::{self, entry, riscv};
pub use procmacros as macros;
#[cfg(xtensa)]
pub use xtensa_lx;
#[cfg(xtensa)]
pub use xtensa_lx_rt::{self, entry};
#[cfg(adc)]
pub use self::analog::adc;
#[cfg(dac)]
pub use self::analog::dac;
#[cfg(any(xtensa, all(riscv, systimer)))]
pub use self::delay::Delay;
#[cfg(gdma)]
pub use self::dma::gdma;
#[cfg(pdma)]
pub use self::dma::pdma;
#[cfg(gpio)]
pub use self::gpio::IO;
#[cfg(rmt)]
pub use self::rmt::Rmt;
#[cfg(rng)]
pub use self::rng::Rng;
#[cfg(any(lp_clkrst, rtc_cntl))]
pub use self::rtc_cntl::{Rtc, Rwdt};
#[cfg(any(esp32, esp32s3))]
pub use self::soc::cpu_control;
#[cfg(efuse)]
pub use self::soc::efuse;
#[cfg(lp_core)]
pub use self::soc::lp_core;
pub use self::soc::peripherals;
#[cfg(psram)]
pub use self::soc::psram;
#[cfg(ulp_riscv_core)]
pub use self::soc::ulp_core;
#[cfg(any(timg0, timg1))]
pub use self::timer::Timer;
#[cfg(any(uart0, uart1, uart2))]
pub use self::uart::{Uart, UartRx, UartTx};
#[cfg(usb_device)]
pub use self::usb_serial_jtag::UsbSerialJtag;
#[cfg(aes)]
pub mod aes;
#[cfg(any(adc, dac))]
pub mod analog;
#[cfg(assist_debug)]
pub mod assist_debug;
pub mod clock;
#[cfg(any(xtensa, all(riscv, systimer)))]
pub mod delay;
#[cfg(any(gdma, pdma))]
pub mod dma;
#[cfg(ecc)]
pub mod ecc;
#[cfg(feature = "embassy")]
pub mod embassy;
#[cfg(soc_etm)]
pub mod etm;
#[cfg(gpio)]
pub mod gpio;
#[cfg(hmac)]
pub mod hmac;
#[cfg(any(i2c0, i2c1))]
pub mod i2c;
#[cfg(any(i2s0, i2s1))]
pub mod i2s;
#[cfg(any(dport, interrupt_core0, interrupt_core1))]
pub mod interrupt;
#[cfg(ledc)]
pub mod ledc;
#[cfg(any(mcpwm0, mcpwm1))]
pub mod mcpwm;
#[cfg(usb0)]
pub mod otg_fs;
#[cfg(parl_io)]
pub mod parl_io;
#[cfg(pcnt)]
pub mod pcnt;
pub mod peripheral;
pub mod prelude;
#[cfg(any(hmac, sha))]
mod reg_access;
pub mod reset;
#[cfg(rmt)]
pub mod rmt;
#[cfg(rng)]
pub mod rng;
pub mod rom;
#[cfg(rsa)]
pub mod rsa;
#[cfg(any(lp_clkrst, rtc_cntl))]
pub mod rtc_cntl;
#[cfg(sha)]
pub mod sha;
#[cfg(any(spi0, spi1, spi2, spi3))]
pub mod spi;
#[cfg(any(dport, pcr, system))]
pub mod system;
#[cfg(systimer)]
pub mod systimer;
#[cfg(any(timg0, timg1))]
pub mod timer;
#[cfg(trace)]
pub mod trace;
#[cfg(any(twai0, twai1))]
pub mod twai;
#[cfg(any(uart0, uart1, uart2))]
pub mod uart;
#[cfg(usb_device)]
pub mod usb_serial_jtag;
/// State of the CPU saved when entering exception or interrupt
pub mod trapframe {
#[cfg(riscv)]
pub use esp_riscv_rt::TrapFrame;
#[cfg(xtensa)]
pub use xtensa_lx_rt::exception::Context as TrapFrame;
}
// The `soc` module contains chip-specific implementation details and should not
// be directly exposed.
mod soc;
#[cfg(xtensa)]
#[no_mangle]
extern "C" fn EspDefaultHandler(_level: u32, _interrupt: peripherals::Interrupt) {
#[cfg(not(feature = "defmt"))]
panic!("Unhandled level {} interrupt: {:?}", _level, _interrupt);
#[cfg(feature = "defmt")]
panic!(
"Unhandled level {} interrupt: {:?}",
_level,
defmt::Debug2Format(&_interrupt)
);
}
#[cfg(riscv)]
#[no_mangle]
extern "C" fn EspDefaultHandler(_interrupt: peripherals::Interrupt) {
#[cfg(not(feature = "defmt"))]
panic!("Unhandled interrupt: {:?}", _interrupt);
#[cfg(feature = "defmt")]
panic!(
"Unhandled interrupt: {:?}",
defmt::Debug2Format(&_interrupt)
);
}
/// Available CPU cores
///
/// The actual number of available cores depends on the target.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Cpu {
/// The first core
ProCpu = 0,
/// The second core
#[cfg(multi_core)]
AppCpu,
}
#[cfg(all(xtensa, multi_core))]
fn get_raw_core() -> u32 {
xtensa_lx::get_processor_id() & 0x2000
}
/// Which core the application is currently executing on
#[cfg(all(xtensa, multi_core))]
pub fn get_core() -> Cpu {
match get_raw_core() {
0 => Cpu::ProCpu,
_ => Cpu::AppCpu,
}
}
/// Which core the application is currently executing on
#[cfg(not(all(xtensa, multi_core)))]
pub fn get_core() -> Cpu {
Cpu::ProCpu
}
mod critical_section_impl {
struct CriticalSection;
critical_section::set_impl!(CriticalSection);
#[cfg(xtensa)]
mod xtensa {
// PS has 15 useful bits. Bits 12..16 and 19..32 are unused, so we can use bit
// #31 as our reentry flag.
#[cfg(multi_core)]
const REENTRY_FLAG: u32 = 1 << 31;
unsafe impl critical_section::Impl for super::CriticalSection {
unsafe fn acquire() -> critical_section::RawRestoreState {
let mut tkn: critical_section::RawRestoreState;
core::arch::asm!("rsil {0}, 5", out(reg) tkn);
#[cfg(multi_core)]
{
use super::multicore::{LockKind, MULTICORE_LOCK};
match MULTICORE_LOCK.lock() {
LockKind::Lock => {
// We can assume the reserved bit is 0 otherwise
// rsil - wsr pairings would be undefined behavior
}
LockKind::Reentry => tkn |= REENTRY_FLAG,
}
}
tkn
}
unsafe fn release(token: critical_section::RawRestoreState) {
#[cfg(multi_core)]
{
use super::multicore::MULTICORE_LOCK;
debug_assert!(MULTICORE_LOCK.is_owned_by_current_thread());
if token & REENTRY_FLAG != 0 {
return;
}
MULTICORE_LOCK.unlock();
}
const RESERVED_MASK: u32 = 0b1111_1111_1111_1000_1111_0000_0000_0000;
debug_assert!(token & RESERVED_MASK == 0);
core::arch::asm!(
"wsr.ps {0}",
"rsync", in(reg) token)
}
}
}
#[cfg(riscv)]
mod riscv {
use esp_riscv_rt::riscv;
#[cfg(multi_core)]
// The restore state is a u8 that is casted from a bool, so it has a value of
// 0x00 or 0x01 before we add the reentry flag to it.
const REENTRY_FLAG: u8 = 1 << 7;
unsafe impl critical_section::Impl for super::CriticalSection {
unsafe fn acquire() -> critical_section::RawRestoreState {
let mut mstatus = 0u32;
core::arch::asm!("csrrci {0}, mstatus, 8", inout(reg) mstatus);
let tkn = ((mstatus & 0b1000) != 0) as critical_section::RawRestoreState;
#[cfg(multi_core)]
{
use super::multicore::{LockKind, MULTICORE_LOCK};
match MULTICORE_LOCK.lock() {
LockKind::Lock => {}
LockKind::Reentry => tkn |= REENTRY_FLAG,
}
}
tkn
}
unsafe fn release(token: critical_section::RawRestoreState) {
#[cfg(multi_core)]
{
use super::multicore::MULTICORE_LOCK;
debug_assert!(MULTICORE_LOCK.is_owned_by_current_thread());
if token & REENTRY_FLAG != 0 {
return;
}
MULTICORE_LOCK.unlock();
}
if token != 0 {
riscv::interrupt::enable();
}
}
}
}
#[cfg(multi_core)]
mod multicore {
use portable_atomic::{AtomicUsize, Ordering};
// We're using a value that we know get_raw_core() will never return. This
// avoids an unnecessary increment of the core ID.
#[cfg(xtensa)] // TODO: first multi-core RISC-V target will show if this value is OK
// globally or only for Xtensa
const UNUSED_THREAD_ID_VALUE: usize = 0x0001;
fn thread_id() -> usize {
crate::get_raw_core() as usize
}
pub(super) static MULTICORE_LOCK: ReentrantMutex = ReentrantMutex::new();
pub(super) enum LockKind {
Lock = 0,
Reentry,
}
pub(super) struct ReentrantMutex {
owner: AtomicUsize,
}
impl ReentrantMutex {
const fn new() -> Self {
Self {
owner: AtomicUsize::new(UNUSED_THREAD_ID_VALUE),
}
}
pub fn is_owned_by_current_thread(&self) -> bool {
self.owner.load(Ordering::Relaxed) == thread_id()
}
pub(super) fn lock(&self) -> LockKind {
let current_thread_id = thread_id();
if self.try_lock(current_thread_id) {
return LockKind::Lock;
}
let current_owner = self.owner.load(Ordering::Relaxed);
if current_owner == current_thread_id {
return LockKind::Reentry;
}
while !self.try_lock(current_thread_id) {}
LockKind::Lock
}
fn try_lock(&self, new_owner: usize) -> bool {
self.owner
.compare_exchange(
UNUSED_THREAD_ID_VALUE,
new_owner,
Ordering::Acquire,
Ordering::Relaxed,
)
.is_ok()
}
pub(super) fn unlock(&self) {
self.owner.store(UNUSED_THREAD_ID_VALUE, Ordering::Release);
}
}
}
}
/// FlashSafeDma
///
/// The embedded-hal traits make no guarantees about
/// where the buffers are placed. The DMA implementation in Espressif chips has
/// a limitation in that it can only access the RAM address space, meaning data
/// to be transmitted from the flash address space must be copied into RAM
/// first.
///
/// This wrapper struct should be used when a peripheral using the DMA engine
/// needs to transmit data from flash (ROM) via the embedded-hal traits. This is
/// often a `const` variable.
///
/// Example usage using [`spi::master::dma::SpiDma`]
/// ```no_run
/// const ARRAY_IN_FLASH = [0xAA; 128]
///
/// let spi = SpiDma::new(/* */);
///
/// spi.write(&ARRAY_IN_FLASH[..]).unwrap(); // error when transmission starts
///
/// let spi = FlashSafeDma::new(spi);
///
/// spi.write(&ARRAY_IN_FLASH[..]).unwrap(); // success
/// ```
pub struct FlashSafeDma<T, const SIZE: usize> {
inner: T,
buffer: [u8; SIZE],
}
impl<T, const SIZE: usize> FlashSafeDma<T, SIZE> {
pub fn new(inner: T) -> Self {
Self {
inner,
buffer: [0u8; SIZE],
}
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn inner(&self) -> &T {
&self.inner
}
pub fn free(self) -> T {
self.inner
}
}

View File

@ -1,838 +0,0 @@
//! # MCPWM peripheral - operator module
//!
//! ## Overview
//! The `operator` module is part of the `MCPWM` peripheral driver for
//! `ESP` chips. It is responsible for
//! generating `PWM (Pulse Width Modulation)` signals and handling various
//! aspects related to `PWM` signal generation.
//!
//! This module provides flexibility in configuring the PWM outputs. Its
//! implementation allows for motor control and other applications that demand
//! accurate pulse timing and sophisticated modulation techniques.
use core::marker::PhantomData;
use crate::{
gpio::OutputPin,
mcpwm::{timer::Timer, PwmPeripheral},
peripheral::{Peripheral, PeripheralRef},
};
/// Input/Output Stream descriptor for each channel
pub enum PWMStream {
/// PWM Stream A
PWMA,
/// PWM Stream B
PWMB,
}
/// Configuration for MCPWM Operator DeadTime
/// It's recommended to reference the technical manual for configuration
pub struct DeadTimeCfg {
cfg_reg: u32,
rising_edge_delay: u16,
falling_edge_delay: u16,
}
impl DeadTimeCfg {
// NOTE: it's a bit difficult to make this typestate
// due to the different interconnections (FED/RED vs PWMxA/PWMxB) and
// the many mode of operation
/// Uses the following configuration:
/// * Clock: PWM_clk
/// * Bypass: A & B
/// * Inputs: A->A, B->B (InSel)
/// * Outputs: A->A, B->B (OutSwap)
/// * No Dual-edge B
/// * No Invert
/// * FED/RED update mode = immediate
/// * FED/RED = 0
pub fn new_bypass() -> DeadTimeCfg {
DeadTimeCfg {
cfg_reg: 0b0_11_00_00_00_0_000_000,
rising_edge_delay: 0,
falling_edge_delay: 0,
}
}
/// Active High Complementary (AHC) from Technical Reference manual
///
/// Will generate a PWM from input PWMA, such that output PWMA & PWMB are
/// each others complement Except during a transition in which they will
/// be both off (as deadtime) such that they should never overlap, useful
/// for H-Bridge type scenarios
///
/// Default delay on both rising (red) and falling (fed) edge is 16 cycles
pub fn new_ahc(red_delay: Option<u16>, fed_delay: Option<u16>) -> DeadTimeCfg {
DeadTimeCfg {
cfg_reg: 0b0_00_10_00_00_0_000_000,
rising_edge_delay: red_delay.unwrap_or(16u16),
falling_edge_delay: fed_delay.unwrap_or(16u16),
}
}
// TODO: Add some common configurations ~AHC~,ALC,AH,AC
fn set_flag(&mut self, offset: u8, val: bool) {
let mask = !(1 << offset);
self.cfg_reg = self.cfg_reg & mask | ((val as u32) << offset);
}
/// Sets the delay for the FED/RED module
pub fn set_delay(&mut self, rising_edge: u16, falling_edge: u16) {
self.rising_edge_delay = rising_edge;
self.falling_edge_delay = falling_edge;
}
/// Sets FED/RED output inverter
/// Inverts the output of the FED/RED module (excl DEB mode feedback)
pub fn invert_output(&mut self, fed: bool, red: bool) {
self.set_flag(13, fed);
self.set_flag(14, red);
}
/// Swaps the output of a PWM Stream
/// i.e. If streams have output_swap enabled, the output of the module
/// is swapped, while if only one is enabled that one 'copies' from the
/// other stream
pub fn set_output_swap(&mut self, stream: PWMStream, swap: bool) {
self.set_flag(
match stream {
PWMStream::PWMA => 9,
PWMStream::PWMB => 10,
},
swap,
);
}
/// Set PWMA/PWMB stream to bypass everything except output_swap
/// This means no deadtime is applied when enabled
pub fn set_bypass(&mut self, stream: PWMStream, enable: bool) {
self.set_flag(
match stream {
PWMStream::PWMA => 15,
PWMStream::PWMB => 16,
},
enable,
);
}
/// Select Between PWMClk & PT_Clk
pub fn select_clock(&mut self, pwm_clock: bool) {
self.set_flag(17, pwm_clock);
}
/// Select which stream is used for the input of FED/RED
pub fn select_input(&mut self, fed: PWMStream, red: PWMStream) {
self.set_flag(
12,
match fed {
PWMStream::PWMA => false,
PWMStream::PWMB => true,
},
);
self.set_flag(
11,
match red {
PWMStream::PWMA => false,
PWMStream::PWMB => true,
},
);
}
}
#[cfg(feature = "esp32s3")]
fn dt_cfg<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DB0_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.db0_cfg(),
1 => unsafe { &*(&block.db1_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.db2_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
#[cfg(feature = "esp32s3")]
fn dt_fed<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DB0_FED_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.db0_fed_cfg(),
1 => unsafe { &*(&block.db1_fed_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.db2_fed_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
#[cfg(feature = "esp32s3")]
fn dt_red<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DB0_RED_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.db0_red_cfg(),
1 => unsafe { &*(&block.db1_red_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.db2_red_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
// TODO: dt_cfg, dt_fed, dt_red (and similar functions in mcpwm can be made safe
// by patching PACS)
#[cfg(not(feature = "esp32s3"))]
fn dt_cfg<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DT0_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.dt0_cfg(),
1 => unsafe { &*(&block.dt1_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.dt2_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
#[cfg(not(feature = "esp32s3"))]
fn dt_fed<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DT0_FED_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.dt0_fed_cfg(),
1 => unsafe { &*(&block.dt1_fed_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.dt2_fed_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
#[cfg(not(feature = "esp32s3"))]
fn dt_red<const OP: u8, PWM: PwmPeripheral>() -> &'static crate::peripherals::mcpwm0::DT0_RED_CFG {
let block = unsafe { &*PWM::block() };
match OP {
0 => &block.dt0_red_cfg(),
1 => unsafe { &*(&block.dt1_red_cfg() as *const _ as *const _) },
2 => unsafe { &*(&block.dt2_red_cfg() as *const _ as *const _) },
_ => unreachable!(),
}
}
/// A MCPWM operator
///
/// The PWM Operator submodule has the following functions:
/// * Generates a PWM signal pair, based on timing references obtained from the
/// corresponding PWM timer.
/// * Each signal out of the PWM signal pair includes a specific pattern of dead
/// time. (Not yet implemented)
/// * Superimposes a carrier on the PWM signal, if configured to do so. (Not yet
/// implemented)
/// * Handles response under fault conditions. (Not yet implemented)
pub struct Operator<const OP: u8, PWM> {
phantom: PhantomData<PWM>,
}
impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
pub(super) fn new() -> Self {
// Side note:
// It would have been nice to deselect any timer reference on peripheral
// initialization.
// However experimentation (ESP32-S3) showed that writing `3` to timersel
// will not disable the timer reference but instead act as though `2` was
// written.
Operator {
phantom: PhantomData,
}
}
/// Select a [`Timer`] to be the timing reference for this operator
///
/// ### Note:
/// By default TIMER0 is used
pub fn set_timer<const TIM: u8>(&mut self, timer: &Timer<TIM, PWM>) {
let _ = timer;
// SAFETY:
// We only write to our OPERATORx_TIMERSEL register
let block = unsafe { &*PWM::block() };
block.operator_timersel().modify(|_, w| match OP {
0 => w.operator0_timersel().variant(TIM),
1 => w.operator1_timersel().variant(TIM),
2 => w.operator2_timersel().variant(TIM),
_ => {
unreachable!()
}
});
}
/// Configures deadtime for this operator
pub fn set_deadtime(&mut self, cfg: &DeadTimeCfg) {
dt_fed::<OP, PWM>().write(|w| unsafe { w.bits(cfg.falling_edge_delay as u32) });
dt_red::<OP, PWM>().write(|w| unsafe { w.bits(cfg.rising_edge_delay as u32) });
dt_cfg::<OP, PWM>().write(|w| unsafe { w.bits(cfg.cfg_reg) });
}
/// Use the A output with the given pin and configuration
pub fn with_pin_a<'d, Pin: OutputPin>(
self,
pin: impl Peripheral<P = Pin> + 'd,
config: PwmPinConfig<true>,
) -> PwmPin<'d, Pin, PWM, OP, true> {
PwmPin::new(pin, config)
}
/// Use the B output with the given pin and configuration
pub fn with_pin_b<'d, Pin: OutputPin>(
self,
pin: impl Peripheral<P = Pin> + 'd,
config: PwmPinConfig<false>,
) -> PwmPin<'d, Pin, PWM, OP, false> {
PwmPin::new(pin, config)
}
/// Use both the A and the B output with the given pins and configurations
pub fn with_pins<'d, PinA: OutputPin, PinB: OutputPin>(
self,
pin_a: impl Peripheral<P = PinA> + 'd,
config_a: PwmPinConfig<true>,
pin_b: impl Peripheral<P = PinB> + 'd,
config_b: PwmPinConfig<false>,
) -> (
PwmPin<'d, PinA, PWM, OP, true>,
PwmPin<'d, PinB, PWM, OP, false>,
) {
(PwmPin::new(pin_a, config_a), PwmPin::new(pin_b, config_b))
}
}
/// Configuration describing how the operator generates a signal on a connected
/// pin
pub struct PwmPinConfig<const IS_A: bool> {
actions: PwmActions<IS_A>,
update_method: PwmUpdateMethod,
}
impl<const IS_A: bool> PwmPinConfig<IS_A> {
/// A configuration using [`PwmActions::UP_ACTIVE_HIGH`] and
/// [`PwmUpdateMethod::SYNC_ON_ZERO`]
pub const UP_ACTIVE_HIGH: Self =
Self::new(PwmActions::UP_ACTIVE_HIGH, PwmUpdateMethod::SYNC_ON_ZERO);
/// A configuration using [`PwmActions::UP_DOWN_ACTIVE_HIGH`] and
/// [`PwmUpdateMethod::SYNC_ON_ZERO`]
pub const UP_DOWN_ACTIVE_HIGH: Self = Self::new(
PwmActions::UP_DOWN_ACTIVE_HIGH,
PwmUpdateMethod::SYNC_ON_ZERO,
);
/// Get a configuration using the given `PwmActions` and `PwmUpdateMethod`
pub const fn new(actions: PwmActions<IS_A>, update_method: PwmUpdateMethod) -> Self {
PwmPinConfig {
actions,
update_method,
}
}
}
/// A pin driven by an MCPWM operator
pub struct PwmPin<'d, Pin, PWM, const OP: u8, const IS_A: bool> {
_pin: PeripheralRef<'d, Pin>,
phantom: PhantomData<PWM>,
}
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
PwmPin<'d, Pin, PWM, OP, IS_A>
{
fn new(pin: impl Peripheral<P = Pin> + 'd, config: PwmPinConfig<IS_A>) -> Self {
crate::into_ref!(pin);
let output_signal = PWM::output_signal::<OP, IS_A>();
pin.enable_output(true)
.connect_peripheral_to_output(output_signal);
let mut pin = PwmPin {
_pin: pin,
phantom: PhantomData,
};
pin.set_actions(config.actions);
pin.set_update_method(config.update_method);
pin
}
/// Updates dead-time FED register
///
/// WARNING: FED is connected to the operator, and could be connected to
/// another pin
#[inline]
pub fn update_fed(&self, cycles: u16) {
dt_fed::<OP, PWM>().write(|w| unsafe { w.bits(cycles as u32) });
}
/// Updates dead-time RED register
///
/// WARNING: RED is connected to the operator, and could be connected to
/// another pin
#[inline]
pub fn update_red(&self, cycles: u16) {
dt_red::<OP, PWM>().write(|w| unsafe { w.bits(cycles as u32) });
}
/// Configure what actions should be taken on timing events
pub fn set_actions(&mut self, value: PwmActions<IS_A>) {
// SAFETY:
// We only write to our GENx_x register
let block = unsafe { &*PWM::block() };
let bits = value.0;
// SAFETY:
// `bits` is a valid bit pattern
unsafe {
match (OP, IS_A) {
(0, true) => block.gen0_a().write(|w| w.bits(bits)),
(1, true) => block.gen1_a().write(|w| w.bits(bits)),
(2, true) => block.gen2_a().write(|w| w.bits(bits)),
(0, false) => block.gen0_b().write(|w| w.bits(bits)),
(1, false) => block.gen1_b().write(|w| w.bits(bits)),
(2, false) => block.gen2_b().write(|w| w.bits(bits)),
_ => unreachable!(),
}
}
}
/// Set how a new timestamp syncs with the timer
#[cfg(esp32)]
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) {
// SAFETY:
// We only write to our GENx_x_UPMETHOD register
let block = unsafe { &*PWM::block() };
let bits = update_method.0;
match (OP, IS_A) {
(0, true) => block
.gen0_stmp_cfg()
.modify(|_, w| w.gen0_a_upmethod().variant(bits)),
(1, true) => block
.gen1_stmp_cfg()
.modify(|_, w| w.gen1_a_upmethod().variant(bits)),
(2, true) => block
.gen2_stmp_cfg()
.modify(|_, w| w.gen2_a_upmethod().variant(bits)),
(0, false) => block
.gen0_stmp_cfg()
.modify(|_, w| w.gen0_b_upmethod().variant(bits)),
(1, false) => block
.gen1_stmp_cfg()
.modify(|_, w| w.gen1_b_upmethod().variant(bits)),
(2, false) => block
.gen2_stmp_cfg()
.modify(|_, w| w.gen2_b_upmethod().variant(bits)),
_ => {
unreachable!()
}
}
}
/// Set how a new timestamp syncs with the timer
#[cfg(esp32s3)]
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) {
// SAFETY:
// We only write to our GENx_x_UPMETHOD register
let block = unsafe { &*PWM::block() };
let bits = update_method.0;
match (OP, IS_A) {
(0, true) => block
.cmpr0_cfg()
.modify(|_, w| w.cmpr0_a_upmethod().variant(bits)),
(1, true) => block
.cmpr1_cfg()
.modify(|_, w| w.cmpr1_a_upmethod().variant(bits)),
(2, true) => block
.cmpr2_cfg()
.modify(|_, w| w.cmpr2_a_upmethod().variant(bits)),
(0, false) => block
.cmpr0_cfg()
.modify(|_, w| w.cmpr0_b_upmethod().variant(bits)),
(1, false) => block
.cmpr1_cfg()
.modify(|_, w| w.cmpr1_b_upmethod().variant(bits)),
(2, false) => block
.cmpr2_cfg()
.modify(|_, w| w.cmpr2_b_upmethod().variant(bits)),
_ => {
unreachable!()
}
}
}
/// Set how a new timestamp syncs with the timer
#[cfg(any(esp32c6, esp32h2))]
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) {
// SAFETY:
// We only write to our GENx_x_UPMETHOD register
let block = unsafe { &*PWM::block() };
let bits = update_method.0;
match (OP, IS_A) {
(0, true) => block
.gen0_stmp_cfg()
.modify(|_, w| w.cmpr0_a_upmethod().variant(bits)),
(1, true) => block
.gen1_stmp_cfg()
.modify(|_, w| w.cmpr1_a_upmethod().variant(bits)),
(2, true) => block
.gen2_stmp_cfg()
.modify(|_, w| w.cmpr2_a_upmethod().variant(bits)),
(0, false) => block
.gen0_stmp_cfg()
.modify(|_, w| w.cmpr0_b_upmethod().variant(bits)),
(1, false) => block
.gen1_stmp_cfg()
.modify(|_, w| w.cmpr1_b_upmethod().variant(bits)),
(2, false) => block
.gen2_stmp_cfg()
.modify(|_, w| w.cmpr2_b_upmethod().variant(bits)),
_ => {
unreachable!()
}
}
}
/// Write a new timestamp.
/// The written value will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(esp32)]
pub fn set_timestamp(&mut self, value: u16) {
// SAFETY:
// We only write to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.gen0_tstmp_a().write(|w| w.gen0_a().variant(value)),
(1, true) => block.gen1_tstmp_a().write(|w| w.gen1_a().variant(value)),
(2, true) => block.gen2_tstmp_a().write(|w| w.gen2_a().variant(value)),
(0, false) => block.gen0_tstmp_b().write(|w| w.gen0_b().variant(value)),
(1, false) => block.gen1_tstmp_b().write(|w| w.gen1_b().variant(value)),
(2, false) => block.gen2_tstmp_b().write(|w| w.gen2_b().variant(value)),
_ => {
unreachable!()
}
}
}
/// Get the old timestamp.
/// The value of the timestamp will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(esp32)]
pub fn get_timestamp(&self) -> u16 {
// SAFETY:
// We only read to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.gen0_tstmp_a().read().gen0_a().bits(),
(1, true) => block.gen1_tstmp_a().read().gen1_a().bits(),
(2, true) => block.gen2_tstmp_a().read().gen2_a().bits(),
(0, false) => block.gen0_tstmp_b().read().gen0_b().bits(),
(1, false) => block.gen1_tstmp_b().read().gen1_b().bits(),
(2, false) => block.gen2_tstmp_b().read().gen2_b().bits(),
_ => {
unreachable!()
}
}
}
/// Write a new timestamp.
/// The written value will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(esp32s3)]
pub fn set_timestamp(&mut self, value: u16) {
// SAFETY:
// We only write to our CMPRx_VALUEx register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.cmpr0_value0().write(|w| w.cmpr0_a().variant(value)),
(1, true) => block.cmpr1_value0().write(|w| w.cmpr1_a().variant(value)),
(2, true) => block.cmpr2_value0().write(|w| w.cmpr2_a().variant(value)),
(0, false) => block.cmpr0_value1().write(|w| w.cmpr0_b().variant(value)),
(1, false) => block.cmpr1_value1().write(|w| w.cmpr1_b().variant(value)),
(2, false) => block.cmpr2_value1().write(|w| w.cmpr2_b().variant(value)),
_ => {
unreachable!()
}
}
}
/// Get the old timestamp.
/// The value of the timestamp will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(esp32s3)]
pub fn get_timestamp(&self) -> u16 {
// SAFETY:
// We only read to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.cmpr0_value0().read().cmpr0_a().bits(),
(1, true) => block.cmpr1_value0().read().cmpr1_a().bits(),
(2, true) => block.cmpr2_value0().read().cmpr2_a().bits(),
(0, false) => block.cmpr0_value1().read().cmpr0_b().bits(),
(1, false) => block.cmpr1_value1().read().cmpr1_b().bits(),
(2, false) => block.cmpr2_value1().read().cmpr2_b().bits(),
_ => {
unreachable!()
}
}
}
/// Write a new timestamp.
/// The written value will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(any(esp32c6, esp32h2))]
pub fn set_timestamp(&mut self, value: u16) {
// SAFETY:
// We only write to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.gen0_tstmp_a().write(|w| w.cmpr0_a().variant(value)),
(1, true) => block.gen1_tstmp_a().write(|w| w.cmpr1_a().variant(value)),
(2, true) => block.gen2_tstmp_a().write(|w| w.cmpr2_a().variant(value)),
(0, false) => block.gen0_tstmp_b().write(|w| w.cmpr0_b().variant(value)),
(1, false) => block.gen1_tstmp_b().write(|w| w.cmpr1_b().variant(value)),
(2, false) => block.gen2_tstmp_b().write(|w| w.cmpr2_b().variant(value)),
_ => {
unreachable!()
}
}
}
/// Get the old timestamp.
/// The value of the timestamp will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(any(esp32c6, esp32h2))]
pub fn get_timestamp(&self) -> u16 {
// SAFETY:
// We only read to our GENx_TSTMP_x register
let block = unsafe { &*PWM::block() };
match (OP, IS_A) {
(0, true) => block.gen0_tstmp_a().read().cmpr0_a().bits(),
(1, true) => block.gen1_tstmp_a().read().cmpr1_a().bits(),
(2, true) => block.gen2_tstmp_a().read().cmpr2_a().bits(),
(0, false) => block.gen0_tstmp_b().read().cmpr0_b().bits(),
(1, false) => block.gen1_tstmp_b().read().cmpr1_b().bits(),
(2, false) => block.gen2_tstmp_b().read().cmpr2_b().bits(),
_ => {
unreachable!()
}
}
}
/// Get the period of the timer.
fn get_period(&self) -> u16 {
// SAFETY:
// We only grant access to our CFG0 register with the lifetime of &mut self
let block = unsafe { &*PWM::block() };
let tim_select = block.operator_timersel().read();
let tim = match OP {
0 => tim_select.operator0_timersel().bits(),
1 => tim_select.operator1_timersel().bits(),
2 => tim_select.operator2_timersel().bits(),
_ => {
unreachable!()
}
};
// SAFETY:
// The CFG0 registers are identical for all timers so we can pretend they're
// TIMER0_CFG0
let timer0_cfg = &block.timer0_cfg0();
let timer0_cfg = match tim {
0 => timer0_cfg,
1 => unsafe { &*(&block.timer1_cfg0() as *const _ as *const _) },
2 => unsafe { &*(&block.timer2_cfg0() as *const _ as *const _) },
_ => unreachable!(),
};
timer0_cfg.read().timer0_period().bits()
}
}
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal::PwmPin
for PwmPin<'d, Pin, PWM, OP, IS_A>
{
type Duty = u16;
/// This only set the timestamp to 0, if you want to disable the PwmPin,
/// it must be done on the timer itself.
fn disable(&mut self) {
self.set_timestamp(0);
}
/// This only set the timestamp to the maximum, if you want to disable the
/// PwmPin, it must be done on the timer itself.
fn enable(&mut self) {
self.set_timestamp(u16::MAX);
}
/// Get the duty of the pin
fn get_duty(&self) -> Self::Duty {
self.get_timestamp()
}
/// Get the max duty of the pin
fn get_max_duty(&self) -> Self::Duty {
self.get_period()
}
/// Set the duty of the pin
fn set_duty(&mut self, duty: Self::Duty) {
self.set_timestamp(duty);
}
}
/// Implement no error type for the PwmPin because the method are infallible
#[cfg(feature = "eh1")]
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
embedded_hal_1::pwm::ErrorType for &mut PwmPin<'d, Pin, PWM, OP, IS_A>
{
type Error = core::convert::Infallible;
}
/// Implement the trait SetDutyCycle for PwmPin
#[cfg(feature = "eh1")]
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
embedded_hal_1::pwm::SetDutyCycle for &mut PwmPin<'d, Pin, PWM, OP, IS_A>
{
/// Get the max duty of the PwmPin
fn max_duty_cycle(&self) -> u16 {
self.get_period()
}
/// Set the max duty of the PwmPin
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), core::convert::Infallible> {
self.set_timestamp(duty);
Ok(())
}
}
/// An action the operator applies to an output
#[non_exhaustive]
#[repr(u32)]
pub enum UpdateAction {
/// Clear the output by setting it to a low level.
SetLow = 1,
/// Set the to a high level.
SetHigh = 2,
/// Change the current output level to the opposite value.
/// If it is currently pulled high, pull it low, or vice versa.
Toggle = 3,
}
/// Settings for what actions should be taken on timing events
///
/// ### Note:
/// The hardware supports using a timestamp A event to trigger an action on
/// output B or vice versa. For clearer ownership semantics this HAL does not
/// support such configurations.
pub struct PwmActions<const IS_A: bool>(u32);
impl<const IS_A: bool> PwmActions<IS_A> {
/// Using this setting together with a timer configured with
/// [`PwmWorkingMode::Increase`](super::timer::PwmWorkingMode::Increase)
/// will set the output high for a duration proportional to the set
/// timestamp.
pub const UP_ACTIVE_HIGH: Self = Self::empty()
.on_up_counting_timer_equals_zero(UpdateAction::SetHigh)
.on_up_counting_timer_equals_timestamp(UpdateAction::SetLow);
/// Using this setting together with a timer configured with
/// [`PwmWorkingMode::UpDown`](super::timer::PwmWorkingMode::UpDown) will
/// set the output high for a duration proportional to the set
/// timestamp.
pub const UP_DOWN_ACTIVE_HIGH: Self = Self::empty()
.on_down_counting_timer_equals_timestamp(UpdateAction::SetHigh)
.on_up_counting_timer_equals_timestamp(UpdateAction::SetLow);
/// `PwmActions` with no `UpdateAction`s set
pub const fn empty() -> Self {
PwmActions(0)
}
/// Choose an `UpdateAction` for an `UTEZ` event
pub const fn on_up_counting_timer_equals_zero(self, action: UpdateAction) -> Self {
self.with_value_at_offset(action as u32, 0)
}
/// Choose an `UpdateAction` for an `UTEP` event
pub const fn on_up_counting_timer_equals_period(self, action: UpdateAction) -> Self {
self.with_value_at_offset(action as u32, 2)
}
/// Choose an `UpdateAction` for an `UTEA`/`UTEB` event
pub const fn on_up_counting_timer_equals_timestamp(self, action: UpdateAction) -> Self {
match IS_A {
true => self.with_value_at_offset(action as u32, 4),
false => self.with_value_at_offset(action as u32, 6),
}
}
/// Choose an `UpdateAction` for an `UTEA`/`UTEB` event where you can
/// specify which of the A/B to use
pub const fn on_up_counting_timer_equals_ch_timestamp<const CH_A: bool>(
self,
action: UpdateAction,
) -> Self {
match CH_A {
true => self.with_value_at_offset(action as u32, 4),
false => self.with_value_at_offset(action as u32, 6),
}
}
/// Choose an `UpdateAction` for an `DTEZ` event
pub const fn on_down_counting_timer_equals_zero(self, action: UpdateAction) -> Self {
self.with_value_at_offset(action as u32, 12)
}
/// Choose an `UpdateAction` for an `DTEP` event
pub const fn on_down_counting_timer_equals_period(self, action: UpdateAction) -> Self {
self.with_value_at_offset(action as u32, 14)
}
/// Choose an `UpdateAction` for an `DTEA`/`DTEB` event
pub const fn on_down_counting_timer_equals_timestamp(self, action: UpdateAction) -> Self {
match IS_A {
true => self.with_value_at_offset(action as u32, 16),
false => self.with_value_at_offset(action as u32, 18),
}
}
/// Choose an `UpdateAction` for an `DTEA`/`DTEB` event where you can
/// specify which of the A/B to use
pub const fn on_down_counting_timer_equals_ch_timestamp<const CH_A: bool>(
self,
action: UpdateAction,
) -> Self {
match CH_A {
true => self.with_value_at_offset(action as u32, 16),
false => self.with_value_at_offset(action as u32, 18),
}
}
const fn with_value_at_offset(self, value: u32, offset: u32) -> Self {
let mask = !(0b11 << offset);
let value = (self.0 & mask) | (value << offset);
PwmActions(value)
}
}
/// Settings for when [`PwmPin::set_timestamp`] takes effect
///
/// Multiple syncing triggers can be set.
pub struct PwmUpdateMethod(u8);
impl PwmUpdateMethod {
/// New timestamp will be applied immediately
pub const SYNC_IMMEDIATLY: Self = Self::empty();
/// New timestamp will be applied when timer is equal to zero
pub const SYNC_ON_ZERO: Self = Self::empty().sync_on_timer_equals_zero();
/// New timestamp will be applied when timer is equal to period
pub const SYNC_ON_PERIOD: Self = Self::empty().sync_on_timer_equals_period();
/// `PwmUpdateMethod` with no sync triggers.
/// Corresponds to syncing immediately
pub const fn empty() -> Self {
PwmUpdateMethod(0)
}
/// Enable syncing new timestamp values when timer is equal to zero
pub const fn sync_on_timer_equals_zero(mut self) -> Self {
self.0 |= 0b0001;
self
}
/// Enable syncing new timestamp values when timer is equal to period
pub const fn sync_on_timer_equals_period(mut self) -> Self {
self.0 |= 0b0010;
self
}
}

View File

@ -1,142 +0,0 @@
//! # USB OTG full-speed peripheral
//!
//! ## Overview
//! The USB OTG Full-speed peripheral driver provides support for the USB
//! On-The-Go (OTG) full-speed functionality on ESP chips, allows communication
//! with USB devices.
//!
//! The driver uses the `esp_synopsys_usb_otg` crate, which provides the `USB
//! bus` implementation and `USB peripheral traits`. It also relies on other
//! peripheral modules, such as `GPIO`, `system`, and `clock control`, to
//! configure and enable the `USB` peripheral.
//!
//! To use the USB OTG Full-speed peripheral driver, you need to initialize the
//! peripheral and configure its settings. The USB struct represents the USB
//! peripheral and requires the implementation of the `UsbSel`, `UsbDp`, and
//! `UsbDm` traits, which define the specific types used for USB pin selection
//! and data pins.
//!
//! The USB struct provides a `new` function for initialization.
//! Inside the `new` function, the `into_ref!` macro is used to convert the
//! peripheral references into `PeripheralRef` instances.
//!
//! The `USB` struct implements the `UsbPeripheral` trait from the
//! `esp_synopsys_usb_otg` crate, which defines the required constants and
//! functions for `USB peripheral` operation. The trait implementation includes
//! enabling the `USB peripheral`, configuring the `USB` settings and connecting
//! the appropriate `GPIO` pins to the `USB peripheral`.
pub use esp_synopsys_usb_otg::UsbBus;
use esp_synopsys_usb_otg::UsbPeripheral;
use crate::{
gpio::InputSignal,
peripheral::{Peripheral, PeripheralRef},
peripherals,
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
};
#[doc(hidden)]
pub trait UsbDp {}
#[doc(hidden)]
pub trait UsbDm {}
pub struct USB<'d, P, M>
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
_usb0: PeripheralRef<'d, peripherals::USB0>,
_usb_dp: PeripheralRef<'d, P>,
_usb_dm: PeripheralRef<'d, M>,
}
impl<'d, P, M> USB<'d, P, M>
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
pub fn new(
usb0: impl Peripheral<P = peripherals::USB0> + 'd,
usb_dp: impl Peripheral<P = P> + 'd,
usb_dm: impl Peripheral<P = M> + 'd,
) -> Self {
crate::into_ref!(usb_dp, usb_dm);
PeripheralClockControl::enable(PeripheralEnable::Usb);
Self {
_usb0: usb0.into_ref(),
_usb_dp: usb_dp,
_usb_dm: usb_dm,
}
}
}
unsafe impl<'d, P, M> Sync for USB<'d, P, M>
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
}
unsafe impl<'d, P, M> UsbPeripheral for USB<'d, P, M>
where
P: UsbDp + Send + Sync,
M: UsbDm + Send + Sync,
{
const REGISTERS: *const () = peripherals::USB0::ptr() as *const ();
const HIGH_SPEED: bool = false;
const FIFO_DEPTH_WORDS: usize = 256;
const ENDPOINT_COUNT: usize = 5;
fn enable() {
unsafe {
let usb_wrap = &*peripherals::USB_WRAP::PTR;
usb_wrap.otg_conf().modify(|_, w| {
w.usb_pad_enable()
.set_bit()
.phy_sel()
.clear_bit()
.clk_en()
.set_bit()
.ahb_clk_force_on()
.set_bit()
.phy_clk_force_on()
.set_bit()
});
#[cfg(esp32s3)]
{
let rtc = &*peripherals::RTC_CNTL::PTR;
rtc.usb_conf()
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit());
}
crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_IDDIG); // connected connector is mini-B side
crate::gpio::connect_high_to_peripheral(InputSignal::USB_SRP_BVALID); // HIGH to force USB device mode
crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_VBUSVALID); // receiving a valid Vbus from device
crate::gpio::connect_low_to_peripheral(InputSignal::USB_OTG_AVALID);
usb_wrap.otg_conf().modify(|_, w| {
w.pad_pull_override()
.set_bit()
.dp_pullup()
.set_bit()
.dp_pulldown()
.clear_bit()
.dm_pullup()
.clear_bit()
.dm_pulldown()
.clear_bit()
});
}
}
fn ahb_frequency_hz(&self) -> u32 {
// unused
80_000_000
}
}

View File

@ -1,254 +0,0 @@
//! # PCNT - channel configuration
//!
//! ## Overview
//! The `channel` module is part of the `PCNT` peripheral driver
//! for `ESP` chips.
//!
//! It provides a convenient and efficient way to configure and use
//! individual channels of the `PCNT` peripheral of pulse counting and signal
//! edge detection on ESP chips.
use super::unit;
use crate::{
gpio::{InputPin, InputSignal, ONE_INPUT, ZERO_INPUT},
peripheral::Peripheral,
peripherals::GPIO,
};
/// Channel number
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Number {
Channel0,
Channel1,
}
/// PCNT channel action on signal edge
#[derive(Debug, Copy, Clone, Default)]
pub enum EdgeMode {
/// Hold current count value
Hold = 0,
/// Increase count value
#[default]
Increment = 1,
/// Decrease count value
Decrement = 2,
}
/// PCNT channel action on control level
#[derive(Debug, Copy, Clone, Default)]
pub enum CtrlMode {
/// Keep current count mode
Keep = 0,
/// Invert current count mode (increase -> decrease, decrease -> increase)
#[default]
Reverse = 1,
/// Hold current count value
Disable = 2,
}
/// Pulse Counter configuration for a single channel
#[derive(Debug, Copy, Clone, Default)]
pub struct Config {
/// PCNT low control mode
pub lctrl_mode: CtrlMode,
/// PCNT high control mode
pub hctrl_mode: CtrlMode,
/// PCNT signal positive edge count mode
pub pos_edge: EdgeMode,
/// PCNT signal negative edge count mode
pub neg_edge: EdgeMode,
pub invert_ctrl: bool,
pub invert_sig: bool,
}
/// PcntPin can be always high, always low, or an actual pin
#[derive(Clone, Copy)]
pub struct PcntSource {
source: u8,
}
impl PcntSource {
pub fn from_pin<'a, P: InputPin>(pin: impl Peripheral<P = P> + 'a) -> Self {
crate::into_ref!(pin);
Self {
source: pin.number(),
}
}
pub fn always_high() -> Self {
Self { source: ONE_INPUT }
}
pub fn always_low() -> Self {
Self { source: ZERO_INPUT }
}
}
pub struct Channel {
unit: unit::Number,
channel: Number,
}
impl Channel {
/// return a new Channel
pub(super) fn new(unit: unit::Number, channel: Number) -> Self {
Self { unit, channel }
}
/// Configure the channel
pub fn configure(&mut self, ctrl_signal: PcntSource, edge_signal: PcntSource, config: Config) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
let conf0 = match self.unit {
unit::Number::Unit0 => pcnt.u0_conf0(),
unit::Number::Unit1 => pcnt.u1_conf0(),
unit::Number::Unit2 => pcnt.u2_conf0(),
unit::Number::Unit3 => pcnt.u3_conf0(),
#[cfg(esp32)]
unit::Number::Unit4 => pcnt.u4_conf0(),
#[cfg(esp32)]
unit::Number::Unit5 => pcnt.u5_conf0(),
#[cfg(esp32)]
unit::Number::Unit6 => pcnt.u6_conf0(),
#[cfg(esp32)]
unit::Number::Unit7 => pcnt.u7_conf0(),
};
match self.channel {
Number::Channel0 => {
conf0.modify(|_, w| unsafe {
w.ch0_hctrl_mode()
.bits(config.hctrl_mode as u8)
.ch0_lctrl_mode()
.bits(config.lctrl_mode as u8)
.ch0_neg_mode()
.bits(config.neg_edge as u8)
.ch0_pos_mode()
.bits(config.pos_edge as u8)
});
}
Number::Channel1 => {
conf0.modify(|_, w| unsafe {
w.ch1_hctrl_mode()
.bits(config.hctrl_mode as u8)
.ch1_lctrl_mode()
.bits(config.lctrl_mode as u8)
.ch1_neg_mode()
.bits(config.neg_edge as u8)
.ch1_pos_mode()
.bits(config.pos_edge as u8)
});
}
}
self.set_ctrl_signal(ctrl_signal, config.invert_ctrl);
self.set_edge_signal(edge_signal, config.invert_sig);
}
/// Set the control signal (pin/high/low) for this channel
pub fn set_ctrl_signal(&self, source: PcntSource, invert: bool) -> &Self {
let signal = match self.unit {
unit::Number::Unit0 => match self.channel {
Number::Channel0 => InputSignal::PCNT0_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT0_CTRL_CH1,
},
unit::Number::Unit1 => match self.channel {
Number::Channel0 => InputSignal::PCNT1_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT1_CTRL_CH1,
},
unit::Number::Unit2 => match self.channel {
Number::Channel0 => InputSignal::PCNT2_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT2_CTRL_CH1,
},
unit::Number::Unit3 => match self.channel {
Number::Channel0 => InputSignal::PCNT3_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT3_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit4 => match self.channel {
Number::Channel0 => InputSignal::PCNT4_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT4_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit5 => match self.channel {
Number::Channel0 => InputSignal::PCNT5_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT5_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit6 => match self.channel {
Number::Channel0 => InputSignal::PCNT6_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT6_CTRL_CH1,
},
#[cfg(esp32)]
unit::Number::Unit7 => match self.channel {
Number::Channel0 => InputSignal::PCNT7_CTRL_CH0,
Number::Channel1 => InputSignal::PCNT7_CTRL_CH1,
},
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize)
.modify(|_, w| unsafe {
w.sel()
.set_bit()
.in_inv_sel()
.bit(invert)
.in_sel()
.bits(source.source)
});
}
self
}
/// Set the edge signal (pin/high/low) for this channel
pub fn set_edge_signal(&self, source: PcntSource, invert: bool) -> &Self {
let signal = match self.unit {
unit::Number::Unit0 => match self.channel {
Number::Channel0 => InputSignal::PCNT0_SIG_CH0,
Number::Channel1 => InputSignal::PCNT0_SIG_CH1,
},
unit::Number::Unit1 => match self.channel {
Number::Channel0 => InputSignal::PCNT1_SIG_CH0,
Number::Channel1 => InputSignal::PCNT1_SIG_CH1,
},
unit::Number::Unit2 => match self.channel {
Number::Channel0 => InputSignal::PCNT2_SIG_CH0,
Number::Channel1 => InputSignal::PCNT2_SIG_CH1,
},
unit::Number::Unit3 => match self.channel {
Number::Channel0 => InputSignal::PCNT3_SIG_CH0,
Number::Channel1 => InputSignal::PCNT3_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit4 => match self.channel {
Number::Channel0 => InputSignal::PCNT4_SIG_CH0,
Number::Channel1 => InputSignal::PCNT4_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit5 => match self.channel {
Number::Channel0 => InputSignal::PCNT5_SIG_CH0,
Number::Channel1 => InputSignal::PCNT5_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit6 => match self.channel {
Number::Channel0 => InputSignal::PCNT6_SIG_CH0,
Number::Channel1 => InputSignal::PCNT6_SIG_CH1,
},
#[cfg(esp32)]
unit::Number::Unit7 => match self.channel {
Number::Channel0 => InputSignal::PCNT7_SIG_CH0,
Number::Channel1 => InputSignal::PCNT7_SIG_CH1,
},
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize)
.modify(|_, w| unsafe {
w.sel()
.set_bit()
.in_inv_sel()
.bit(invert)
.in_sel()
.bits(source.source)
});
}
self
}
}

View File

@ -1,162 +0,0 @@
//! # Pulse Counter peripheral driver
//!
//! ## Overview
//! The `PCNT (Pulse Counter)` driver for `ESP` chips is a software component
//! that provides an interface for controlling and utilizing the `PCNT`
//! peripheral. The `PCNT` peripheral is a hardware module available in `ESP`
//! chips, which functions as a pulse counter and encoder. It is capable of
//! counting pulses and monitoring changes in signal levels from external
//! sources.
//!
//! The `PCNT` driver is designed to offer convenient and efficient access to
//! the functionalities of the `PCNT` peripheral. It consists of two main
//! modules:
//! * [channel]
//! * [unit]
//!
//! The `channel` module allows users to configure and manage individual
//! channels of the `PCNT` peripheral. It provides methods to set various
//! parameters for each channel, such as control modes for signal edges, action
//! on control level, and configurations for positive and negative edge count
//! modes.
//!
//! The `unit` module is responsible for configuring and handling individual
//! units of the `PCNT` peripheral. Each unit represents a separate instance of
//! the `PCNT` module, identified by unit numbers like `Unit0`, `Unit1`, and so
//! on. Users can interact with these units to configure settings such as low
//! and high limits, thresholds, and optional filtering. The unit module also
//! enables users to pause, resume, and clear the counter, as well as enable or
//! disable interrupts for specific events associated with the unit.
//!
//! ## Example
//! ```no_run
//! let unit_number = unit::Number::Unit1;
//!
//! // setup a pulse couter
//! println!("setup pulse counter unit 0");
//! let pcnt = PCNT::new(peripherals.PCNT);
//! let mut u0 = pcnt.get_unit(unit_number);
//! u0.configure(unit::Config {
//! low_limit: -100,
//! high_limit: 100,
//! filter: Some(min(10u16 * 80, 1023u16)),
//! ..Default::default()
//! })
//! .unwrap();
//!
//! println!("setup channel 0");
//! let mut ch0 = u0.get_channel(channel::Number::Channel0);
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut pin_a = io.pins.gpio5.into_pull_up_input();
//! let mut pin_b = io.pins.gpio6.into_pull_up_input();
//!
//! ch0.configure(
//! PcntSource::from_pin(&mut pin_a),
//! PcntSource::from_pin(&mut pin_b),
//! channel::Config {
//! lctrl_mode: channel::CtrlMode::Reverse,
//! hctrl_mode: channel::CtrlMode::Keep,
//! pos_edge: channel::EdgeMode::Decrement,
//! neg_edge: channel::EdgeMode::Increment,
//! invert_ctrl: false,
//! invert_sig: false,
//! },
//! );
//!
//! println!("setup channel 1");
//! let mut ch1 = u0.get_channel(channel::Number::Channel1);
//! ch1.configure(
//! PcntSource::from_pin(&mut pin_b),
//! PcntSource::from_pin(&mut pin_a),
//! channel::Config {
//! lctrl_mode: channel::CtrlMode::Reverse,
//! hctrl_mode: channel::CtrlMode::Keep,
//! pos_edge: channel::EdgeMode::Increment,
//! neg_edge: channel::EdgeMode::Decrement,
//! invert_ctrl: false,
//! invert_sig: false,
//! },
//! );
//! println!("subscribing to events");
//! u0.events(unit::Events {
//! low_limit: true,
//! high_limit: true,
//! thresh0: false,
//! thresh1: false,
//! zero: false,
//! });
//!
//! println!("enabling interrupts");
//! u0.listen();
//! println!("resume pulse counter unit 0");
//! u0.resume();
//!
//! critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0));
//!
//! interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap();
//!
//! let mut last_value: i32 = 0;
//! loop {
//! critical_section::with(|cs| {
//! let mut u0 = UNIT0.borrow_ref_mut(cs);
//! let u0 = u0.as_mut().unwrap();
//! let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst);
//! if value != last_value {
//! println!("value: {value}");
//! last_value = value;
//! }
//! });
//! }
//! ```
//!
//! Where the `PCNT` interrupt handler is defined as:
//! ```no_run
//! #[interrupt]
//! fn PCNT() {
//! critical_section::with(|cs| {
//! let mut u0 = UNIT0.borrow_ref_mut(cs);
//! let u0 = u0.as_mut().unwrap();
//! if u0.interrupt_set() {
//! let events = u0.get_events();
//! if events.high_limit {
//! VALUE.fetch_add(100, Ordering::SeqCst);
//! } else if events.low_limit {
//! VALUE.fetch_add(-100, Ordering::SeqCst);
//! }
//! u0.reset_interrupt();
//! }
//! });
//! }
//! ```
//!
//! [channel]: channel/index.html
//! [unit]: unit/index.html
use self::unit::Unit;
use crate::{
peripheral::{Peripheral, PeripheralRef},
system::PeripheralClockControl,
};
pub mod channel;
pub mod unit;
pub struct PCNT<'d> {
_instance: PeripheralRef<'d, crate::peripherals::PCNT>,
}
impl<'d> PCNT<'d> {
/// Return a new PCNT
pub fn new(_instance: impl Peripheral<P = crate::peripherals::PCNT> + 'd) -> Self {
crate::into_ref!(_instance);
// Enable the PCNT peripherals clock in the system peripheral
PeripheralClockControl::enable(crate::system::Peripheral::Pcnt);
PCNT { _instance }
}
/// Return a unit
pub fn get_unit(&self, number: unit::Number) -> Unit {
Unit::new(number)
}
}

View File

@ -1,408 +0,0 @@
//! # PCNT - Unit module
//!
//! ## Overview
//! The `unit` module is a part of the `PCNT` peripheral driver
//! for ESP chips. It offers functionalities for configuring and utilizing
//! specific units of the PCNT peripheral.
//!
//! Each unit is identified by a unit number, such as `Unit0`, `Unit1`, `Unit2`,
//! and so on. This module provides methods to configure a unit with specific
//! settings, like low and high limits, thresholds, and optional filtering.
//! Users can easily configure these units based on their requirements.
use critical_section::CriticalSection;
use super::channel;
/// Unit number
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Number {
Unit0,
Unit1,
Unit2,
Unit3,
#[cfg(esp32)]
Unit4,
#[cfg(esp32)]
Unit5,
#[cfg(esp32)]
Unit6,
#[cfg(esp32)]
Unit7,
}
/// Unit errors
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
/// Invalid filter threshold value
InvalidFilterThresh,
/// Invalid low limit - must be < 0
InvalidLowLimit,
/// Invalid high limit - must be > 0
InvalidHighLimit,
}
/// the current status of the counter.
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ZeroMode {
/// pulse counter decreases from positive to 0.
#[default]
PosZero = 0,
/// pulse counter increases from negative to 0
NegZero = 1,
/// pulse counter is negative (not implemented?)
Negitive = 2,
/// pulse counter is positive (not implemented?)
Positive = 3,
}
impl From<u8> for ZeroMode {
fn from(value: u8) -> Self {
match value {
0 => Self::PosZero,
1 => Self::NegZero,
2 => Self::Negitive,
3 => Self::Positive,
_ => unreachable!(), // TODO: is this good enoough? should we use some default?
}
}
}
// Events
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Events {
pub low_limit: bool,
pub high_limit: bool,
pub thresh0: bool,
pub thresh1: bool,
pub zero: bool,
}
/// Unit configuration
#[derive(Copy, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Config {
pub low_limit: i16,
pub high_limit: i16,
pub thresh0: i16,
pub thresh1: i16,
pub filter: Option<u16>,
}
pub struct Unit {
number: Number,
}
impl Unit {
/// return a new Unit
pub(super) fn new(number: Number) -> Self {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
let conf0 = match number {
Number::Unit0 => pcnt.u0_conf0(),
Number::Unit1 => pcnt.u1_conf0(),
Number::Unit2 => pcnt.u2_conf0(),
Number::Unit3 => pcnt.u3_conf0(),
#[cfg(esp32)]
Number::Unit4 => pcnt.u4_conf0(),
#[cfg(esp32)]
Number::Unit5 => pcnt.u5_conf0(),
#[cfg(esp32)]
Number::Unit6 => pcnt.u6_conf0(),
#[cfg(esp32)]
Number::Unit7 => pcnt.u7_conf0(),
};
// disable filter and all events
conf0.modify(|_, w| unsafe {
w.filter_en()
.clear_bit()
.filter_thres()
.bits(0)
.thr_l_lim_en()
.clear_bit()
.thr_h_lim_en()
.clear_bit()
.thr_thres0_en()
.clear_bit()
.thr_thres1_en()
.clear_bit()
.thr_zero_en()
.clear_bit()
});
Self { number }
}
pub fn configure(&mut self, config: Config) -> Result<(), Error> {
// low limit must be >= or the limit is -32768 and when thats
// hit the event status claims it was the high limit.
// tested on an esp32s3
if config.low_limit >= 0 {
return Err(Error::InvalidLowLimit);
}
if config.high_limit <= 0 {
return Err(Error::InvalidHighLimit);
}
let (filter_en, filter) = match config.filter {
Some(filter) => (true, filter),
None => (false, 0),
};
// filter must be less than 1024
if filter > 1023 {
return Err(Error::InvalidFilterThresh);
}
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
let (conf0, conf1, conf2) = match self.number {
Number::Unit0 => (pcnt.u0_conf0(), pcnt.u0_conf1(), pcnt.u0_conf2()),
Number::Unit1 => (pcnt.u1_conf0(), pcnt.u1_conf1(), pcnt.u1_conf2()),
Number::Unit2 => (pcnt.u2_conf0(), pcnt.u2_conf1(), pcnt.u2_conf2()),
Number::Unit3 => (pcnt.u3_conf0(), pcnt.u3_conf1(), pcnt.u3_conf2()),
#[cfg(esp32)]
Number::Unit4 => (pcnt.u4_conf0(), pcnt.u4_conf1(), pcnt.u4_conf2()),
#[cfg(esp32)]
Number::Unit5 => (pcnt.u5_conf0(), pcnt.u5_conf1(), pcnt.u5_conf2()),
#[cfg(esp32)]
Number::Unit6 => (pcnt.u6_conf0(), pcnt.u6_conf1(), pcnt.u6_conf2()),
#[cfg(esp32)]
Number::Unit7 => (pcnt.u7_conf0(), pcnt.u7_conf1(), pcnt.u7_conf2()),
};
conf2.write(|w| unsafe {
w.cnt_l_lim()
.bits(config.low_limit as u16)
.cnt_h_lim()
.bits(config.high_limit as u16)
});
conf1.write(|w| unsafe {
w.cnt_thres0()
.bits(config.thresh0 as u16)
.cnt_thres1()
.bits(config.thresh1 as u16)
});
conf0.modify(|_, w| unsafe { w.filter_thres().bits(filter).filter_en().bit(filter_en) });
self.pause();
self.clear();
Ok(())
}
pub fn get_channel(&self, number: channel::Number) -> super::channel::Channel {
super::channel::Channel::new(self.number, number)
}
pub fn clear(&self) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| {
match self.number {
Number::Unit0 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u0().set_bit()),
Number::Unit1 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u1().set_bit()),
Number::Unit2 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u2().set_bit()),
Number::Unit3 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u3().set_bit()),
#[cfg(esp32)]
Number::Unit4 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u4().set_bit()),
#[cfg(esp32)]
Number::Unit5 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u5().set_bit()),
#[cfg(esp32)]
Number::Unit6 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u6().set_bit()),
#[cfg(esp32)]
Number::Unit7 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u7().set_bit()),
}
// TODO: does this need a delay? (liebman / Jan 2 2023)
match self.number {
Number::Unit0 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u0().clear_bit()),
Number::Unit1 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u1().clear_bit()),
Number::Unit2 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u2().clear_bit()),
Number::Unit3 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u3().clear_bit()),
#[cfg(esp32)]
Number::Unit4 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u4().clear_bit()),
#[cfg(esp32)]
Number::Unit5 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u5().clear_bit()),
#[cfg(esp32)]
Number::Unit6 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u6().clear_bit()),
#[cfg(esp32)]
Number::Unit7 => pcnt.ctrl().modify(|_, w| w.cnt_rst_u7().clear_bit()),
}
});
}
/// Pause the counter
pub fn pause(&self) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| match self.number {
Number::Unit0 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u0().set_bit()),
Number::Unit1 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u1().set_bit()),
Number::Unit2 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u2().set_bit()),
Number::Unit3 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u3().set_bit()),
#[cfg(esp32)]
Number::Unit4 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u4().set_bit()),
#[cfg(esp32)]
Number::Unit5 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u5().set_bit()),
#[cfg(esp32)]
Number::Unit6 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u6().set_bit()),
#[cfg(esp32)]
Number::Unit7 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u7().set_bit()),
});
}
/// Resume the counter
pub fn resume(&self) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| match self.number {
Number::Unit0 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u0().clear_bit()),
Number::Unit1 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u1().clear_bit()),
Number::Unit2 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u2().clear_bit()),
Number::Unit3 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u3().clear_bit()),
#[cfg(esp32)]
Number::Unit4 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u4().clear_bit()),
#[cfg(esp32)]
Number::Unit5 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u5().clear_bit()),
#[cfg(esp32)]
Number::Unit6 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u6().clear_bit()),
#[cfg(esp32)]
Number::Unit7 => pcnt.ctrl().modify(|_, w| w.cnt_pause_u7().clear_bit()),
});
}
/// Enable which events generate interrupts on this unit.
pub fn events(&self, events: Events) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
let conf0 = match self.number {
Number::Unit0 => pcnt.u0_conf0(),
Number::Unit1 => pcnt.u1_conf0(),
Number::Unit2 => pcnt.u2_conf0(),
Number::Unit3 => pcnt.u3_conf0(),
#[cfg(esp32)]
Number::Unit4 => pcnt.u4_conf0(),
#[cfg(esp32)]
Number::Unit5 => pcnt.u5_conf0(),
#[cfg(esp32)]
Number::Unit6 => pcnt.u6_conf0(),
#[cfg(esp32)]
Number::Unit7 => pcnt.u7_conf0(),
};
conf0.modify(|_, w| {
w.thr_l_lim_en()
.bit(events.low_limit)
.thr_h_lim_en()
.bit(events.high_limit)
.thr_thres0_en()
.bit(events.thresh0)
.thr_thres1_en()
.bit(events.thresh1)
.thr_zero_en()
.bit(events.zero)
});
}
/// Get the latest events for this unit.
pub fn get_events(&self) -> Events {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
let status = pcnt.u_status(self.number as usize).read();
Events {
low_limit: status.l_lim().bit(),
high_limit: status.h_lim().bit(),
thresh0: status.thres0().bit(),
thresh1: status.thres1().bit(),
zero: status.zero().bit(),
}
}
/// Get the mode of the last zero crossing
pub fn get_zero_mode(&self) -> ZeroMode {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
pcnt.u_status(self.number as usize)
.read()
.zero_mode()
.bits()
.into()
}
/// Enable interrupts for this unit.
pub fn listen(&self) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| {
pcnt.int_ena().modify(|_, w| match self.number {
Number::Unit0 => w.cnt_thr_event_u0().set_bit(),
Number::Unit1 => w.cnt_thr_event_u1().set_bit(),
Number::Unit2 => w.cnt_thr_event_u2().set_bit(),
Number::Unit3 => w.cnt_thr_event_u3().set_bit(),
#[cfg(esp32)]
Number::Unit4 => w.cnt_thr_event_u4().set_bit(),
#[cfg(esp32)]
Number::Unit5 => w.cnt_thr_event_u5().set_bit(),
#[cfg(esp32)]
Number::Unit6 => w.cnt_thr_event_u6().set_bit(),
#[cfg(esp32)]
Number::Unit7 => w.cnt_thr_event_u7().set_bit(),
})
});
}
/// Disable interrupts for this unit.
pub fn unlisten(&self, _cs: CriticalSection) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| {
pcnt.int_ena().write(|w| match self.number {
Number::Unit0 => w.cnt_thr_event_u0().clear_bit(),
Number::Unit1 => w.cnt_thr_event_u1().clear_bit(),
Number::Unit2 => w.cnt_thr_event_u2().clear_bit(),
Number::Unit3 => w.cnt_thr_event_u3().clear_bit(),
#[cfg(esp32)]
Number::Unit4 => w.cnt_thr_event_u4().clear_bit(),
#[cfg(esp32)]
Number::Unit5 => w.cnt_thr_event_u5().clear_bit(),
#[cfg(esp32)]
Number::Unit6 => w.cnt_thr_event_u6().clear_bit(),
#[cfg(esp32)]
Number::Unit7 => w.cnt_thr_event_u7().clear_bit(),
})
});
}
/// Returns true if an interrupt is active for this unit.
pub fn interrupt_set(&self) -> bool {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
match self.number {
Number::Unit0 => pcnt.int_st().read().cnt_thr_event_u0().bit(),
Number::Unit1 => pcnt.int_st().read().cnt_thr_event_u1().bit(),
Number::Unit2 => pcnt.int_st().read().cnt_thr_event_u2().bit(),
Number::Unit3 => pcnt.int_st().read().cnt_thr_event_u3().bit(),
#[cfg(esp32)]
Number::Unit4 => pcnt.int_st().read().cnt_thr_event_u4().bit(),
#[cfg(esp32)]
Number::Unit5 => pcnt.int_st().read().cnt_thr_event_u5().bit(),
#[cfg(esp32)]
Number::Unit6 => pcnt.int_st().read().cnt_thr_event_u6().bit(),
#[cfg(esp32)]
Number::Unit7 => pcnt.int_st().read().cnt_thr_event_u7().bit(),
}
}
/// Clear the interrupt bit for this unit.
pub fn reset_interrupt(&self) {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
critical_section::with(|_cs| {
pcnt.int_clr().write(|w| match self.number {
Number::Unit0 => w.cnt_thr_event_u0().set_bit(),
Number::Unit1 => w.cnt_thr_event_u1().set_bit(),
Number::Unit2 => w.cnt_thr_event_u2().set_bit(),
Number::Unit3 => w.cnt_thr_event_u3().set_bit(),
#[cfg(esp32)]
Number::Unit4 => w.cnt_thr_event_u4().set_bit(),
#[cfg(esp32)]
Number::Unit5 => w.cnt_thr_event_u5().set_bit(),
#[cfg(esp32)]
Number::Unit6 => w.cnt_thr_event_u6().set_bit(),
#[cfg(esp32)]
Number::Unit7 => w.cnt_thr_event_u7().set_bit(),
})
});
}
/// Get the current counter value.
pub fn get_value(&self) -> i16 {
let pcnt = unsafe { &*crate::peripherals::PCNT::ptr() };
pcnt.u_cnt(self.number as usize).read().cnt().bits() as i16
}
}

View File

@ -1,387 +0,0 @@
//! # Exclusive peripheral access
//!
//! ## Overview
//! The Peripheral module provides an exclusive access mechanism to peripherals
//! on ESP chips. It includes the `PeripheralRef` struct, which represents an
//! exclusive reference to a peripheral. It offers memory efficiency benefits
//! for zero-sized types.
//!
//! The `PeripheralRef` struct is used to access and interact with peripherals.
//! It implements the `Deref` and `DerefMut` traits, allowing you to dereference
//! it to access the underlying peripheral. It also provides methods for cloning
//! and re-borrowing the peripheral.
//!
//! The module also defines the `Peripheral` trait, which is implemented by
//! types that can be used as peripherals. The trait allows conversion between
//! owned and borrowed peripherals and provides an unsafe method for cloning the
//! peripheral. By implementing this trait, a type can be used with the
//! `PeripheralRef` struct.
//!
//! The module also includes a `peripheral_macros` module, which contains macros
//! for generating peripheral structs and associated traits based on
//! configuration options.
//!
//! ## Examples
//!
//! ### Initialization
//! ```no_run
//! let peripherals = Peripherals::take();
//! ```
//! ### Accessing peripherals
//! ```no_run
//! let mut rtc = Rtc::new(peripherals.RTC_CNTL);
//! ```
//! ```no_run
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
//! ```
use core::{
marker::PhantomData,
ops::{Deref, DerefMut},
};
/// An exclusive reference to a peripheral.
///
/// This is functionally the same as a `&'a mut T`. The reason for having a
/// dedicated struct is memory efficiency:
///
/// Peripheral singletons are typically either zero-sized (for concrete
/// peripehrals like `PA9` or `Spi4`) or very small (for example `AnyPin` which
/// is 1 byte). However `&mut T` is always 4 bytes for 32-bit targets, even if T
/// is zero-sized. PeripheralRef stores a copy of `T` instead, so it's the same
/// size.
///
/// but it is the size of `T` not the size
/// of a pointer. This is useful if T is a zero sized type.
pub struct PeripheralRef<'a, T> {
inner: T,
_lifetime: PhantomData<&'a mut T>,
}
impl<'a, T> PeripheralRef<'a, T> {
#[inline]
pub fn new(inner: T) -> Self {
Self {
inner,
_lifetime: PhantomData,
}
}
/// Unsafely clone (duplicate) a peripheral singleton.
///
/// # Safety
///
/// This returns an owned clone of the peripheral. You must manually ensure
/// only one copy of the peripheral is in use at a time. For example, don't
/// create two SPI drivers on `SPI1`, because they will "fight" each other.
///
/// You should strongly prefer using `reborrow()` instead. It returns a
/// `PeripheralRef` that borrows `self`, which allows the borrow checker
/// to enforce this at compile time.
pub unsafe fn clone_unchecked(&mut self) -> PeripheralRef<'a, T>
where
T: Peripheral<P = T>,
{
PeripheralRef::new(self.inner.clone_unchecked())
}
/// Reborrow into a "child" PeripheralRef.
///
/// `self` will stay borrowed until the child PeripheralRef is dropped.
pub fn reborrow(&mut self) -> PeripheralRef<'_, T>
where
T: Peripheral<P = T>,
{
// safety: we're returning the clone inside a new PeripheralRef that borrows
// self, so user code can't use both at the same time.
PeripheralRef::new(unsafe { self.inner.clone_unchecked() })
}
/// Map the inner peripheral using `Into`.
///
/// This converts from `PeripheralRef<'a, T>` to `PeripheralRef<'a, U>`,
/// using an `Into` impl to convert from `T` to `U`.
///
/// For example, this can be useful to degrade GPIO pins: converting from
/// PeripheralRef<'a, PB11>` to `PeripheralRef<'a, AnyPin>`.
#[inline]
pub fn map_into<U>(self) -> PeripheralRef<'a, U>
where
T: Into<U>,
{
PeripheralRef {
inner: self.inner.into(),
_lifetime: PhantomData,
}
}
}
impl<'a, T> Deref for PeripheralRef<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, T> DerefMut for PeripheralRef<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
/// Trait for any type that can be used as a peripheral of type `P`.
///
/// This is used in driver constructors, to allow passing either owned
/// peripherals (e.g. `TWISPI0`), or borrowed peripherals (e.g. `&mut TWISPI0`).
///
/// For example, if you have a driver with a constructor like this:
///
/// ```ignore
/// impl<'d, T: Instance> Twim<'d, T> {
/// pub fn new(
/// twim: impl Peripheral<P = T> + 'd,
/// irq: impl Peripheral<P = T::Interrupt> + 'd,
/// sda: impl Peripheral<P = impl GpioPin> + 'd,
/// scl: impl Peripheral<P = impl GpioPin> + 'd,
/// config: Config,
/// ) -> Self { .. }
/// }
/// ```
///
/// You may call it with owned peripherals, which yields an instance that can
/// live forever (`'static`):
///
/// ```ignore
/// let mut twi: Twim<'static, ...> = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
/// ```
///
/// Or you may call it with borrowed peripherals, which yields an instance that
/// can only live for as long as the borrows last:
///
/// ```ignore
/// let mut twi: Twim<'_, ...> = Twim::new(&mut p.TWISPI0, &mut irq, &mut p.P0_03, &mut p.P0_04, config);
/// ```
///
/// # Implementation details, for HAL authors
///
/// When writing a HAL, the intended way to use this trait is to take `impl
/// Peripheral<P = ..>` in the HAL's public API (such as driver constructors),
/// calling `.into_ref()` to obtain a `PeripheralRef`, and storing that in the
/// driver struct.
///
/// `.into_ref()` on an owned `T` yields a `PeripheralRef<'static, T>`.
/// `.into_ref()` on an `&'a mut T` yields a `PeripheralRef<'a, T>`.
pub trait Peripheral: Sized + sealed::Sealed {
/// Peripheral singleton type
type P;
/// Unsafely clone (duplicate) a peripheral singleton.
///
/// # Safety
///
/// This returns an owned clone of the peripheral. You must manually ensure
/// only one copy of the peripheral is in use at a time. For example, don't
/// create two SPI drivers on `SPI1`, because they will "fight" each other.
///
/// You should strongly prefer using `into_ref()` instead. It returns a
/// `PeripheralRef`, which allows the borrow checker to enforce this at
/// compile time.
unsafe fn clone_unchecked(&mut self) -> Self::P;
/// Convert a value into a `PeripheralRef`.
///
/// When called on an owned `T`, yields a `PeripheralRef<'static, T>`.
/// When called on an `&'a mut T`, yields a `PeripheralRef<'a, T>`.
#[inline]
fn into_ref<'a>(mut self) -> PeripheralRef<'a, Self::P>
where
Self: 'a,
{
PeripheralRef::new(unsafe { self.clone_unchecked() })
}
}
impl<T> Peripheral for &mut T
where
T: Peripheral<P = T>,
{
type P = T;
unsafe fn clone_unchecked(&mut self) -> Self::P {
T::clone_unchecked(self)
}
}
impl<T> sealed::Sealed for &mut T where T: sealed::Sealed {}
pub(crate) mod sealed {
pub trait Sealed {}
}
mod peripheral_macros {
#[doc(hidden)]
#[macro_export]
macro_rules! peripherals {
($($(#[$cfg:meta])? $name:ident <= $from_pac:tt),*$(,)?) => {
/// Contains the generated peripherals which implement [`Peripheral`]
mod peripherals {
pub use super::pac::*;
$(
crate::create_peripheral!($(#[$cfg])? $name <= $from_pac);
)*
}
#[allow(non_snake_case)]
pub struct Peripherals {
$(
$(#[$cfg])?
pub $name: peripherals::$name,
)*
}
impl Peripherals {
/// Returns all the peripherals *once*
#[inline]
pub fn take() -> Self {
#[no_mangle]
static mut _ESP_HAL_DEVICE_PERIPHERALS: bool = false;
critical_section::with(|_| unsafe {
if _ESP_HAL_DEVICE_PERIPHERALS {
panic!("init called more than once!")
}
_ESP_HAL_DEVICE_PERIPHERALS = true;
Self::steal()
})
}
}
impl Peripherals {
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self {
$(
$(#[$cfg])?
$name: peripherals::$name::steal(),
)*
}
}
}
// expose the new structs
$(
pub use peripherals::$name;
)*
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! into_ref {
($($name:ident),*) => {
$(
#[allow(unused_mut)]
let mut $name = $name.into_ref();
)*
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! create_peripheral {
($(#[$cfg:meta])? $name:ident <= virtual) => {
$(#[$cfg])?
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct $name { _inner: () }
$(#[$cfg])?
impl $name {
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self { _inner: () }
}
}
impl crate::peripheral::Peripheral for $name {
type P = $name;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self::steal()
}
}
impl crate::peripheral::sealed::Sealed for $name {}
};
($(#[$cfg:meta])? $name:ident <= $base:ident) => {
$(#[$cfg])?
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct $name { _inner: () }
$(#[$cfg])?
impl $name {
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self { _inner: () }
}
#[doc = r"Pointer to the register block"]
pub const PTR: *const <super::pac::$base as core::ops::Deref>::Target = super::pac::$base::PTR;
#[doc = r"Return the pointer to the register block"]
#[inline(always)]
pub const fn ptr() -> *const <super::pac::$base as core::ops::Deref>::Target {
super::pac::$base::PTR
}
}
impl core::ops::Deref for $name {
type Target = <super::pac::$base as core::ops::Deref>::Target;
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}
impl core::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(Self::PTR as *mut _) }
}
}
impl crate::peripheral::Peripheral for $name {
type P = $name;
#[inline]
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self::steal()
}
}
impl crate::peripheral::sealed::Sealed for $name {}
};
}
}

View File

@ -1,62 +0,0 @@
//! The prelude
//!
//! Re-exports all traits required for interacting with the various peripheral
//! drivers implemented in this crate.
pub use embedded_dma::{
ReadBuffer as _embedded_dma_ReadBuffer,
ReadTarget as _embedded_dma_ReadTarget,
Word as _embedded_dma_Word,
WriteBuffer as _embedded_dma_WriteBuffer,
WriteTarget as _embedded_dma_WriteTarget,
};
pub use embedded_hal::{
digital::v2::{
InputPin as _embedded_hal_digital_v2_InputPin,
OutputPin as _embedded_hal_digital_v2_OutputPin,
StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin,
ToggleableOutputPin as _embedded_hal_digital_v2_ToggleableOutputPin,
},
prelude::*,
};
pub use fugit::{
ExtU32 as _fugit_ExtU32,
ExtU64 as _fugit_ExtU64,
RateExtU32 as _fugit_RateExtU32,
RateExtU64 as _fugit_RateExtU64,
};
pub use nb;
#[cfg(any(apb_saradc, sens))]
pub use crate::analog::AnalogExt as _esp_hal_analog_AnalogExt;
#[cfg(any(gdma, pdma))]
pub use crate::dma::{
DmaTransfer as _esp_hal_dma_DmaTransfer,
DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx,
};
#[cfg(gpio)]
pub use crate::gpio::{
InputPin as _esp_hal_gpio_InputPin,
OutputPin as _esp_hal_gpio_OutputPin,
Pin as _esp_hal_gpio_Pin,
};
#[cfg(any(i2c0, i2c1))]
pub use crate::i2c::Instance as _esp_hal_i2c_Instance;
#[cfg(ledc)]
pub use crate::ledc::{
channel::{
ChannelHW as _esp_hal_ledc_channel_ChannelHW,
ChannelIFace as _esp_hal_ledc_channel_ChannelIFace,
},
timer::{TimerHW as _esp_hal_ledc_timer_TimerHW, TimerIFace as _esp_hal_ledc_timer_TimerIFace},
};
#[cfg(any(dport, pcr, system))]
pub use crate::system::SystemExt as _esp_hal_system_SystemExt;
#[cfg(any(timg0, timg1))]
pub use crate::timer::{
Instance as _esp_hal_timer_Instance,
TimerGroupInstance as _esp_hal_timer_TimerGroupInstance,
};
#[cfg(any(uart0, uart1, uart2))]
pub use crate::uart::{Instance as _esp_hal_uart_Instance, UartPins as _esp_hal_uart_UartPins};
pub use crate::{clock::Clock as _esp_hal_clock_Clock, entry, macros::*};

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +0,0 @@
//! # Random Number Generator
//!
//! ## Overview
//! The Random Number Generator (RNG) Driver for ESP chips is a software module
//! that provides an interface to generate random numbers using the RNG
//! peripheral on ESP chips. This driver allows you to generate random numbers
//! that can be used for various cryptographic, security, or general-purpose
//! applications.
//!
//! The RNG peripheral on ESP chips produces random numbers based on physical
//! noise sources, which provide true random numbers under specific conditions
//! (see conditions below).
//!
//! To use the [Rng] Driver, you need to initialize it with the RNG peripheral.
//! Once initialized, you can generate random numbers by calling the `random`
//! method, which returns a 32-bit unsigned integer.
//!
//! Additionally, this driver implements the
//! [Read](embedded_hal::blocking::rng::Read) trait from the `embedded_hal`
//! crate, allowing you to generate random bytes by calling the `read` method.
//
//! # Important Note
//!
//! There are certain pre-conditions which must be met in order for the RNG to
//! produce *true* random numbers. The hardware RNG produces true random numbers
//! under any of the following conditions:
//!
//! - RF subsystem is enabled (i.e. Wi-Fi or Bluetooth are enabled).
//! - An internal entropy source has been enabled by calling
//! `bootloader_random_enable()` and not yet disabled by calling
//! `bootloader_random_disable()`.
//! - While the ESP-IDF Second stage bootloader is running. This is because the
//! default ESP-IDF bootloader implementation calls
//! `bootloader_random_enable()` when the bootloader starts, and
//! `bootloader_random_disable()` before executing the app.
//!
//! When any of these conditions are true, samples of physical noise are
//! continuously mixed into the internal hardware RNG state to provide entropy.
//! If none of the above conditions are true, the output of the RNG should be
//! considered pseudo-random only.
//!
//! For more information, please refer to the ESP-IDF documentation:
//! <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html>
//!
//! # Examples
//!
//! ## Initialization
//!
//! ```no_run
//! let mut rng = Rng::new(peripherals.RNG);
//! ```
//!
//! ## Generate a random word (u32)
//!
//! ```no_run
//! let random: u32 = rng.random();
//! ```
//!
//! ## Fill a buffer of arbitrary size with random bytes
//!
//! ```no_run
//! let mut buffer = [0u8; 32];
//! rng.read(&mut buffer).unwrap();
//! ```
use core::{convert::Infallible, marker::PhantomData};
use crate::{peripheral::Peripheral, peripherals::RNG};
/// Random number generator driver
#[derive(Clone, Copy)]
pub struct Rng {
_phantom: PhantomData<RNG>,
}
impl Rng {
/// Create a new random number generator instance
pub fn new(_rng: impl Peripheral<P = RNG>) -> Self {
Self {
_phantom: PhantomData,
}
}
#[inline]
/// Reads currently available `u32` integer from `RNG`
pub fn random(&mut self) -> u32 {
// SAFETY: read-only register access
unsafe { &*crate::peripherals::RNG::PTR }
.data()
.read()
.bits()
}
}
impl embedded_hal::blocking::rng::Read for Rng {
type Error = Infallible;
fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> {
for chunk in buffer.chunks_mut(4) {
let bytes = self.random().to_le_bytes();
chunk.copy_from_slice(&bytes[..chunk.len()]);
}
Ok(())
}
}

View File

@ -1,216 +0,0 @@
use core::{
convert::Infallible,
marker::PhantomData,
ptr::{copy_nonoverlapping, write_bytes},
};
use crate::rsa::{
implement_op,
Multi,
Rsa,
RsaMode,
RsaModularExponentiation,
RsaModularMultiplication,
RsaMultiplication,
};
impl<'d> Rsa<'d> {
/// After the RSA Accelerator is released from reset, the memory blocks
/// needs to be initialized, only after that peripheral should be used.
/// This function would return without an error if the memory is initialized
pub fn ready(&mut self) -> nb::Result<(), Infallible> {
if self.rsa.clean().read().clean().bit_is_clear() {
return Err(nb::Error::WouldBlock);
}
Ok(())
}
pub(super) fn write_multi_mode(&mut self, mode: u32) {
self.rsa
.mult_mode()
.write(|w| unsafe { w.bits(mode as u32) });
}
pub(super) fn write_modexp_mode(&mut self, mode: u32) {
self.rsa.modexp_mode().write(|w| unsafe { w.bits(mode) });
}
pub(super) fn write_modexp_start(&mut self) {
self.rsa
.modexp_start()
.write(|w| w.modexp_start().set_bit());
}
pub(super) fn write_multi_start(&mut self) {
self.rsa.mult_start().write(|w| w.mult_start().set_bit());
}
pub(super) fn clear_interrupt(&mut self) {
self.rsa.interrupt().write(|w| w.interrupt().set_bit());
}
pub(super) fn is_idle(&mut self) -> bool {
self.rsa.interrupt().read().bits() == 1
}
unsafe fn write_multi_operand_a<const N: usize>(&mut self, operand_a: &[u32; N]) {
copy_nonoverlapping(
operand_a.as_ptr(),
self.rsa.x_mem(0).as_ptr() as *mut u32,
N,
);
write_bytes(self.rsa.x_mem(0).as_ptr().add(N), 0, N);
}
unsafe fn write_multi_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
write_bytes(self.rsa.z_mem(0).as_ptr(), 0, N);
copy_nonoverlapping(
operand_b.as_ptr(),
self.rsa.z_mem(0).as_ptr().add(N) as *mut u32,
N,
);
}
}
pub mod operand_sizes {
//! Marker types for the operand sizes
use paste::paste;
use super::{implement_op, Multi, RsaMode};
implement_op!(
(512, multi),
(1024, multi),
(1536, multi),
(2048, multi),
(2560),
(3072),
(3584),
(4096)
);
}
impl<'a, 'd, T: RsaMode, const N: usize> RsaModularMultiplication<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
/// Creates an Instance of `RsaMultiplication`.
/// `m_prime` could be calculated using `-(modular multiplicative inverse of
/// modulus) mod 2^32`, for more information check 24.3.2 in the
/// <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>
pub fn new(rsa: &'a mut Rsa<'d>, modulus: &T::InputType, m_prime: u32) -> Self {
Self::set_mode(rsa);
unsafe {
rsa.write_modulus(modulus);
}
rsa.write_mprime(m_prime);
Self {
rsa,
phantom: PhantomData,
}
}
fn set_mode(rsa: &mut Rsa) {
rsa.write_multi_mode((N / 16 - 1) as u32)
}
/// Starts the first step of modular multiplication operation. `r` could be
/// calculated using `2 ^ ( bitlength * 2 ) mod modulus`,
/// for more information check 24.3.2 in the
/// <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>
pub fn start_step1(&mut self, operand_a: &T::InputType, r: &T::InputType) {
unsafe {
self.rsa.write_operand_a(operand_a);
self.rsa.write_r(r);
}
self.set_start();
}
/// Starts the second step of modular multiplication operation.
/// This is a non blocking function that returns without an error if
/// operation is completed successfully. `start_step1` must be called
/// before calling this function.
pub fn start_step2(&mut self, operand_b: &T::InputType) {
loop {
if self.rsa.is_idle() {
self.rsa.clear_interrupt();
unsafe {
self.rsa.write_operand_a(operand_b);
}
self.set_start();
break;
}
}
}
fn set_start(&mut self) {
self.rsa.write_multi_start();
}
}
impl<'a, 'd, T: RsaMode, const N: usize> RsaModularExponentiation<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
/// Creates an Instance of `RsaModularExponentiation`.
/// `m_prime` could be calculated using `-(modular multiplicative inverse of
/// modulus) mod 2^32`, for more information check 24.3.2 in the
/// <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>
pub fn new(
rsa: &'a mut Rsa<'d>,
exponent: &T::InputType,
modulus: &T::InputType,
m_prime: u32,
) -> Self {
Self::set_mode(rsa);
unsafe {
rsa.write_operand_b(exponent);
rsa.write_modulus(modulus);
}
rsa.write_mprime(m_prime);
Self {
rsa,
phantom: PhantomData,
}
}
pub(super) fn set_mode(rsa: &mut Rsa) {
rsa.write_modexp_mode((N / 16 - 1) as u32)
}
pub(super) fn set_start(&mut self) {
self.rsa.write_modexp_start();
}
}
impl<'a, 'd, T: RsaMode + Multi, const N: usize> RsaMultiplication<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
/// Creates an Instance of `RsaMultiplication`.
pub fn new(rsa: &'a mut Rsa<'d>) -> Self {
Self::set_mode(rsa);
Self {
rsa,
phantom: PhantomData,
}
}
/// Starts the multiplication operation.
pub fn start_multiplication(&mut self, operand_a: &T::InputType, operand_b: &T::InputType) {
unsafe {
self.rsa.write_multi_operand_a(operand_a);
self.rsa.write_multi_operand_b(operand_b);
}
self.set_start();
}
pub(super) fn set_mode(rsa: &mut Rsa) {
rsa.write_multi_mode(((N * 2) / 16 + 7) as u32)
}
pub(super) fn set_start(&mut self) {
self.rsa.write_multi_start();
}
}

View File

@ -1,349 +0,0 @@
use core::{convert::Infallible, marker::PhantomData, ptr::copy_nonoverlapping};
use crate::rsa::{
implement_op,
Multi,
Rsa,
RsaMode,
RsaModularExponentiation,
RsaModularMultiplication,
RsaMultiplication,
};
impl<'d> Rsa<'d> {
/// After the RSA Accelerator is released from reset, the memory blocks
/// needs to be initialized, only after that peripheral should be used.
/// This function would return without an error if the memory is initialized
pub fn ready(&mut self) -> nb::Result<(), Infallible> {
if self.rsa.query_clean().read().query_clean().bit_is_clear() {
return Err(nb::Error::WouldBlock);
}
Ok(())
}
/// Enables/disables rsa interrupt, when enabled rsa perpheral would
/// generate an interrupt when a operation is finished.
pub fn enable_disable_interrupt(&mut self, enable: bool) {
match enable {
true => self.rsa.int_ena().write(|w| w.int_ena().set_bit()),
false => self.rsa.int_ena().write(|w| w.int_ena().clear_bit()),
}
}
fn write_mode(&mut self, mode: u32) {
self.rsa.mode().write(|w| unsafe { w.bits(mode as u32) });
}
/// Enables/disables search acceleration, when enabled it would increases
/// the performance of modular exponentiation by discarding the
/// exponent's bits before the most significant set bit. Note: this might
/// affect the security, for more info refer 18.3.4 of <https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf>
pub fn enable_disable_search_acceleration(&mut self, enable: bool) {
match enable {
true => self
.rsa
.search_enable()
.write(|w| w.search_enable().set_bit()),
false => self
.rsa
.search_enable()
.write(|w| w.search_enable().clear_bit()),
}
}
pub(super) fn is_search_enabled(&mut self) -> bool {
self.rsa.search_enable().read().search_enable().bit_is_set()
}
pub(super) fn write_search_position(&mut self, search_position: u32) {
self.rsa
.search_pos()
.write(|w| unsafe { w.bits(search_position) });
}
/// Enables/disables constant time acceleration, when enabled it would
/// increases the performance of modular exponentiation by simplifying
/// the calculation concerning the 0 bits of the exponent i.e. lesser the
/// hamming weight, greater the performance. Note : this might affect
/// the security, for more info refer 18.3.4 of <https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf>
pub fn enable_disable_constant_time_acceleration(&mut self, enable: bool) {
match enable {
true => self
.rsa
.constant_time()
.write(|w| w.constant_time().clear_bit()),
false => self
.rsa
.constant_time()
.write(|w| w.constant_time().set_bit()),
}
}
pub(super) fn write_modexp_start(&mut self) {
self.rsa
.set_start_modexp()
.write(|w| w.set_start_modexp().set_bit());
}
pub(super) fn write_multi_start(&mut self) {
self.rsa
.set_start_mult()
.write(|w| w.set_start_mult().set_bit());
}
fn write_modmulti_start(&mut self) {
self.rsa
.set_start_modmult()
.write(|w| w.set_start_modmult().set_bit());
}
pub(super) fn clear_interrupt(&mut self) {
self.rsa.int_clr().write(|w| w.clear_interrupt().set_bit());
}
pub(super) fn is_idle(&mut self) -> bool {
self.rsa.query_idle().read().query_idle().bit_is_set()
}
unsafe fn write_multi_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
copy_nonoverlapping(
operand_b.as_ptr(),
self.rsa.z_mem(0).as_ptr().add(N) as *mut u32,
N,
);
}
}
pub mod operand_sizes {
//! Marker types for the operand sizes
use paste::paste;
use super::{implement_op, Multi, RsaMode};
implement_op!(
(32, multi),
(64, multi),
(96, multi),
(128, multi),
(160, multi),
(192, multi),
(224, multi),
(256, multi),
(288, multi),
(320, multi),
(352, multi),
(384, multi),
(416, multi),
(448, multi),
(480, multi),
(512, multi),
(544, multi),
(576, multi),
(608, multi),
(640, multi),
(672, multi),
(704, multi),
(736, multi),
(768, multi),
(800, multi),
(832, multi),
(864, multi),
(896, multi),
(928, multi),
(960, multi),
(992, multi),
(1024, multi),
(1056, multi),
(1088, multi),
(1120, multi),
(1152, multi),
(1184, multi),
(1216, multi),
(1248, multi),
(1280, multi),
(1312, multi),
(1344, multi),
(1376, multi),
(1408, multi),
(1440, multi),
(1472, multi),
(1504, multi),
(1536, multi),
(1568),
(1600),
(1632),
(1664),
(1696),
(1728),
(1760),
(1792),
(1824),
(1856),
(1888),
(1920),
(1952),
(1984),
(2016),
(2048),
(2080),
(2112),
(2144),
(2176),
(2208),
(2240),
(2272),
(2304),
(2336),
(2368),
(2400),
(2432),
(2464),
(2496),
(2528),
(2560),
(2592),
(2624),
(2656),
(2688),
(2720),
(2752),
(2784),
(2816),
(2848),
(2880),
(2912),
(2944),
(2976),
(3008),
(3040),
(3072)
);
}
impl<'a, 'd, T: RsaMode, const N: usize> RsaModularExponentiation<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
/// Creates an Instance of `RsaModularExponentiation`.
/// `m_prime` could be calculated using `-(modular multiplicative inverse of
/// modulus) mod 2^32`, for more information check 19.3.1 in the
/// <https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf>
pub fn new(
rsa: &'a mut Rsa<'d>,
exponent: &T::InputType,
modulus: &T::InputType,
m_prime: u32,
) -> Self {
Self::set_mode(rsa);
unsafe {
rsa.write_operand_b(exponent);
rsa.write_modulus(modulus);
}
rsa.write_mprime(m_prime);
if rsa.is_search_enabled() {
rsa.write_search_position(Self::find_search_pos(exponent));
}
Self {
rsa,
phantom: PhantomData,
}
}
fn find_search_pos(exponent: &T::InputType) -> u32 {
for (i, byte) in exponent.iter().rev().enumerate() {
if *byte == 0 {
continue;
}
return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
}
0
}
pub(super) fn set_mode(rsa: &mut Rsa) {
rsa.write_mode((N - 1) as u32)
}
pub(super) fn set_start(&mut self) {
self.rsa.write_modexp_start();
}
}
impl<'a, 'd, T: RsaMode, const N: usize> RsaModularMultiplication<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
fn write_mode(rsa: &mut Rsa) {
rsa.write_mode((N - 1) as u32)
}
/// Creates an Instance of `RsaModularMultiplication`.
/// `m_prime` could be calculated using `-(modular multiplicative inverse of
/// modulus) mod 2^32`, for more information check 19.3.1 in the
/// <https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf>
pub fn new(
rsa: &'a mut Rsa<'d>,
operand_a: &T::InputType,
operand_b: &T::InputType,
modulus: &T::InputType,
m_prime: u32,
) -> Self {
Self::write_mode(rsa);
rsa.write_mprime(m_prime);
unsafe {
rsa.write_modulus(modulus);
rsa.write_operand_a(operand_a);
rsa.write_operand_b(operand_b);
}
Self {
rsa,
phantom: PhantomData,
}
}
/// Starts the modular multiplication operation. `r` could be calculated
/// using `2 ^ ( bitlength * 2 ) mod modulus`, for more information
/// check 19.3.1 in the <https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf>
pub fn start_modular_multiplication(&mut self, r: &T::InputType) {
unsafe {
self.rsa.write_r(r);
}
self.set_start();
}
fn set_start(&mut self) {
self.rsa.write_modmulti_start();
}
}
impl<'a, 'd, T: RsaMode + Multi, const N: usize> RsaMultiplication<'a, 'd, T>
where
T: RsaMode<InputType = [u32; N]>,
{
/// Creates an Instance of `RsaMultiplication`.
pub fn new(rsa: &'a mut Rsa<'d>, operand_a: &T::InputType) -> Self {
Self::set_mode(rsa);
unsafe {
rsa.write_operand_a(operand_a);
}
Self {
rsa,
phantom: PhantomData,
}
}
/// Starts the multiplication operation.
pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
unsafe {
self.rsa.write_multi_operand_b(operand_b);
}
self.set_start();
}
pub(super) fn set_mode(rsa: &mut Rsa) {
rsa.write_mode((N * 2 - 1) as u32)
}
pub(super) fn set_start(&mut self) {
self.rsa.write_multi_start();
}
}

Some files were not shown because too many files have changed in this diff Show More