
* RMT: make PulseCode a newtype rather than an extension trait on u32 This has several advantages: - the meaning of `u32` used as pulse code becomes more explicit - it allows using `PulseCode` methods in `const` context (which is otherwise not possible because Rust does not presently support associated const fn in traits). - it allows providing custom `defmt::Format` and `core::fmt::Debug` impls for `PulseCode`, greatly helping with debugging I have taken the liberty to implement `core::fmt::Debug` in a slightly non-standard way: The most natural implementation would probably use a struct-style output like PulseCode { length1: 42, level1: Level::High, length2: 24, level2: Level::Low } However, that is very lengthy and not really human-readable anymore when dealing with an array of `PulseCode`s. Thus, this uses the more compact format PulseCode(H 42, L 24) This provides `u32: From<PulseCode>` and `PulseCode: From<u32>` impls and converts rx and tx methods to accept `impl Into<PulseCode>` and `impl From<PulseCode>`, respectively. This should help to reduce how much user code needs to change (but replacing `u32` type annotations with `PulseCode` will be required). By applying `#[repr(transparent)]` to `struct PulseCode`, it is guaranteed to match the layout of `u32` such that accessing the hardware buffer via `*mut PulseCode` pointers is valid. * RMT: Address review on PulseCode refactor, further refine the interface a bit - introduce Level::const_from and Level::const_into - pre-compute a few more shifts and masks (this is unlikely to affect generated code, since the compiler would have const propagated them anyway, but it helps to keep the PulseCode impl more readable) - improve docstrings - remove PulseCode::empty in favor of PulseCode::default, keep PulseCode::end_marker for now (but it's not completely clear that this interface is optimal; see also the FIXME note on adding a variant of this methods that supports settings levels and length1) - make PulseCode::new_unchecked pub and shuffle it around in the code so that it doesn't show up first in the docs - factor out PulseCode::symbolX methods for internal use in debug formatting - sprinkle a few more #[inline] to be totally sure that this really adds no overhead over having plain u32 - convert methods receivers from &self to self given that PulseCode is Copy (which probably doesn't matter much since all these methods should always be inlined) - remove PulseCode::as_u32() and make the tuple field pub: There's no safety implication of marking this pub, and field access still provides a const-compatible way to obtain the wrapped value
Examples
This package contains a number of binary applications demonstrating the use of various hardware peripherals found within ESP32 the family of devices.
Each device has its own unique set of peripherals, and as such not every example will run on every device. We recommend building and flashing the examples using the xtask
method documented below, which will greatly simplify the process.
To check if a device is compatible with a given example, check the metadata comments above the imports, which will list all supported devices following the //% CHIPS:
designator. If this metadata is not present, then the example will work on any device supported by esp-hal
.
As previously stated, we use the cargo-xtask pattern for automation. Commands invoking this tool must be run from the root of the repository.
Building Examples
You can build all examples for a given device using the build examples
subcommand:
cargo xtask build examples esp-hal esp32
Note that we must specify which package to build the examples for, since this repository contains multiple packages (specifying esp-hal will build the examples in the examples package instead).
Running Examples
You can also build and then subsequently flash and run an example using the run example
subcommand. With a target device connected to your host system, run:
cargo xtask run example esp-hal esp32c6 --example embassy_hello_world
Again, note that we must specify which package to build the example from, plus which example to build and flash to the target device.
Adding Examples
If you are contributing to esp-hal
and would like to add an example, the process is generally the same as any other project.
One major difference in our case is the metadata comments which state the compatible devices and required features for an example. Both of these designators are optional; if //% CHIPS:
is omitted then all devices considered to be supported, and if //% FEATURES:
is omitted then no features are enabled at build time.
To demonstrated, in src/bin/embassy_hello_world.rs
you will see the following:
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy esp-hal-embassy/integrated-timers
Another thing to be aware of is the GPIO pins being used. We have tried to use pins available the DevKit-C boards from Espressif, however this is being done on a best-effort basis.
In general, the following GPIO are recommended for use, though be conscious of whether certain pins are used for UART, strapping pins, etc. on some devices:
- GPIO0
- GPIO1
- GPIO2
- GPIO3
- GPIO4
- GPIO5
- GPIO8
- GPIO9
- GPIO10