aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--cyw43-pio/CHANGELOG.md2
-rw-r--r--cyw43-pio/src/lib.rs108
-rw-r--r--docs/examples/basic/Cargo.toml2
-rw-r--r--docs/examples/basic/src/main.rs33
-rw-r--r--docs/pages/embassy_in_the_wild.adoc4
-rw-r--r--embassy-executor/CHANGELOG.md3
-rw-r--r--embassy-executor/Cargo.toml11
-rw-r--r--embassy-executor/build.rs5
-rw-r--r--embassy-executor/src/arch/cortex_ar.rs7
-rw-r--r--embassy-executor/src/raw/trace.rs2
-rw-r--r--embassy-mspm0/CHANGELOG.md5
-rw-r--r--embassy-mspm0/Cargo.toml4
-rw-r--r--embassy-mspm0/build.rs11
-rw-r--r--embassy-mspm0/src/i2c.rs13
-rw-r--r--embassy-mspm0/src/i2c_target.rs509
-rw-r--r--embassy-mspm0/src/lib.rs112
-rw-r--r--embassy-net-esp-hosted/CHANGELOG.md4
-rw-r--r--embassy-net-esp-hosted/Cargo.toml2
-rw-r--r--embassy-net-esp-hosted/src/control.rs66
-rw-r--r--embassy-net-esp-hosted/src/esp_hosted_config.proto205
-rw-r--r--embassy-net-esp-hosted/src/iface.rs62
-rw-r--r--embassy-net-esp-hosted/src/lib.rs71
-rw-r--r--embassy-net-esp-hosted/src/proto.rs14242
-rw-r--r--embassy-net-nrf91/CHANGELOG.md2
-rw-r--r--embassy-net-nrf91/Cargo.toml2
-rw-r--r--embassy-net/CHANGELOG.md2
-rw-r--r--embassy-net/src/tcp.rs14
-rw-r--r--embassy-nrf/CHANGELOG.md15
-rw-r--r--embassy-nrf/Cargo.toml23
-rw-r--r--embassy-nrf/src/buffered_uarte/mod.rs14
-rw-r--r--embassy-nrf/src/buffered_uarte/v1.rs (renamed from embassy-nrf/src/buffered_uarte.rs)125
-rw-r--r--embassy-nrf/src/buffered_uarte/v2.rs687
-rw-r--r--embassy-nrf/src/chips/nrf51.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs51
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs71
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs71
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs71
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs71
-rw-r--r--embassy-nrf/src/chips/nrf54l15_app.rs378
-rw-r--r--embassy-nrf/src/chips/nrf9120.rs39
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs39
-rw-r--r--embassy-nrf/src/cracen.rs157
-rw-r--r--embassy-nrf/src/gpio.rs2
-rw-r--r--embassy-nrf/src/gpiote.rs420
-rw-r--r--embassy-nrf/src/lib.rs50
-rw-r--r--embassy-nrf/src/ppi/dppi.rs11
-rw-r--r--embassy-nrf/src/ppi/mod.rs119
-rw-r--r--embassy-nrf/src/pwm.rs383
-rw-r--r--embassy-nrf/src/saadc.rs247
-rw-r--r--embassy-nrf/src/spim.rs163
-rw-r--r--embassy-nrf/src/spis.rs16
-rw-r--r--embassy-nrf/src/twim.rs44
-rw-r--r--embassy-nrf/src/twis.rs44
-rw-r--r--embassy-nrf/src/uarte.rs170
-rw-r--r--embassy-nxp/CHANGELOG.md3
-rw-r--r--embassy-nxp/Cargo.toml4
-rw-r--r--embassy-nxp/src/chips/lpc55.rs12
-rw-r--r--embassy-nxp/src/fmt.rs1
-rw-r--r--embassy-nxp/src/gpio/lpc55.rs66
-rw-r--r--embassy-nxp/src/lib.rs7
-rw-r--r--embassy-nxp/src/pwm.rs5
-rw-r--r--embassy-nxp/src/pwm/lpc55.rs325
-rw-r--r--embassy-nxp/src/usart/lpc55.rs173
-rw-r--r--embassy-rp/CHANGELOG.md3
-rw-r--r--embassy-rp/src/block.rs4
-rw-r--r--embassy-rp/src/clocks.rs2
-rw-r--r--embassy-rp/src/gpio.rs2
-rw-r--r--embassy-rp/src/i2c_slave.rs4
-rw-r--r--embassy-rp/src/multicore.rs2
-rw-r--r--embassy-rp/src/pio/mod.rs2
-rw-r--r--embassy-rp/src/pio_programs/i2s.rs18
-rw-r--r--embassy-rp/src/pio_programs/onewire.rs18
-rw-r--r--embassy-rp/src/pio_programs/pwm.rs2
-rw-r--r--embassy-rp/src/pio_programs/spi.rs4
-rw-r--r--embassy-rp/src/pio_programs/uart.rs2
-rw-r--r--embassy-rp/src/pio_programs/ws2812.rs123
-rw-r--r--embassy-rp/src/rom_data/rp2040.rs2
-rw-r--r--embassy-rp/src/rtc/mod.rs2
-rw-r--r--embassy-rp/src/spi.rs2
-rw-r--r--embassy-rp/src/uart/mod.rs2
-rw-r--r--embassy-stm32/CHANGELOG.md25
-rw-r--r--embassy-stm32/Cargo.toml21
-rw-r--r--embassy-stm32/build.rs25
-rw-r--r--embassy-stm32/src/adc/g4.rs359
-rw-r--r--embassy-stm32/src/adc/injected.rs44
-rw-r--r--embassy-stm32/src/adc/mod.rs20
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs182
-rw-r--r--embassy-stm32/src/adc/ringbuffered_v2.rs432
-rw-r--r--embassy-stm32/src/adc/v2.rs134
-rw-r--r--embassy-stm32/src/adc/v3.rs173
-rw-r--r--embassy-stm32/src/backup_sram.rs28
-rw-r--r--embassy-stm32/src/can/fd/config.rs13
-rw-r--r--embassy-stm32/src/can/fdcan.rs15
-rw-r--r--embassy-stm32/src/dsihost.rs12
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/flash/l.rs12
-rw-r--r--embassy-stm32/src/fmc.rs36
-rw-r--r--embassy-stm32/src/hrtim/mod.rs87
-rw-r--r--embassy-stm32/src/i2c/config.rs8
-rw-r--r--embassy-stm32/src/i2c/mod.rs102
-rw-r--r--embassy-stm32/src/i2c/v1.rs1080
-rw-r--r--embassy-stm32/src/i2c/v2.rs19
-rw-r--r--embassy-stm32/src/i2s.rs3
-rw-r--r--embassy-stm32/src/lib.rs20
-rw-r--r--embassy-stm32/src/low_power.rs141
-rw-r--r--embassy-stm32/src/rcc/bd.rs26
-rw-r--r--embassy-stm32/src/rcc/l.rs43
-rw-r--r--embassy-stm32/src/rcc/mod.rs5
-rw-r--r--embassy-stm32/src/rtc/low_power.rs15
-rw-r--r--embassy-stm32/src/rtc/mod.rs112
-rw-r--r--embassy-stm32/src/rtc/v2.rs2
-rw-r--r--embassy-stm32/src/rtc/v3.rs6
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs10
-rw-r--r--embassy-stm32/src/spi/mod.rs147
-rw-r--r--embassy-stm32/src/time_driver.rs78
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs12
-rw-r--r--embassy-stm32/src/timer/low_level.rs86
-rw-r--r--embassy-stm32/src/timer/mod.rs4
-rw-r--r--embassy-stm32/src/uid.rs4
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs34
-rw-r--r--embassy-stm32/src/vrefbuf/mod.rs8
-rw-r--r--embassy-usb-logger/CHANGELOG.md2
-rw-r--r--embassy-usb-logger/src/lib.rs20
-rw-r--r--examples/lpc55s69/src/bin/pwm.rs18
-rw-r--r--examples/mspm0g3507/src/bin/i2c_target.rs63
-rw-r--r--examples/mspm0l1306/src/bin/i2c_target.rs63
-rw-r--r--examples/nrf52840/src/bin/egu.rs15
-rw-r--r--examples/nrf52840/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf52840/src/bin/i2s_monitor.rs9
-rw-r--r--examples/nrf52840/src/bin/ppi.rs34
-rw-r--r--examples/nrf52840/src/bin/pwm.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ppi.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_servo.rs14
-rw-r--r--examples/nrf52840/src/bin/wifi_esp_hosted.rs16
-rw-r--r--examples/nrf5340/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf54l15/Cargo.toml9
-rw-r--r--examples/nrf54l15/src/bin/buffered_uart.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_channel.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_port.rs33
-rw-r--r--examples/nrf54l15/src/bin/pwm.rs86
-rw-r--r--examples/nrf54l15/src/bin/rng.rs28
-rw-r--r--examples/nrf54l15/src/bin/rtc.rs56
-rw-r--r--examples/nrf54l15/src/bin/saadc.rs28
-rw-r--r--examples/nrf54l15/src/bin/spim.rs30
-rw-r--r--examples/nrf54l15/src/bin/twim.rs37
-rw-r--r--examples/nrf54l15/src/bin/twis.rs47
-rw-r--r--examples/nrf54l15/src/bin/uart.rs37
-rw-r--r--examples/rp/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/stm32c0/src/bin/rtc.rs4
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs29
-rw-r--r--examples/stm32f4/src/bin/eth_w5500.rs3
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_async.rs135
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_blocking.rs132
-rw-r--r--examples/stm32f4/src/bin/rtc.rs4
-rw-r--r--examples/stm32g0/src/bin/onewire_ds18b20.rs2
-rw-r--r--examples/stm32g0/src/bin/rtc.rs4
-rw-r--r--examples/stm32g4/Cargo.toml13
-rw-r--r--examples/stm32g4/src/bin/adc_dma.rs4
-rw-r--r--examples/stm32g4/src/bin/adc_injected_and_regular.rs154
-rw-r--r--examples/stm32h5/Cargo.toml2
-rw-r--r--examples/stm32h5/src/bin/backup_sram.rs31
-rw-r--r--examples/stm32h5/src/bin/stop.rs8
-rw-r--r--examples/stm32h7/Cargo.toml2
-rw-r--r--examples/stm32h7/src/bin/rtc.rs4
-rw-r--r--examples/stm32h7/src/bin/spi.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_bdma.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32h755cm4/Cargo.toml2
-rw-r--r--examples/stm32h755cm7/Cargo.toml2
-rw-r--r--examples/stm32h7b0/Cargo.toml2
-rw-r--r--examples/stm32h7rs/Cargo.toml2
-rw-r--r--examples/stm32h7rs/src/bin/rtc.rs4
-rw-r--r--examples/stm32h7rs/src/bin/spi.rs2
-rw-r--r--examples/stm32h7rs/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32l4/src/bin/adc_dma.rs51
-rw-r--r--examples/stm32l4/src/bin/rtc.rs4
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs3
-rw-r--r--examples/stm32l5/src/bin/stop.rs8
-rw-r--r--examples/stm32u0/src/bin/rtc.rs4
-rw-r--r--examples/stm32wl/src/bin/rtc.rs4
-rw-r--r--examples/stm32wle5/.cargo/config.toml9
-rw-r--r--examples/stm32wle5/Cargo.toml38
-rw-r--r--examples/stm32wle5/README.md52
-rw-r--r--examples/stm32wle5/build.rs5
-rw-r--r--examples/stm32wle5/src/bin/adc.rs94
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs84
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs85
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs104
-rw-r--r--examples/stm32wle5/stm32wle5.code-workspace13
-rw-r--r--tests/nrf/.cargo/config.toml4
-rw-r--r--tests/nrf/src/bin/buffered_uart_spam.rs10
-rw-r--r--tests/nrf/src/bin/wifi_esp_hosted_perf.rs15
-rw-r--r--tests/stm32/Cargo.toml3
-rw-r--r--tests/stm32/src/bin/rtc.rs23
-rw-r--r--tests/stm32/src/bin/spi.rs7
-rw-r--r--tests/stm32/src/bin/spi_dma.rs7
-rw-r--r--tests/stm32/src/bin/stop.rs17
-rw-r--r--tests/stm32/src/common.rs2
206 files changed, 23136 insertions, 2546 deletions
diff --git a/README.md b/README.md
index de6b3bb59..950d19a6d 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Rust's [async/await](https://rust-lang.github.io/async-book/) allows for unprece
28 No more messing with hardware timers. [embassy_time](https://docs.embassy.dev/embassy-time) provides Instant, Duration, and Timer types that are globally available and never overflow. 28 No more messing with hardware timers. [embassy_time](https://docs.embassy.dev/embassy-time) provides Instant, Duration, and Timer types that are globally available and never overflow.
29 29
30- **Real-time ready** - 30- **Real-time ready** -
31 Tasks on the same async executor run cooperatively, but you can create multiple executors with different priorities so that higher priority tasks preempt lower priority ones. See the [example](https://github.com/embassy-rs/embassy/blob/master/examples/nrf52840/src/bin/multiprio.rs). 31 Tasks on the same async executor run cooperatively, but you can create multiple executors with different priorities so that higher priority tasks preempt lower priority ones. See the [example](https://github.com/embassy-rs/embassy/blob/main/examples/nrf52840/src/bin/multiprio.rs).
32 32
33- **Low-power ready** - 33- **Low-power ready** -
34 Easily build devices with years of battery life. The async executor automatically puts the core to sleep when there's no work to do. Tasks are woken by interrupts, there is no busy-loop polling while waiting. 34 Easily build devices with years of battery life. The async executor automatically puts the core to sleep when there's no work to do. Tasks are woken by interrupts, there is no busy-loop polling while waiting.
@@ -49,7 +49,7 @@ Rust's [async/await](https://rust-lang.github.io/async-book/) allows for unprece
49 [embassy-usb](https://docs.embassy.dev/embassy-usb/) implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. 49 [embassy-usb](https://docs.embassy.dev/embassy-usb/) implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own.
50 50
51- **Bootloader and DFU** - 51- **Bootloader and DFU** -
52 [embassy-boot](https://github.com/embassy-rs/embassy/tree/master/embassy-boot) is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. 52 [embassy-boot](https://github.com/embassy-rs/embassy/tree/main/embassy-boot) is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks.
53 53
54## Sneak peek 54## Sneak peek
55 55
diff --git a/cyw43-pio/CHANGELOG.md b/cyw43-pio/CHANGELOG.md
index ec38989e3..c2d18919c 100644
--- a/cyw43-pio/CHANGELOG.md
+++ b/cyw43-pio/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Select pio program based on core clock speed #4792
12
11## 0.8.0 - 2025-08-28 13## 0.8.0 - 2025-08-28
12 14
13- Bump cyw43 version 15- Bump cyw43 version
diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs
index 41ac6816d..c8715e662 100644
--- a/cyw43-pio/src/lib.rs
+++ b/cyw43-pio/src/lib.rs
@@ -7,6 +7,7 @@ use core::slice;
7 7
8use cyw43::SpiBusCyw43; 8use cyw43::SpiBusCyw43;
9use embassy_rp::Peri; 9use embassy_rp::Peri;
10use embassy_rp::clocks::clk_sys_freq;
10use embassy_rp::dma::Channel; 11use embassy_rp::dma::Channel;
11use embassy_rp::gpio::{Drive, Level, Output, Pull, SlewRate}; 12use embassy_rp::gpio::{Drive, Level, Output, Pull, SlewRate};
12use embassy_rp::pio::program::pio_asm; 13use embassy_rp::pio::program::pio_asm;
@@ -23,23 +24,24 @@ pub struct PioSpi<'d, PIO: Instance, const SM: usize, DMA: Channel> {
23 wrap_target: u8, 24 wrap_target: u8,
24} 25}
25 26
26/// The default clock divider that works for Pico 1 and 2 W. As well as the RM2 on rp2040 devices. 27/// Clock divider used for most applications
27/// same speed as pico-sdk, 62.5Mhz 28/// With default core clock configuration:
28/// This is actually the fastest we can go without overclocking. 29/// RP2350: 150Mhz / 2 = 75Mhz pio clock -> 37.5Mhz GSPI clock
29/// According to data sheet, the theoretical maximum is 100Mhz Pio => 50Mhz SPI Freq. 30/// RP2040: 133Mhz / 2 = 66.5Mhz pio clock -> 33.25Mhz GSPI clock
30/// However, the PIO uses a fractional divider, which works by introducing jitter when
31/// the divider is not an integer. It does some clocks at 125mhz and others at 62.5mhz
32/// so that it averages out to the desired frequency of 100mhz. The 125mhz clock cycles
33/// violate the maximum from the data sheet.
34pub const DEFAULT_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0200); 31pub const DEFAULT_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0200);
35 32
36/// The overclock clock divider for the Pico 1 W. Does not work on any known RM2 devices. 33/// Clock divider used to overclock the cyw43
37/// 125mhz Pio => 62.5Mhz SPI Freq. 25% higher than theoretical maximum according to 34/// With default core clock configuration:
38/// data sheet, but seems to work fine. 35/// RP2350: 150Mhz / 1 = 150Mhz pio clock -> 75Mhz GSPI clock (50% greater that manufacturer
36/// recommended 50Mhz)
37/// RP2040: 133Mhz / 1 = 133Mhz pio clock -> 66.5Mhz GSPI clock (33% greater that manufacturer
38/// recommended 50Mhz)
39pub const OVERCLOCK_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0100); 39pub const OVERCLOCK_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0100);
40 40
41/// The clock divider for the RM2 module. Found to be needed for the Pimoroni Pico Plus 2 W, 41/// Clock divider used with the RM2
42/// Pico Plus 2 Non w with the RM2 breakout module, and the Pico 2 with the RM2 breakout module. 42/// With default core clock configuration:
43/// RP2350: 150Mhz / 3 = 50Mhz pio clock -> 25Mhz GSPI clock
44/// RP2040: 133Mhz / 3 = 44.33Mhz pio clock -> 22.16Mhz GSPI clock
43pub const RM2_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0300); 45pub const RM2_CLOCK_DIVIDER: FixedU32<U8> = FixedU32::from_bits(0x0300);
44 46
45impl<'d, PIO, const SM: usize, DMA> PioSpi<'d, PIO, SM, DMA> 47impl<'d, PIO, const SM: usize, DMA> PioSpi<'d, PIO, SM, DMA>
@@ -58,7 +60,40 @@ where
58 clk: Peri<'d, impl PioPin>, 60 clk: Peri<'d, impl PioPin>,
59 dma: Peri<'d, DMA>, 61 dma: Peri<'d, DMA>,
60 ) -> Self { 62 ) -> Self {
61 let loaded_program = if clock_divider < DEFAULT_CLOCK_DIVIDER { 63 let effective_pio_frequency = (clk_sys_freq() as f32 / clock_divider.to_num::<f32>()) as u32;
64
65 #[cfg(feature = "defmt")]
66 defmt::trace!("Effective pio frequency: {}Hz", effective_pio_frequency);
67
68 // Non-integer pio clock dividers are achieved by introducing clock jitter resulting in a
69 // combination of long and short cycles. The long and short cycles average to achieve the
70 // requested clock speed.
71 // This can be a problem for peripherals that expect a consistent clock / have a clock
72 // speed upper bound that is violated by the short cycles. The cyw43 seems to handle the
73 // jitter well, but we emit a warning to recommend an integer divider anyway.
74 if clock_divider.frac() != FixedU32::<U8>::ZERO {
75 #[cfg(feature = "defmt")]
76 defmt::trace!(
77 "Configured clock divider is not a whole number. Some clock cycles may violate the maximum recommended GSPI speed. Use at your own risk."
78 );
79 }
80
81 // Different pio programs must be used for different pio clock speeds.
82 // The programs used below are based on the pico SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.pio
83 // The clock speed cutoff for each program has been determined experimentally:
84 // > 100Mhz -> Overclock program
85 // [75Mhz, 100Mhz] -> High speed program
86 // [0, 75Mhz) -> Low speed program
87 let loaded_program = if effective_pio_frequency > 100_000_000 {
88 // Any frequency > 100Mhz is overclocking the chip (manufacturer recommends max 50Mhz GSPI
89 // clock)
90 // Example:
91 // * RP2040 @ 133Mhz (stock) with OVERCLOCK_CLOCK_DIVIDER (133MHz)
92 #[cfg(feature = "defmt")]
93 defmt::trace!(
94 "Configured clock divider results in a GSPI frequency greater than the manufacturer recommendation (50Mhz). Use at your own risk."
95 );
96
62 let overclock_program = pio_asm!( 97 let overclock_program = pio_asm!(
63 ".side_set 1" 98 ".side_set 1"
64 99
@@ -69,7 +104,7 @@ where
69 "jmp x-- lp side 1" 104 "jmp x-- lp side 1"
70 // switch directions 105 // switch directions
71 "set pindirs, 0 side 0" 106 "set pindirs, 0 side 0"
72 "nop side 1" // necessary for clkdiv=1. 107 "nop side 1"
73 "nop side 0" 108 "nop side 0"
74 // read in y-1 bits 109 // read in y-1 bits
75 "lp2:" 110 "lp2:"
@@ -83,8 +118,47 @@ where
83 ".wrap" 118 ".wrap"
84 ); 119 );
85 common.load_program(&overclock_program.program) 120 common.load_program(&overclock_program.program)
121 } else if effective_pio_frequency >= 75_000_000 {
122 // Experimentally determined cutoff.
123 // Notably includes the stock RP2350 configured with clk_div of 2 (150Mhz base clock / 2 = 75Mhz)
124 // but does not include stock RP2040 configured with clk_div of 2 (133Mhz base clock / 2 = 66.5Mhz)
125 // Example:
126 // * RP2350 @ 150Mhz (stock) with DEFAULT_CLOCK_DIVIDER (75Mhz)
127 // * RP2XXX @ 200Mhz with DEFAULT_CLOCK_DIVIDER (100Mhz)
128 #[cfg(feature = "defmt")]
129 defmt::trace!("Using high speed pio program.");
130 let high_speed_program = pio_asm!(
131 ".side_set 1"
132
133 ".wrap_target"
134 // write out x-1 bits
135 "lp:"
136 "out pins, 1 side 0"
137 "jmp x-- lp side 1"
138 // switch directions
139 "set pindirs, 0 side 0"
140 "nop side 1"
141 // read in y-1 bits
142 "lp2:"
143 "in pins, 1 side 0"
144 "jmp y-- lp2 side 1"
145
146 // wait for event and irq host
147 "wait 1 pin 0 side 0"
148 "irq 0 side 0"
149
150 ".wrap"
151 );
152 common.load_program(&high_speed_program.program)
86 } else { 153 } else {
87 let default_program = pio_asm!( 154 // Low speed
155 // Examples:
156 // * RP2040 @ 133Mhz (stock) with DEFAULT_CLOCK_DIVIDER (66.5Mhz)
157 // * RP2040 @ 133Mhz (stock) with RM2_CLOCK_DIVIDER (44.3Mhz)
158 // * RP2350 @ 150Mhz (stock) with RM2_CLOCK_DIVIDER (50Mhz)
159 #[cfg(feature = "defmt")]
160 defmt::trace!("Using low speed pio program.");
161 let low_speed_program = pio_asm!(
88 ".side_set 1" 162 ".side_set 1"
89 163
90 ".wrap_target" 164 ".wrap_target"
@@ -106,7 +180,7 @@ where
106 180
107 ".wrap" 181 ".wrap"
108 ); 182 );
109 common.load_program(&default_program.program) 183 common.load_program(&low_speed_program.program)
110 }; 184 };
111 185
112 let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio); 186 let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio);
diff --git a/docs/examples/basic/Cargo.toml b/docs/examples/basic/Cargo.toml
index b90180853..fadda102b 100644
--- a/docs/examples/basic/Cargo.toml
+++ b/docs/examples/basic/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2authors = ["Dario Nieuwenhuis <[email protected]>"] 2authors = ["Dario Nieuwenhuis <[email protected]>"]
3edition = "2018" 3edition = "2024"
4name = "embassy-basic-example" 4name = "embassy-basic-example"
5version = "0.1.0" 5version = "0.1.0"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
diff --git a/docs/examples/basic/src/main.rs b/docs/examples/basic/src/main.rs
index 6e274bacb..42797612c 100644
--- a/docs/examples/basic/src/main.rs
+++ b/docs/examples/basic/src/main.rs
@@ -3,24 +3,41 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive}; 6use embassy_nrf::Peri;
7use embassy_time::{Duration, Timer}; 7use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pull};
8use {defmt_rtt as _, panic_probe as _}; // global logger 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
9 10
11// Declare async tasks
10#[embassy_executor::task] 12#[embassy_executor::task]
11async fn blinker(mut led: Output<'static>, interval: Duration) { 13async fn blink(pin: Peri<'static, AnyPin>) {
14 let mut led = Output::new(pin, Level::Low, OutputDrive::Standard);
15
12 loop { 16 loop {
17 // Timekeeping is globally available, no need to mess with hardware timers.
13 led.set_high(); 18 led.set_high();
14 Timer::after(interval).await; 19 Timer::after_millis(150).await;
15 led.set_low(); 20 led.set_low();
16 Timer::after(interval).await; 21 Timer::after_millis(150).await;
17 } 22 }
18} 23}
19 24
25// Main is itself an async task as well.
20#[embassy_executor::main] 26#[embassy_executor::main]
21async fn main(spawner: Spawner) { 27async fn main(spawner: Spawner) {
28 // Initialize the embassy-nrf HAL.
22 let p = embassy_nrf::init(Default::default()); 29 let p = embassy_nrf::init(Default::default());
23 30
24 let led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); 31 // Spawned tasks run in the background, concurrently.
25 spawner.spawn(unwrap!(blinker(led, Duration::from_millis(300)))); 32 spawner.spawn(blink(p.P0_13.into()).unwrap());
33
34 let mut button = Input::new(p.P0_11, Pull::Up);
35 loop {
36 // Asynchronously wait for GPIO events, allowing other tasks
37 // to run, or the core to sleep.
38 button.wait_for_low().await;
39 info!("Button pressed!");
40 button.wait_for_high().await;
41 info!("Button released!");
42 }
26} 43}
diff --git a/docs/pages/embassy_in_the_wild.adoc b/docs/pages/embassy_in_the_wild.adoc
index 3b58bb9b4..0792130eb 100644
--- a/docs/pages/embassy_in_the_wild.adoc
+++ b/docs/pages/embassy_in_the_wild.adoc
@@ -4,6 +4,10 @@ Here are known examples of real-world projects which make use of Embassy. Feel f
4 4
5_newer entries at the top_ 5_newer entries at the top_
6 6
7* link:https://github.com/thataquarel/protovolt[ProtoV MINI: A USB-C mini lab power supply]
8** A dual-channel USB PD powered breadboard power supply based on the RP2040, running embedded graphics. Open-source schematics and firmware.
9* link:https://github.com/Dawson-HEP/opentrig/[Opentrig: A particle physics trigger and data acquisition system]
10** Digital event trigger with threshold, data acquisition system designed to interface with AIDA-2020 TLU systems, tested at the DESY II Test Beam Facility. Based on the RP2040, and Embassy's async event handling.
7* link:https://github.com/1-rafael-1/air-quality-monitor[Air Quality Monitor] 11* link:https://github.com/1-rafael-1/air-quality-monitor[Air Quality Monitor]
8** Air Quality Monitor based on rp2350 board, ens160 and aht21 sensors and ssd1306 display. Code and 3D printable enclosure included. 12** Air Quality Monitor based on rp2350 board, ens160 and aht21 sensors and ssd1306 display. Code and 3D printable enclosure included.
9* link:https://github.com/CarlKCarlK/clock[Embassy Clock: Layered, modular bare-metal clock with emulation] 13* link:https://github.com/CarlKCarlK/clock[Embassy Clock: Layered, modular bare-metal clock with emulation]
diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md
index 47a8ae995..5fbb8cf13 100644
--- a/embassy-executor/CHANGELOG.md
+++ b/embassy-executor/CHANGELOG.md
@@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13- Upgraded rtos-trace 13- Upgraded rtos-trace
14- Added optional "highest priority" scheduling 14- Added optional "highest priority" scheduling
15- Added optional "earliest deadline first" EDF scheduling 15- Added optional "earliest deadline first" EDF scheduling
16- Bump `cortex-ar` to v0.3 16- Migrate `cortex-ar` to `aarch32-cpu`. The feature name `arch-cortex-ar` remains the same and
17 legacy ARM architectures are not supported.
17 18
18## 0.9.1 - 2025-08-31 19## 0.9.1 - 2025-08-31
19 20
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index ecc4b6338..d3e5b241a 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -30,6 +30,7 @@ build = [
30 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-deadline"]}, 30 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-deadline"]},
31 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-priority", "scheduler-deadline"]}, 31 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-priority", "scheduler-deadline"]},
32 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-deadline"]}, 32 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "scheduler-deadline"]},
33 {target = "thumbv7em-none-eabi", features = ["arch-cortex-m", "executor-interrupt", "executor-thread", "embassy-time-driver", "scheduler-priority", "scheduler-deadline", "trace"]},
33 {target = "thumbv7em-none-eabi", features = ["arch-spin"]}, 34 {target = "thumbv7em-none-eabi", features = ["arch-spin"]},
34 {target = "thumbv7em-none-eabi", features = ["arch-spin", "scheduler-deadline"]}, 35 {target = "thumbv7em-none-eabi", features = ["arch-spin", "scheduler-deadline"]},
35 {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]}, 36 {target = "armv7a-none-eabi", features = ["arch-cortex-ar", "executor-thread"]},
@@ -37,6 +38,7 @@ build = [
37 {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]}, 38 {target = "armv7r-none-eabihf", features = ["arch-cortex-ar", "executor-thread"]},
38 {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32"]}, 39 {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32"]},
39 {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread"]}, 40 {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread"]},
41 {target = "riscv32imac-unknown-none-elf", features = ["arch-riscv32", "executor-thread", "trace"]},
40 # Nightly builds 42 # Nightly builds
41 {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly"]}, 43 {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly"]},
42 {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "log"]}, 44 {group = "nightly", target = "thumbv7em-none-eabi", features = ["nightly", "log"]},
@@ -100,7 +102,7 @@ portable-atomic = { version = "1.5", optional = true }
100cortex-m = { version = "0.7.6", optional = true } 102cortex-m = { version = "0.7.6", optional = true }
101 103
102# arch-cortex-ar dependencies 104# arch-cortex-ar dependencies
103cortex-ar = { version = "0.3", optional = true } 105aarch32-cpu = { version = "0.1", optional = true }
104 106
105# arch-wasm dependencies 107# arch-wasm dependencies
106wasm-bindgen = { version = "0.2.82", optional = true } 108wasm-bindgen = { version = "0.2.82", optional = true }
@@ -128,7 +130,7 @@ nightly = ["embassy-executor-macros/nightly"]
128## Enable defmt logging 130## Enable defmt logging
129defmt = ["dep:defmt"] 131defmt = ["dep:defmt"]
130 132
131## Enable log logging 133## Enable log logging
132log = ["dep:log"] 134log = ["dep:log"]
133 135
134# Enables turbo wakers, which requires patching core. Not surfaced in the docs by default due to 136# Enables turbo wakers, which requires patching core. Not surfaced in the docs by default due to
@@ -143,7 +145,7 @@ arch-std = ["_arch"]
143## Cortex-M 145## Cortex-M
144arch-cortex-m = ["_arch", "dep:cortex-m"] 146arch-cortex-m = ["_arch", "dep:cortex-m"]
145## Cortex-A/R 147## Cortex-A/R
146arch-cortex-ar = ["_arch", "dep:cortex-ar"] 148arch-cortex-ar = ["_arch", "dep:aarch32-cpu", "dep:arm-targets"]
147## RISC-V 32 149## RISC-V 32
148arch-riscv32 = ["_arch"] 150arch-riscv32 = ["_arch"]
149## WASM 151## WASM
@@ -180,3 +182,6 @@ scheduler-priority = []
180## Enable the embassy_time_driver dependency. 182## Enable the embassy_time_driver dependency.
181## This can unlock extra APIs, for example for the `sheduler-deadline` 183## This can unlock extra APIs, for example for the `sheduler-deadline`
182embassy-time-driver = ["dep:embassy-time-driver"] 184embassy-time-driver = ["dep:embassy-time-driver"]
185
186[build-dependencies]
187arm-targets = { version = "0.4", optional = true }
diff --git a/embassy-executor/build.rs b/embassy-executor/build.rs
index 37becde3e..36e23a632 100644
--- a/embassy-executor/build.rs
+++ b/embassy-executor/build.rs
@@ -4,4 +4,9 @@ mod common;
4fn main() { 4fn main() {
5 let mut rustc_cfgs = common::CfgSet::new(); 5 let mut rustc_cfgs = common::CfgSet::new();
6 common::set_target_cfgs(&mut rustc_cfgs); 6 common::set_target_cfgs(&mut rustc_cfgs);
7
8 // This is used to exclude legacy architecture support. The raw executor needs to be used for
9 // those architectures because SEV/WFE are not supported.
10 #[cfg(feature = "arch-cortex-ar")]
11 arm_targets::process();
7} 12}
diff --git a/embassy-executor/src/arch/cortex_ar.rs b/embassy-executor/src/arch/cortex_ar.rs
index a9be3d323..ce572738a 100644
--- a/embassy-executor/src/arch/cortex_ar.rs
+++ b/embassy-executor/src/arch/cortex_ar.rs
@@ -1,3 +1,6 @@
1#[cfg(arm_profile = "legacy")]
2compile_error!("`arch-cortex-ar` does not support the legacy ARM profile, WFE/SEV are not available.");
3
1#[cfg(feature = "executor-interrupt")] 4#[cfg(feature = "executor-interrupt")]
2compile_error!("`executor-interrupt` is not supported with `arch-cortex-ar`."); 5compile_error!("`executor-interrupt` is not supported with `arch-cortex-ar`.");
3 6
@@ -10,7 +13,7 @@ fn __pender(context: *mut ()) {
10 #[cfg(feature = "executor-thread")] 13 #[cfg(feature = "executor-thread")]
11 // Try to make Rust optimize the branching away if we only use thread mode. 14 // Try to make Rust optimize the branching away if we only use thread mode.
12 if !cfg!(feature = "executor-interrupt") || context == THREAD_PENDER { 15 if !cfg!(feature = "executor-interrupt") || context == THREAD_PENDER {
13 cortex_ar::asm::sev(); 16 aarch32_cpu::asm::sev();
14 return; 17 return;
15 } 18 }
16} 19}
@@ -23,7 +26,7 @@ mod thread {
23 26
24 use core::marker::PhantomData; 27 use core::marker::PhantomData;
25 28
26 use cortex_ar::asm::wfe; 29 use aarch32_cpu::asm::wfe;
27 pub use embassy_executor_macros::main_cortex_ar as main; 30 pub use embassy_executor_macros::main_cortex_ar as main;
28 31
29 use crate::{Spawner, raw}; 32 use crate::{Spawner, raw};
diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs
index 74519b927..830162039 100644
--- a/embassy-executor/src/raw/trace.rs
+++ b/embassy-executor/src/raw/trace.rs
@@ -169,7 +169,7 @@ impl TaskTracker {
169} 169}
170 170
171#[cfg(feature = "trace")] 171#[cfg(feature = "trace")]
172extern "Rust" { 172unsafe extern "Rust" {
173 /// This callback is called when the executor begins polling. This will always 173 /// This callback is called when the executor begins polling. This will always
174 /// be paired with a later call to `_embassy_trace_executor_idle`. 174 /// be paired with a later call to `_embassy_trace_executor_idle`.
175 /// 175 ///
diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md
index 948f0205d..f0b5868f4 100644
--- a/embassy-mspm0/CHANGELOG.md
+++ b/embassy-mspm0/CHANGELOG.md
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) 11- feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435)
12- fix gpio interrupt not being set for mspm0l110x 12- fix gpio interrupt not being set for mspm0l110x
13- feat: Add window watchdog implementation based on WWDT0, WWDT1 peripherals (#4574) 13- feat: Add window watchdog implementation based on WWDT0, WWDT1 peripherals (#4574)
@@ -16,3 +16,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16- fix: gpio OutputOpenDrain config (#4735) 16- fix: gpio OutputOpenDrain config (#4735)
17- fix: add MSPM0C1106 to build test matrix 17- fix: add MSPM0C1106 to build test matrix
18- feat: add MSPM0H3216 support 18- feat: add MSPM0H3216 support
19- feat: Add i2c target implementation (#4605)
20- fix: group irq handlers must check for NO_INTR (#4785)
21- feat: Add read_reset_cause function
diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml
index df6176ff6..b76bc7e41 100644
--- a/embassy-mspm0/Cargo.toml
+++ b/embassy-mspm0/Cargo.toml
@@ -72,7 +72,7 @@ cortex-m = "0.7.6"
72critical-section = "1.2.0" 72critical-section = "1.2.0"
73 73
74# mspm0-metapac = { version = "" } 74# mspm0-metapac = { version = "" }
75mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-e7de4103a0713772695ffcad52c3c2f07414dc29" } 75mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-8542f260cc89645a983b7f1a874c87b21822279e" }
76 76
77[build-dependencies] 77[build-dependencies]
78proc-macro2 = "1.0.94" 78proc-macro2 = "1.0.94"
@@ -80,7 +80,7 @@ quote = "1.0.40"
80cfg_aliases = "0.2.1" 80cfg_aliases = "0.2.1"
81 81
82# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } 82# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] }
83mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-e7de4103a0713772695ffcad52c3c2f07414dc29", default-features = false, features = ["metadata"] } 83mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-8542f260cc89645a983b7f1a874c87b21822279e", default-features = false, features = ["metadata"] }
84 84
85[features] 85[features]
86default = ["rt"] 86default = ["rt"]
diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs
index 1d118ad66..4942364aa 100644
--- a/embassy-mspm0/build.rs
+++ b/embassy-mspm0/build.rs
@@ -194,8 +194,15 @@ fn generate_groups() -> TokenStream {
194 use crate::pac::#group_enum; 194 use crate::pac::#group_enum;
195 195
196 let group = crate::pac::CPUSS.int_group(#group_number); 196 let group = crate::pac::CPUSS.int_group(#group_number);
197 // MUST subtract by 1 since 0 is NO_INTR 197 let stat = group.iidx().read().stat();
198 let iidx = group.iidx().read().stat().to_bits() - 1; 198
199 // check for spurious interrupts
200 if stat == crate::pac::cpuss::vals::Iidx::NO_INTR {
201 return;
202 }
203
204 // MUST subtract by 1 because NO_INTR offsets IIDX values.
205 let iidx = stat.to_bits() - 1;
199 206
200 let Ok(group) = #group_enum::try_from(iidx as u8) else { 207 let Ok(group) = #group_enum::try_from(iidx as u8) else {
201 return; 208 return;
diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs
index 192527dd2..3067f4833 100644
--- a/embassy-mspm0/src/i2c.rs
+++ b/embassy-mspm0/src/i2c.rs
@@ -56,7 +56,7 @@ pub enum ClockDiv {
56} 56}
57 57
58impl ClockDiv { 58impl ClockDiv {
59 fn into(self) -> vals::Ratio { 59 pub(crate) fn into(self) -> vals::Ratio {
60 match self { 60 match self {
61 Self::DivBy1 => vals::Ratio::DIV_BY_1, 61 Self::DivBy1 => vals::Ratio::DIV_BY_1,
62 Self::DivBy2 => vals::Ratio::DIV_BY_2, 62 Self::DivBy2 => vals::Ratio::DIV_BY_2,
@@ -133,6 +133,11 @@ pub enum ConfigError {
133 /// 133 ///
134 /// The clock soure is not enabled is SYSCTL. 134 /// The clock soure is not enabled is SYSCTL.
135 ClockSourceNotEnabled, 135 ClockSourceNotEnabled,
136
137 /// Invalid target address.
138 ///
139 /// The target address is not 7-bit.
140 InvalidTargetAddress,
136} 141}
137 142
138#[non_exhaustive] 143#[non_exhaustive]
@@ -140,7 +145,7 @@ pub enum ConfigError {
140/// Config 145/// Config
141pub struct Config { 146pub struct Config {
142 /// I2C clock source. 147 /// I2C clock source.
143 clock_source: ClockSel, 148 pub(crate) clock_source: ClockSel,
144 149
145 /// I2C clock divider. 150 /// I2C clock divider.
146 pub clock_div: ClockDiv, 151 pub clock_div: ClockDiv,
@@ -196,7 +201,7 @@ impl Config {
196 } 201 }
197 202
198 #[cfg(any(mspm0c110x, mspm0c1105_c1106))] 203 #[cfg(any(mspm0c110x, mspm0c1105_c1106))]
199 fn calculate_clock_source(&self) -> u32 { 204 pub(crate) fn calculate_clock_source(&self) -> u32 {
200 // Assume that BusClk has default value. 205 // Assume that BusClk has default value.
201 // TODO: calculate BusClk more precisely. 206 // TODO: calculate BusClk more precisely.
202 match self.clock_source { 207 match self.clock_source {
@@ -209,7 +214,7 @@ impl Config {
209 mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0h321x, mspm0l110x, mspm0l122x, 214 mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x, mspm0h321x, mspm0l110x, mspm0l122x,
210 mspm0l130x, mspm0l134x, mspm0l222x 215 mspm0l130x, mspm0l134x, mspm0l222x
211 ))] 216 ))]
212 fn calculate_clock_source(&self) -> u32 { 217 pub(crate) fn calculate_clock_source(&self) -> u32 {
213 // Assume that BusClk has default value. 218 // Assume that BusClk has default value.
214 // TODO: calculate BusClk more precisely. 219 // TODO: calculate BusClk more precisely.
215 match self.clock_source { 220 match self.clock_source {
diff --git a/embassy-mspm0/src/i2c_target.rs b/embassy-mspm0/src/i2c_target.rs
new file mode 100644
index 000000000..86be91415
--- /dev/null
+++ b/embassy-mspm0/src/i2c_target.rs
@@ -0,0 +1,509 @@
1//! Inter-Integrated-Circuit (I2C) Target
2// The following code is modified from embassy-stm32 and embassy-rp
3// https://github.com/embassy-rs/embassy/tree/main/embassy-stm32
4// https://github.com/embassy-rs/embassy/tree/main/embassy-rp
5
6use core::future::poll_fn;
7use core::marker::PhantomData;
8use core::sync::atomic::Ordering;
9use core::task::Poll;
10
11use embassy_embedded_hal::SetConfig;
12use mspm0_metapac::i2c::vals::CpuIntIidxStat;
13
14use crate::gpio::{AnyPin, SealedPin};
15use crate::interrupt::InterruptExt;
16use crate::mode::{Async, Blocking, Mode};
17use crate::pac::{self, i2c::vals};
18use crate::{i2c, i2c_target, interrupt, Peri};
19// Re-use I2c controller types
20use crate::i2c::{ClockSel, ConfigError, Info, Instance, InterruptHandler, SclPin, SdaPin, State};
21
22#[non_exhaustive]
23#[derive(Clone, Copy, PartialEq, Eq, Debug)]
24/// Config
25pub struct Config {
26 /// 7-bit Target Address
27 pub target_addr: u8,
28
29 /// Control if the target should ack to and report general calls.
30 pub general_call: bool,
31}
32
33impl Default for Config {
34 fn default() -> Self {
35 Self {
36 target_addr: 0x48,
37 general_call: false,
38 }
39 }
40}
41
42/// I2C error
43#[derive(Debug, PartialEq, Eq, Clone, Copy)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45#[non_exhaustive]
46pub enum Error {
47 /// User passed in a response buffer that was 0 length
48 InvalidResponseBufferLength,
49 /// The response buffer length was too short to contain the message
50 ///
51 /// The length parameter will always be the length of the buffer, and is
52 /// provided as a convenience for matching alongside `Command::Write`.
53 PartialWrite(usize),
54 /// The response buffer length was too short to contain the message
55 ///
56 /// The length parameter will always be the length of the buffer, and is
57 /// provided as a convenience for matching alongside `Command::GeneralCall`.
58 PartialGeneralCall(usize),
59}
60
61/// Received command from the controller.
62#[derive(Debug, Copy, Clone, Eq, PartialEq)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64pub enum Command {
65 /// General Call Write: Controller sent the General Call address (0x00) followed by data.
66 /// Contains the number of bytes written by the controller.
67 GeneralCall(usize),
68 /// Read: Controller wants to read data from the target.
69 Read,
70 /// Write: Controller sent the target's address followed by data.
71 /// Contains the number of bytes written by the controller.
72 Write(usize),
73 /// Write followed by Read (Repeated Start): Controller wrote data, then issued a repeated
74 /// start and wants to read data. Contains the number of bytes written before the read.
75 WriteRead(usize),
76}
77
78/// Status after responding to a controller read request.
79#[derive(Debug, Copy, Clone, Eq, PartialEq)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub enum ReadStatus {
82 /// Transaction completed successfully. The controller either NACKed the last byte
83 /// or sent a STOP condition.
84 Done,
85 /// Transaction incomplete, controller trying to read more bytes than were provided
86 NeedMoreBytes,
87 /// Transaction complete, but controller stopped reading bytes before we ran out
88 LeftoverBytes(u16),
89}
90
91/// I2C Target driver.
92// Use the same Instance, SclPin, SdaPin traits as the controller
93pub struct I2cTarget<'d, M: Mode> {
94 info: &'static Info,
95 state: &'static State,
96 scl: Option<Peri<'d, AnyPin>>,
97 sda: Option<Peri<'d, AnyPin>>,
98 config: i2c::Config,
99 target_config: i2c_target::Config,
100 _phantom: PhantomData<M>,
101}
102
103impl<'d> SetConfig for I2cTarget<'d, Async> {
104 type Config = (i2c::Config, i2c_target::Config);
105 type ConfigError = ConfigError;
106
107 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
108 self.info.interrupt.disable();
109
110 if let Some(ref sda) = self.sda {
111 sda.update_pf(config.0.sda_pf());
112 }
113
114 if let Some(ref scl) = self.scl {
115 scl.update_pf(config.0.scl_pf());
116 }
117
118 self.config = config.0.clone();
119 self.target_config = config.1.clone();
120
121 self.reset()
122 }
123}
124
125impl<'d> SetConfig for I2cTarget<'d, Blocking> {
126 type Config = (i2c::Config, i2c_target::Config);
127 type ConfigError = ConfigError;
128
129 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
130 if let Some(ref sda) = self.sda {
131 sda.update_pf(config.0.sda_pf());
132 }
133
134 if let Some(ref scl) = self.scl {
135 scl.update_pf(config.0.scl_pf());
136 }
137
138 self.config = config.0.clone();
139 self.target_config = config.1.clone();
140
141 self.reset()
142 }
143}
144
145impl<'d> I2cTarget<'d, Async> {
146 /// Create a new asynchronous I2C target driver using interrupts
147 /// The `config` reuses the i2c controller config to setup the clock while `target_config`
148 /// configures i2c target specific parameters.
149 pub fn new<T: Instance>(
150 peri: Peri<'d, T>,
151 scl: Peri<'d, impl SclPin<T>>,
152 sda: Peri<'d, impl SdaPin<T>>,
153 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
154 config: i2c::Config,
155 target_config: i2c_target::Config,
156 ) -> Result<Self, ConfigError> {
157 let mut this = Self::new_inner(
158 peri,
159 new_pin!(scl, config.scl_pf()),
160 new_pin!(sda, config.sda_pf()),
161 config,
162 target_config,
163 );
164 this.reset()?;
165 Ok(this)
166 }
167
168 /// Reset the i2c peripheral. If you cancel a respond_to_read, you may stall the bus.
169 /// You can recover the bus by calling this function, but doing so will almost certainly cause
170 /// an i/o error in the controller.
171 pub fn reset(&mut self) -> Result<(), ConfigError> {
172 self.init()?;
173 unsafe { self.info.interrupt.enable() };
174 Ok(())
175 }
176}
177
178impl<'d> I2cTarget<'d, Blocking> {
179 /// Create a new blocking I2C target driver.
180 /// The `config` reuses the i2c controller config to setup the clock while `target_config`
181 /// configures i2c target specific parameters.
182 pub fn new_blocking<T: Instance>(
183 peri: Peri<'d, T>,
184 scl: Peri<'d, impl SclPin<T>>,
185 sda: Peri<'d, impl SdaPin<T>>,
186 config: i2c::Config,
187 target_config: i2c_target::Config,
188 ) -> Result<Self, ConfigError> {
189 let mut this = Self::new_inner(
190 peri,
191 new_pin!(scl, config.scl_pf()),
192 new_pin!(sda, config.sda_pf()),
193 config,
194 target_config,
195 );
196 this.reset()?;
197 Ok(this)
198 }
199
200 /// Reset the i2c peripheral. If you cancel a respond_to_read, you may stall the bus.
201 /// You can recover the bus by calling this function, but doing so will almost certainly cause
202 /// an i/o error in the controller.
203 pub fn reset(&mut self) -> Result<(), ConfigError> {
204 self.init()?;
205 Ok(())
206 }
207}
208
209impl<'d, M: Mode> I2cTarget<'d, M> {
210 fn new_inner<T: Instance>(
211 _peri: Peri<'d, T>,
212 scl: Option<Peri<'d, AnyPin>>,
213 sda: Option<Peri<'d, AnyPin>>,
214 config: i2c::Config,
215 target_config: i2c_target::Config,
216 ) -> Self {
217 if let Some(ref scl) = scl {
218 let pincm = pac::IOMUX.pincm(scl._pin_cm() as usize);
219 pincm.modify(|w| {
220 w.set_hiz1(true);
221 });
222 }
223 if let Some(ref sda) = sda {
224 let pincm = pac::IOMUX.pincm(sda._pin_cm() as usize);
225 pincm.modify(|w| {
226 w.set_hiz1(true);
227 });
228 }
229
230 Self {
231 info: T::info(),
232 state: T::state(),
233 scl,
234 sda,
235 config,
236 target_config,
237 _phantom: PhantomData,
238 }
239 }
240
241 fn init(&mut self) -> Result<(), ConfigError> {
242 let mut config = self.config;
243 let target_config = self.target_config;
244 let regs = self.info.regs;
245
246 config.check_config()?;
247 // Target address must be 7-bit
248 if !(target_config.target_addr < 0x80) {
249 return Err(ConfigError::InvalidTargetAddress);
250 }
251
252 regs.target(0).tctr().modify(|w| {
253 w.set_active(false);
254 });
255
256 // Init power for I2C
257 regs.gprcm(0).rstctl().write(|w| {
258 w.set_resetstkyclr(true);
259 w.set_resetassert(true);
260 w.set_key(vals::ResetKey::KEY);
261 });
262
263 regs.gprcm(0).pwren().write(|w| {
264 w.set_enable(true);
265 w.set_key(vals::PwrenKey::KEY);
266 });
267
268 self.info.interrupt.disable();
269
270 // Init delay from the M0 examples by TI in CCStudio (16 cycles)
271 cortex_m::asm::delay(16);
272
273 // Select and configure the I2C clock using the CLKSEL and CLKDIV registers
274 regs.clksel().write(|w| match config.clock_source {
275 ClockSel::BusClk => {
276 w.set_mfclk_sel(false);
277 w.set_busclk_sel(true);
278 }
279 ClockSel::MfClk => {
280 w.set_mfclk_sel(true);
281 w.set_busclk_sel(false);
282 }
283 });
284 regs.clkdiv().write(|w| w.set_ratio(config.clock_div.into()));
285
286 // Configure at least one target address by writing the 7-bit address to I2Cx.SOAR register. The additional
287 // target address can be enabled and configured by using I2Cx.TOAR2 register.
288 regs.target(0).toar().modify(|w| {
289 w.set_oaren(true);
290 w.set_oar(target_config.target_addr as u16);
291 });
292
293 self.state
294 .clock
295 .store(config.calculate_clock_source(), Ordering::Relaxed);
296
297 regs.target(0).tctr().modify(|w| {
298 w.set_gencall(target_config.general_call);
299 w.set_tclkstretch(true);
300 // Disable target wakeup, follow TI example. (TI note: Workaround for errata I2C_ERR_04.)
301 w.set_twuen(false);
302 w.set_txempty_on_treq(true);
303 });
304
305 // Enable the I2C target mode by setting the ACTIVE bit in I2Cx.TCTR register.
306 regs.target(0).tctr().modify(|w| {
307 w.set_active(true);
308 });
309
310 Ok(())
311 }
312
313 #[inline(always)]
314 fn drain_fifo(&mut self, buffer: &mut [u8], offset: &mut usize) {
315 let regs = self.info.regs;
316
317 for b in &mut buffer[*offset..] {
318 if regs.target(0).tfifosr().read().rxfifocnt() == 0 {
319 break;
320 }
321
322 *b = regs.target(0).trxdata().read().value();
323 *offset += 1;
324 }
325 }
326
327 /// Blocking function to empty the tx fifo
328 ///
329 /// This function can be used to empty the transmit FIFO if data remains after handling a 'read' command (LeftoverBytes).
330 pub fn flush_tx_fifo(&mut self) {
331 self.info.regs.target(0).tfifoctl().modify(|w| {
332 w.set_txflush(true);
333 });
334 while self.info.regs.target(0).tfifosr().read().txfifocnt() as usize != self.info.fifo_size {}
335 self.info.regs.target(0).tfifoctl().modify(|w| {
336 w.set_txflush(false);
337 });
338 }
339}
340
341impl<'d> I2cTarget<'d, Async> {
342 /// Wait asynchronously for commands from an I2C controller.
343 /// `buffer` is provided in case controller does a 'write', 'write read', or 'general call' and is unused for 'read'.
344 pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
345 let regs = self.info.regs;
346
347 let mut len = 0;
348
349 // Set the rx fifo interrupt to avoid a fifo overflow
350 regs.target(0).tfifoctl().modify(|r| {
351 r.set_rxtrig(vals::TfifoctlRxtrig::LEVEL_6);
352 });
353
354 self.wait_on(
355 |me| {
356 // Check if address matches the General Call address (0x00)
357 let is_gencall = regs.target(0).tsr().read().addrmatch() == 0;
358
359 if regs.target(0).tfifosr().read().rxfifocnt() > 0 {
360 me.drain_fifo(buffer, &mut len);
361 }
362
363 if buffer.len() == len && regs.target(0).tfifosr().read().rxfifocnt() > 0 {
364 if is_gencall {
365 return Poll::Ready(Err(Error::PartialGeneralCall(buffer.len())));
366 } else {
367 return Poll::Ready(Err(Error::PartialWrite(buffer.len())));
368 }
369 }
370
371 let iidx = regs.cpu_int(0).iidx().read().stat();
372 trace!("ls:{} len:{}", iidx as u8, len);
373 let result = match iidx {
374 CpuIntIidxStat::TTXEMPTY => match len {
375 0 => Poll::Ready(Ok(Command::Read)),
376 w => Poll::Ready(Ok(Command::WriteRead(w))),
377 },
378 CpuIntIidxStat::TSTOPFG => match (is_gencall, len) {
379 (_, 0) => Poll::Pending,
380 (true, w) => Poll::Ready(Ok(Command::GeneralCall(w))),
381 (false, w) => Poll::Ready(Ok(Command::Write(w))),
382 },
383 _ => Poll::Pending,
384 };
385 if !result.is_pending() {
386 regs.cpu_int(0).imask().write(|_| {});
387 }
388 result
389 },
390 |_me| {
391 regs.cpu_int(0).imask().write(|_| {});
392 regs.cpu_int(0).imask().modify(|w| {
393 w.set_tgencall(true);
394 w.set_trxfifotrg(true);
395 w.set_tstop(true);
396 w.set_ttxempty(true);
397 });
398 },
399 )
400 .await
401 }
402
403 /// Respond to an I2C controller 'read' command, asynchronously.
404 pub async fn respond_to_read(&mut self, buffer: &[u8]) -> Result<ReadStatus, Error> {
405 if buffer.is_empty() {
406 return Err(Error::InvalidResponseBufferLength);
407 }
408
409 let regs = self.info.regs;
410 let fifo_size = self.info.fifo_size;
411 let mut chunks = buffer.chunks(self.info.fifo_size);
412
413 self.wait_on(
414 |_me| {
415 if let Some(chunk) = chunks.next() {
416 for byte in chunk {
417 regs.target(0).ttxdata().write(|w| w.set_value(*byte));
418 }
419
420 return Poll::Pending;
421 }
422
423 let iidx = regs.cpu_int(0).iidx().read().stat();
424 let fifo_bytes = fifo_size - regs.target(0).tfifosr().read().txfifocnt() as usize;
425 trace!("rs:{}, fifo:{}", iidx as u8, fifo_bytes);
426
427 let result = match iidx {
428 CpuIntIidxStat::TTXEMPTY => Poll::Ready(Ok(ReadStatus::NeedMoreBytes)),
429 CpuIntIidxStat::TSTOPFG => match fifo_bytes {
430 0 => Poll::Ready(Ok(ReadStatus::Done)),
431 w => Poll::Ready(Ok(ReadStatus::LeftoverBytes(w as u16))),
432 },
433 _ => Poll::Pending,
434 };
435 if !result.is_pending() {
436 regs.cpu_int(0).imask().write(|_| {});
437 }
438 result
439 },
440 |_me| {
441 regs.cpu_int(0).imask().write(|_| {});
442 regs.cpu_int(0).imask().modify(|w| {
443 w.set_ttxempty(true);
444 w.set_tstop(true);
445 });
446 },
447 )
448 .await
449 }
450
451 /// Respond to reads with the fill byte until the controller stops asking
452 pub async fn respond_till_stop(&mut self, fill: u8) -> Result<(), Error> {
453 // The buffer size could be increased to reduce interrupt noise but has higher probability
454 // of LeftoverBytes
455 let buff = [fill];
456 loop {
457 match self.respond_to_read(&buff).await {
458 Ok(ReadStatus::NeedMoreBytes) => (),
459 Ok(_) => break Ok(()),
460 Err(e) => break Err(e),
461 }
462 }
463 }
464
465 /// Respond to a controller read, then fill any remaining read bytes with `fill`
466 pub async fn respond_and_fill(&mut self, buffer: &[u8], fill: u8) -> Result<ReadStatus, Error> {
467 let resp_stat = self.respond_to_read(buffer).await?;
468
469 if resp_stat == ReadStatus::NeedMoreBytes {
470 self.respond_till_stop(fill).await?;
471 Ok(ReadStatus::Done)
472 } else {
473 Ok(resp_stat)
474 }
475 }
476
477 /// Calls `f` to check if we are ready or not.
478 /// If not, `g` is called once(to eg enable the required interrupts).
479 /// The waker will always be registered prior to calling `f`.
480 #[inline(always)]
481 async fn wait_on<F, U, G>(&mut self, mut f: F, mut g: G) -> U
482 where
483 F: FnMut(&mut Self) -> Poll<U>,
484 G: FnMut(&mut Self),
485 {
486 poll_fn(|cx| {
487 // Register prior to checking the condition
488 self.state.waker.register(cx.waker());
489 let r = f(self);
490
491 if r.is_pending() {
492 g(self);
493 }
494
495 r
496 })
497 .await
498 }
499}
500
501impl<'d, M: Mode> Drop for I2cTarget<'d, M> {
502 fn drop(&mut self) {
503 // Ensure peripheral is disabled and pins are reset
504 self.info.regs.target(0).tctr().modify(|w| w.set_active(false));
505
506 self.scl.as_ref().map(|x| x.set_as_disconnected());
507 self.sda.as_ref().map(|x| x.set_as_disconnected());
508 }
509}
diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs
index 55f3f9381..9f3e4d5e8 100644
--- a/embassy-mspm0/src/lib.rs
+++ b/embassy-mspm0/src/lib.rs
@@ -18,6 +18,7 @@ pub mod adc;
18pub mod dma; 18pub mod dma;
19pub mod gpio; 19pub mod gpio;
20pub mod i2c; 20pub mod i2c;
21pub mod i2c_target;
21pub mod timer; 22pub mod timer;
22pub mod uart; 23pub mod uart;
23pub mod wwdt; 24pub mod wwdt;
@@ -233,3 +234,114 @@ impl Iterator for BitIter {
233 } 234 }
234 } 235 }
235} 236}
237
238/// Reset cause values from SYSCTL.RSTCAUSE register.
239/// Based on MSPM0 L-series Technical Reference Manual Table 2-9 and
240/// MSPM0 G-series Technical Reference Manual Table 2-12.
241#[derive(Clone, Copy, PartialEq, Eq, Debug)]
242#[cfg_attr(feature = "defmt", derive(defmt::Format))]
243pub enum ResetCause {
244 /// No reset since last read
245 NoReset,
246 /// VDD < POR- violation, PMU trim parity fault, or SHUTDNSTOREx parity fault
247 PorHwFailure,
248 /// NRST pin reset (>1s)
249 PorExternalNrst,
250 /// Software-triggered POR
251 PorSwTriggered,
252 /// VDD < BOR- violation
253 BorSupplyFailure,
254 /// Wake from SHUTDOWN
255 BorWakeFromShutdown,
256 /// Non-PMU trim parity fault
257 #[cfg(not(any(
258 mspm0c110x,
259 mspm0c1105_c1106,
260 mspm0g110x,
261 mspm0g150x,
262 mspm0g151x,
263 mspm0g310x,
264 mspm0g350x,
265 mspm0g351x
266 )))]
267 BootrstNonPmuParityFault,
268 /// Fatal clock fault
269 BootrstClockFault,
270 /// Software-triggered BOOTRST
271 BootrstSwTriggered,
272 /// NRST pin reset (<1s)
273 BootrstExternalNrst,
274 /// WWDT0 violation
275 BootrstWwdt0Violation,
276 /// WWDT1 violation (G-series only)
277 #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))]
278 SysrstWwdt1Violation,
279 /// BSL exit (if present)
280 SysrstBslExit,
281 /// BSL entry (if present)
282 SysrstBslEntry,
283 /// Uncorrectable flash ECC error (if present)
284 #[cfg(not(any(mspm0c110x, mspm0c1105_c1106, mspm0g351x, mspm0g151x)))]
285 SysrstFlashEccError,
286 /// CPU lockup violation
287 SysrstCpuLockupViolation,
288 /// Debug-triggered SYSRST
289 SysrstDebugTriggered,
290 /// Software-triggered SYSRST
291 SysrstSwTriggered,
292 /// Debug-triggered CPURST
293 CpurstDebugTriggered,
294 /// Software-triggered CPURST
295 CpurstSwTriggered,
296}
297
298/// Read the reset cause from the SYSCTL.RSTCAUSE register.
299///
300/// This function reads the reset cause register which indicates why the last
301/// system reset occurred. The register is automatically cleared after being read,
302/// so this should be called only once per application startup.
303///
304/// If the reset cause is not recognized, an `Err` containing the raw value is returned.
305#[must_use = "Reading reset cause will clear it"]
306pub fn read_reset_cause() -> Result<ResetCause, u8> {
307 let cause_raw = pac::SYSCTL.rstcause().read().id();
308
309 use ResetCause::*;
310 use pac::sysctl::vals::Id;
311
312 match cause_raw {
313 Id::NORST => Ok(NoReset),
314 Id::PORHWFAIL => Ok(PorHwFailure),
315 Id::POREXNRST => Ok(PorExternalNrst),
316 Id::PORSW => Ok(PorSwTriggered),
317 Id::BORSUPPLY => Ok(BorSupplyFailure),
318 Id::BORWAKESHUTDN => Ok(BorWakeFromShutdown),
319 #[cfg(not(any(
320 mspm0c110x,
321 mspm0c1105_c1106,
322 mspm0g110x,
323 mspm0g150x,
324 mspm0g151x,
325 mspm0g310x,
326 mspm0g350x,
327 mspm0g351x
328 )))]
329 Id::BOOTNONPMUPARITY => Ok(BootrstNonPmuParityFault),
330 Id::BOOTCLKFAIL => Ok(BootrstClockFault),
331 Id::BOOTSW => Ok(BootrstSwTriggered),
332 Id::BOOTEXNRST => Ok(BootrstExternalNrst),
333 Id::BOOTWWDT0 => Ok(BootrstWwdt0Violation),
334 Id::SYSBSLEXIT => Ok(SysrstBslExit),
335 Id::SYSBSLENTRY => Ok(SysrstBslEntry),
336 #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))]
337 Id::SYSWWDT1 => Ok(SysrstWwdt1Violation),
338 #[cfg(not(any(mspm0c110x, mspm0c1105_c1106, mspm0g351x, mspm0g151x)))]
339 Id::SYSFLASHECC => Ok(SysrstFlashEccError),
340 Id::SYSCPULOCK => Ok(SysrstCpuLockupViolation),
341 Id::SYSDBG => Ok(SysrstDebugTriggered),
342 Id::SYSSW => Ok(SysrstSwTriggered),
343 Id::CPUDBG => Ok(CpurstDebugTriggered),
344 Id::CPUSW => Ok(CpurstSwTriggered),
345 other => Err(other as u8),
346 }
347}
diff --git a/embassy-net-esp-hosted/CHANGELOG.md b/embassy-net-esp-hosted/CHANGELOG.md
index 5153e3799..d8b912295 100644
--- a/embassy-net-esp-hosted/CHANGELOG.md
+++ b/embassy-net-esp-hosted/CHANGELOG.md
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Add an `Interface` trait to allow using other interface transports.
12- Switch to `micropb` for protobuf.
13- Update protos to latest `esp-hosted-fg`.
14
11## 0.2.1 - 2025-08-26 15## 0.2.1 - 2025-08-26
12 16
13- First release with changelog. 17- First release with changelog.
diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml
index f148f4762..81096b024 100644
--- a/embassy-net-esp-hosted/Cargo.toml
+++ b/embassy-net-esp-hosted/Cargo.toml
@@ -25,7 +25,7 @@ embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-
25embedded-hal = { version = "1.0" } 25embedded-hal = { version = "1.0" }
26embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
27 27
28noproto = "0.1.0" 28micropb = { version = "0.4.0", default-features = false, features = ["container-heapless", "encode", "decode"] }
29heapless = "0.8" 29heapless = "0.8"
30 30
31[package.metadata.embassy_docs] 31[package.metadata.embassy_docs]
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index cbc194877..38ec648b4 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -1,6 +1,7 @@
1use embassy_net_driver_channel as ch; 1use embassy_net_driver_channel as ch;
2use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; 2use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
3use heapless::String; 3use heapless::String;
4use micropb::{MessageDecode, MessageEncode, PbEncoder};
4 5
5use crate::ioctl::Shared; 6use crate::ioctl::Shared;
6use crate::proto::{self, CtrlMsg}; 7use crate::proto::{self, CtrlMsg};
@@ -38,7 +39,7 @@ enum WifiMode {
38 ApSta = 3, 39 ApSta = 3,
39} 40}
40 41
41pub use proto::CtrlWifiSecProt as Security; 42pub use proto::Ctrl_WifiSecProt as Security;
42 43
43/// WiFi status. 44/// WiFi status.
44#[derive(Clone, Debug)] 45#[derive(Clone, Debug)]
@@ -59,18 +60,20 @@ pub struct Status {
59macro_rules! ioctl { 60macro_rules! ioctl {
60 ($self:ident, $req_variant:ident, $resp_variant:ident, $req:ident, $resp:ident) => { 61 ($self:ident, $req_variant:ident, $resp_variant:ident, $req:ident, $resp:ident) => {
61 let mut msg = proto::CtrlMsg { 62 let mut msg = proto::CtrlMsg {
62 msg_id: proto::CtrlMsgId::$req_variant as _, 63 msg_id: proto::CtrlMsgId::$req_variant,
63 msg_type: proto::CtrlMsgType::Req as _, 64 msg_type: proto::CtrlMsgType::Req,
64 payload: Some(proto::CtrlMsgPayload::$req_variant($req)), 65 payload: Some(proto::CtrlMsg_::Payload::$req_variant($req)),
66 req_resp_type: 0,
67 uid: 0,
65 }; 68 };
66 $self.ioctl(&mut msg).await?; 69 $self.ioctl(&mut msg).await?;
67 #[allow(unused_mut)] 70 #[allow(unused_mut)]
68 let Some(proto::CtrlMsgPayload::$resp_variant(mut $resp)) = msg.payload else { 71 let Some(proto::CtrlMsg_::Payload::$resp_variant(mut $resp)) = msg.payload else {
69 warn!("unexpected response variant"); 72 warn!("unexpected response variant");
70 return Err(Error::Internal); 73 return Err(Error::Internal);
71 }; 74 };
72 if $resp.resp != 0 { 75 if $resp.resp != 0 {
73 return Err(Error::Failed($resp.resp)); 76 return Err(Error::Failed($resp.resp as u32));
74 } 77 }
75 }; 78 };
76} 79}
@@ -100,35 +103,44 @@ impl<'a> Control<'a> {
100 103
101 /// Get the current status. 104 /// Get the current status.
102 pub async fn get_status(&mut self) -> Result<Status, Error> { 105 pub async fn get_status(&mut self) -> Result<Status, Error> {
103 let req = proto::CtrlMsgReqGetApConfig {}; 106 let req = proto::CtrlMsg_Req_GetAPConfig {};
104 ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp); 107 ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp);
105 trim_nulls(&mut resp.ssid); 108 let ssid = core::str::from_utf8(&resp.ssid).map_err(|_| Error::Internal)?;
109 let ssid = String::try_from(ssid.trim_end_matches('\0')).map_err(|_| Error::Internal)?;
110 let bssid_str = core::str::from_utf8(&resp.bssid).map_err(|_| Error::Internal)?;
106 Ok(Status { 111 Ok(Status {
107 ssid: resp.ssid, 112 ssid,
108 bssid: parse_mac(&resp.bssid)?, 113 bssid: parse_mac(bssid_str)?,
109 rssi: resp.rssi as _, 114 rssi: resp.rssi as _,
110 channel: resp.chnl, 115 channel: resp.chnl as u32,
111 security: resp.sec_prot, 116 security: resp.sec_prot,
112 }) 117 })
113 } 118 }
114 119
115 /// Connect to the network identified by ssid using the provided password. 120 /// Connect to the network identified by ssid using the provided password.
116 pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> { 121 pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
117 let req = proto::CtrlMsgReqConnectAp { 122 const WIFI_BAND_MODE_AUTO: i32 = 3; // 2.4GHz + 5GHz
123
124 let req = proto::CtrlMsg_Req_ConnectAP {
118 ssid: unwrap!(String::try_from(ssid)), 125 ssid: unwrap!(String::try_from(ssid)),
119 pwd: unwrap!(String::try_from(password)), 126 pwd: unwrap!(String::try_from(password)),
120 bssid: String::new(), 127 bssid: String::new(),
121 listen_interval: 3, 128 listen_interval: 3,
122 is_wpa3_supported: true, 129 is_wpa3_supported: true,
130 band_mode: WIFI_BAND_MODE_AUTO,
123 }; 131 };
124 ioctl!(self, ReqConnectAp, RespConnectAp, req, resp); 132 ioctl!(self, ReqConnectAp, RespConnectAp, req, resp);
133
134 // TODO: in newer esp-hosted firmwares that added EventStationConnectedToAp
135 // the connect ioctl seems to be async, so we shouldn't immediately set LinkState::Up here.
125 self.state_ch.set_link_state(LinkState::Up); 136 self.state_ch.set_link_state(LinkState::Up);
137
126 Ok(()) 138 Ok(())
127 } 139 }
128 140
129 /// Disconnect from any currently connected network. 141 /// Disconnect from any currently connected network.
130 pub async fn disconnect(&mut self) -> Result<(), Error> { 142 pub async fn disconnect(&mut self) -> Result<(), Error> {
131 let req = proto::CtrlMsgReqGetStatus {}; 143 let req = proto::CtrlMsg_Req_GetStatus {};
132 ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp); 144 ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp);
133 self.state_ch.set_link_state(LinkState::Down); 145 self.state_ch.set_link_state(LinkState::Down);
134 Ok(()) 146 Ok(())
@@ -136,21 +148,25 @@ impl<'a> Control<'a> {
136 148
137 /// duration in seconds, clamped to [10, 3600] 149 /// duration in seconds, clamped to [10, 3600]
138 async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> { 150 async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> {
139 let req = proto::CtrlMsgReqConfigHeartbeat { enable: true, duration }; 151 let req = proto::CtrlMsg_Req_ConfigHeartbeat {
152 enable: true,
153 duration: duration as i32,
154 };
140 ioctl!(self, ReqConfigHeartbeat, RespConfigHeartbeat, req, resp); 155 ioctl!(self, ReqConfigHeartbeat, RespConfigHeartbeat, req, resp);
141 Ok(()) 156 Ok(())
142 } 157 }
143 158
144 async fn get_mac_addr(&mut self) -> Result<[u8; 6], Error> { 159 async fn get_mac_addr(&mut self) -> Result<[u8; 6], Error> {
145 let req = proto::CtrlMsgReqGetMacAddress { 160 let req = proto::CtrlMsg_Req_GetMacAddress {
146 mode: WifiMode::Sta as _, 161 mode: WifiMode::Sta as _,
147 }; 162 };
148 ioctl!(self, ReqGetMacAddress, RespGetMacAddress, req, resp); 163 ioctl!(self, ReqGetMacAddress, RespGetMacAddress, req, resp);
149 parse_mac(&resp.mac) 164 let mac_str = core::str::from_utf8(&resp.mac).map_err(|_| Error::Internal)?;
165 parse_mac(mac_str)
150 } 166 }
151 167
152 async fn set_wifi_mode(&mut self, mode: u32) -> Result<(), Error> { 168 async fn set_wifi_mode(&mut self, mode: u32) -> Result<(), Error> {
153 let req = proto::CtrlMsgReqSetMode { mode }; 169 let req = proto::CtrlMsg_Req_SetMode { mode: mode as i32 };
154 ioctl!(self, ReqSetWifiMode, RespSetWifiMode, req, resp); 170 ioctl!(self, ReqSetWifiMode, RespSetWifiMode, req, resp);
155 171
156 Ok(()) 172 Ok(())
@@ -160,11 +176,15 @@ impl<'a> Control<'a> {
160 debug!("ioctl req: {:?}", &msg); 176 debug!("ioctl req: {:?}", &msg);
161 177
162 let mut buf = [0u8; 128]; 178 let mut buf = [0u8; 128];
179 let buf_len = buf.len();
163 180
164 let req_len = noproto::write(msg, &mut buf).map_err(|_| { 181 let mut encoder = PbEncoder::new(&mut buf[..]);
182 msg.encode(&mut encoder).map_err(|_| {
165 warn!("failed to serialize control request"); 183 warn!("failed to serialize control request");
166 Error::Internal 184 Error::Internal
167 })?; 185 })?;
186 let remaining = encoder.into_writer();
187 let req_len = buf_len - remaining.len();
168 188
169 struct CancelOnDrop<'a>(&'a Shared); 189 struct CancelOnDrop<'a>(&'a Shared);
170 190
@@ -186,8 +206,8 @@ impl<'a> Control<'a> {
186 206
187 ioctl.defuse(); 207 ioctl.defuse();
188 208
189 *msg = noproto::read(&buf[..resp_len]).map_err(|_| { 209 msg.decode_from_bytes(&buf[..resp_len]).map_err(|_| {
190 warn!("failed to serialize control request"); 210 warn!("failed to deserialize control response");
191 Error::Internal 211 Error::Internal
192 })?; 212 })?;
193 debug!("ioctl resp: {:?}", msg); 213 debug!("ioctl resp: {:?}", msg);
@@ -221,9 +241,3 @@ fn parse_mac(mac: &str) -> Result<[u8; 6], Error> {
221 } 241 }
222 Ok(res) 242 Ok(res)
223} 243}
224
225fn trim_nulls<const N: usize>(s: &mut String<N>) {
226 while s.chars().rev().next() == Some(0 as char) {
227 s.pop();
228 }
229}
diff --git a/embassy-net-esp-hosted/src/esp_hosted_config.proto b/embassy-net-esp-hosted/src/esp_hosted_config.proto
index aa1bfde64..7d626207e 100644
--- a/embassy-net-esp-hosted/src/esp_hosted_config.proto
+++ b/embassy-net-esp-hosted/src/esp_hosted_config.proto
@@ -1,3 +1,6 @@
1/* Copyright (C) 2015-2025 Espressif Systems (Shanghai) PTE LTD */
2/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */
3
1syntax = "proto3"; 4syntax = "proto3";
2 5
3/* Enums similar to ESP IDF */ 6/* Enums similar to ESP IDF */
@@ -28,9 +31,10 @@ enum Ctrl_WifiBw {
28} 31}
29 32
30enum Ctrl_WifiPowerSave { 33enum Ctrl_WifiPowerSave {
31 PS_Invalid = 0; 34 NO_PS = 0;
32 MIN_MODEM = 1; 35 MIN_MODEM = 1;
33 MAX_MODEM = 2; 36 MAX_MODEM = 2;
37 PS_Invalid = 3;
34} 38}
35 39
36enum Ctrl_WifiSecProt { 40enum Ctrl_WifiSecProt {
@@ -96,9 +100,16 @@ enum CtrlMsgId {
96 Req_GetWifiCurrTxPower = 120; 100 Req_GetWifiCurrTxPower = 120;
97 101
98 Req_ConfigHeartbeat = 121; 102 Req_ConfigHeartbeat = 121;
103 Req_EnableDisable = 122;
104 Req_GetFwVersion = 123;
105 Req_SetCountryCode = 124;
106 Req_GetCountryCode = 125;
107 Req_SetDhcpDnsStatus = 126;
108 Req_GetDhcpDnsStatus = 127;
109 Req_Custom_RPC_Unserialised_Msg = 128;
99 /* Add new control path command response before Req_Max 110 /* Add new control path command response before Req_Max
100 * and update Req_Max */ 111 * and update Req_Max */
101 Req_Max = 122; 112 Req_Max = 129;
102 113
103 /** Response Msgs **/ 114 /** Response Msgs **/
104 Resp_Base = 200; 115 Resp_Base = 200;
@@ -130,9 +141,16 @@ enum CtrlMsgId {
130 Resp_GetWifiCurrTxPower = 220; 141 Resp_GetWifiCurrTxPower = 220;
131 142
132 Resp_ConfigHeartbeat = 221; 143 Resp_ConfigHeartbeat = 221;
144 Resp_EnableDisable = 222;
145 Resp_GetFwVersion = 223;
146 Resp_SetCountryCode = 224;
147 Resp_GetCountryCode = 225;
148 Resp_SetDhcpDnsStatus = 226;
149 Resp_GetDhcpDnsStatus = 227;
150 Resp_Custom_RPC_Unserialised_Msg = 228;
133 /* Add new control path command response before Resp_Max 151 /* Add new control path command response before Resp_Max
134 * and update Resp_Max */ 152 * and update Resp_Max */
135 Resp_Max = 222; 153 Resp_Max = 229;
136 154
137 /** Event Msgs **/ 155 /** Event Msgs **/
138 Event_Base = 300; 156 Event_Base = 300;
@@ -140,9 +158,22 @@ enum CtrlMsgId {
140 Event_Heartbeat = 302; 158 Event_Heartbeat = 302;
141 Event_StationDisconnectFromAP = 303; 159 Event_StationDisconnectFromAP = 303;
142 Event_StationDisconnectFromESPSoftAP = 304; 160 Event_StationDisconnectFromESPSoftAP = 304;
161 Event_StationConnectedToAP = 305;
162 Event_StationConnectedToESPSoftAP = 306;
163 Event_SetDhcpDnsStatus = 307;
164 Event_Custom_RPC_Unserialised_Msg = 308;
143 /* Add new control path command notification before Event_Max 165 /* Add new control path command notification before Event_Max
144 * and update Event_Max */ 166 * and update Event_Max */
145 Event_Max = 305; 167 Event_Max = 309;
168}
169
170enum HostedFeature {
171 Hosted_InvalidFeature = 0;
172 Hosted_Wifi = 1;
173 Hosted_Bluetooth = 2;
174 Hosted_Is_Network_Split_On = 3;
175
176 /* Add your new features here and re-build prot using build_proto.sh */
146} 177}
147 178
148/* internal supporting structures for CtrlMsg */ 179/* internal supporting structures for CtrlMsg */
@@ -213,6 +244,7 @@ message CtrlMsg_Resp_GetAPConfig {
213 int32 chnl = 4; 244 int32 chnl = 4;
214 Ctrl_WifiSecProt sec_prot = 5; 245 Ctrl_WifiSecProt sec_prot = 5;
215 int32 resp = 6; 246 int32 resp = 6;
247 int32 band_mode = 7;
216} 248}
217 249
218message CtrlMsg_Req_ConnectAP { 250message CtrlMsg_Req_ConnectAP {
@@ -221,11 +253,13 @@ message CtrlMsg_Req_ConnectAP {
221 string bssid = 3; 253 string bssid = 3;
222 bool is_wpa3_supported = 4; 254 bool is_wpa3_supported = 4;
223 int32 listen_interval = 5; 255 int32 listen_interval = 5;
256 int32 band_mode = 6;
224} 257}
225 258
226message CtrlMsg_Resp_ConnectAP { 259message CtrlMsg_Resp_ConnectAP {
227 int32 resp = 1; 260 int32 resp = 1;
228 bytes mac = 2; 261 bytes mac = 2;
262 int32 band_mode = 3;
229} 263}
230 264
231message CtrlMsg_Req_GetSoftAPConfig { 265message CtrlMsg_Req_GetSoftAPConfig {
@@ -240,6 +274,7 @@ message CtrlMsg_Resp_GetSoftAPConfig {
240 bool ssid_hidden = 6; 274 bool ssid_hidden = 6;
241 int32 bw = 7; 275 int32 bw = 7;
242 int32 resp = 8; 276 int32 resp = 8;
277 int32 band_mode = 9;
243} 278}
244 279
245message CtrlMsg_Req_StartSoftAP { 280message CtrlMsg_Req_StartSoftAP {
@@ -250,11 +285,13 @@ message CtrlMsg_Req_StartSoftAP {
250 int32 max_conn = 5; 285 int32 max_conn = 5;
251 bool ssid_hidden = 6; 286 bool ssid_hidden = 6;
252 int32 bw = 7; 287 int32 bw = 7;
288 int32 band_mode = 8;
253} 289}
254 290
255message CtrlMsg_Resp_StartSoftAP { 291message CtrlMsg_Resp_StartSoftAP {
256 int32 resp = 1; 292 int32 resp = 1;
257 bytes mac = 2; 293 bytes mac = 2;
294 int32 band_mode = 3;
258} 295}
259 296
260message CtrlMsg_Req_ScanResult { 297message CtrlMsg_Req_ScanResult {
@@ -302,7 +339,7 @@ message CtrlMsg_Req_VendorIEData {
302 int32 length = 2; 339 int32 length = 2;
303 bytes vendor_oui = 3; 340 bytes vendor_oui = 3;
304 int32 vendor_oui_type = 4; 341 int32 vendor_oui_type = 4;
305 bytes payload = 5; 342 bytes payload = 5;
306} 343}
307 344
308message CtrlMsg_Req_SetSoftAPVendorSpecificIE { 345message CtrlMsg_Req_SetSoftAPVendorSpecificIE {
@@ -341,6 +378,81 @@ message CtrlMsg_Resp_ConfigHeartbeat {
341 int32 resp = 1; 378 int32 resp = 1;
342} 379}
343 380
381message CtrlMsg_Req_EnableDisable {
382 uint32 feature = 1;
383 bool enable = 2;
384}
385
386message CtrlMsg_Resp_EnableDisable {
387 int32 resp = 1;
388}
389
390message CtrlMsg_Req_GetFwVersion {
391}
392
393message CtrlMsg_Resp_GetFwVersion {
394 int32 resp = 1;
395 string name = 2;
396 uint32 major1 = 3;
397 uint32 major2 = 4;
398 uint32 minor = 5;
399 uint32 rev_patch1 = 6;
400 uint32 rev_patch2 = 7;
401}
402
403message CtrlMsg_Req_SetCountryCode {
404 bytes country = 1;
405 bool ieee80211d_enabled = 2;
406}
407
408message CtrlMsg_Resp_SetCountryCode {
409 int32 resp = 1;
410}
411
412message CtrlMsg_Req_GetCountryCode {
413}
414
415message CtrlMsg_Resp_GetCountryCode {
416 int32 resp = 1;
417 bytes country = 2;
418}
419
420message CtrlMsg_Req_SetDhcpDnsStatus {
421 int32 iface = 1;
422 int32 net_link_up = 2;
423
424 int32 dhcp_up = 3;
425 bytes dhcp_ip = 4;
426 bytes dhcp_nm = 5;
427 bytes dhcp_gw = 6;
428
429 int32 dns_up = 7;
430 bytes dns_ip = 8;
431 int32 dns_type = 9;
432}
433
434message CtrlMsg_Resp_SetDhcpDnsStatus {
435 int32 resp = 1;
436}
437
438message CtrlMsg_Req_GetDhcpDnsStatus {
439}
440
441message CtrlMsg_Resp_GetDhcpDnsStatus {
442 int32 resp = 1;
443 int32 iface = 2;
444 int32 net_link_up = 3;
445
446 int32 dhcp_up = 4;
447 bytes dhcp_ip = 5;
448 bytes dhcp_nm = 6;
449 bytes dhcp_gw = 7;
450
451 int32 dns_up = 8;
452 bytes dns_ip = 9;
453 int32 dns_type = 10;
454}
455
344/** Event structure **/ 456/** Event structure **/
345message CtrlMsg_Event_ESPInit { 457message CtrlMsg_Event_ESPInit {
346 bytes init_data = 1; 458 bytes init_data = 1;
@@ -352,11 +464,70 @@ message CtrlMsg_Event_Heartbeat {
352 464
353message CtrlMsg_Event_StationDisconnectFromAP { 465message CtrlMsg_Event_StationDisconnectFromAP {
354 int32 resp = 1; 466 int32 resp = 1;
467 bytes ssid = 2;
468 uint32 ssid_len = 3;
469 bytes bssid = 4;
470 uint32 reason = 5;
471 int32 rssi = 6;
355} 472}
356 473
474message CtrlMsg_Event_StationConnectedToAP {
475 int32 resp = 1;
476 bytes ssid = 2;
477 uint32 ssid_len = 3;
478 bytes bssid = 4;
479 uint32 channel = 5;
480 int32 authmode = 6;
481 int32 aid = 7;
482}
483
484
357message CtrlMsg_Event_StationDisconnectFromESPSoftAP { 485message CtrlMsg_Event_StationDisconnectFromESPSoftAP {
358 int32 resp = 1; 486 int32 resp = 1;
359 bytes mac = 2; 487 bytes mac = 2;
488 uint32 aid = 3;
489 bool is_mesh_child = 4;
490 uint32 reason = 5;
491}
492
493message CtrlMsg_Event_StationConnectedToESPSoftAP {
494 int32 resp = 1;
495 bytes mac = 2;
496 uint32 aid = 3;
497 bool is_mesh_child = 4;
498}
499
500message CtrlMsg_Event_SetDhcpDnsStatus {
501 int32 iface = 1;
502 int32 net_link_up = 2;
503
504 int32 dhcp_up = 3;
505 bytes dhcp_ip = 4;
506 bytes dhcp_nm = 5;
507 bytes dhcp_gw = 6;
508
509 int32 dns_up = 7;
510 bytes dns_ip = 8;
511 int32 dns_type = 9;
512 int32 resp = 10;
513}
514
515/* Add Custom RPC message structures after existing message structures to make it easily notice */
516message CtrlMsg_Req_CustomRpcUnserialisedMsg {
517 uint32 custom_msg_id = 1;
518 bytes data = 2;
519}
520
521message CtrlMsg_Resp_CustomRpcUnserialisedMsg {
522 int32 resp = 1;
523 uint32 custom_msg_id = 2;
524 bytes data = 3;
525}
526
527message CtrlMsg_Event_CustomRpcUnserialisedMsg {
528 int32 resp = 1;
529 uint32 custom_evt_id = 2;
530 bytes data = 3;
360} 531}
361 532
362message CtrlMsg { 533message CtrlMsg {
@@ -366,6 +537,12 @@ message CtrlMsg {
366 /* msg id */ 537 /* msg id */
367 CtrlMsgId msg_id = 2; 538 CtrlMsgId msg_id = 2;
368 539
540 /* UID of message */
541 int32 uid = 3;
542
543 /* Request/response type: sync or async */
544 uint32 req_resp_type = 4;
545
369 /* union of all msg ids */ 546 /* union of all msg ids */
370 oneof payload { 547 oneof payload {
371 /** Requests **/ 548 /** Requests **/
@@ -395,6 +572,13 @@ message CtrlMsg {
395 CtrlMsg_Req_SetWifiMaxTxPower req_set_wifi_max_tx_power = 119; 572 CtrlMsg_Req_SetWifiMaxTxPower req_set_wifi_max_tx_power = 119;
396 CtrlMsg_Req_GetWifiCurrTxPower req_get_wifi_curr_tx_power = 120; 573 CtrlMsg_Req_GetWifiCurrTxPower req_get_wifi_curr_tx_power = 120;
397 CtrlMsg_Req_ConfigHeartbeat req_config_heartbeat = 121; 574 CtrlMsg_Req_ConfigHeartbeat req_config_heartbeat = 121;
575 CtrlMsg_Req_EnableDisable req_enable_disable_feat = 122;
576 CtrlMsg_Req_GetFwVersion req_get_fw_version = 123;
577 CtrlMsg_Req_SetCountryCode req_set_country_code = 124;
578 CtrlMsg_Req_GetCountryCode req_get_country_code = 125;
579 CtrlMsg_Req_SetDhcpDnsStatus req_set_dhcp_dns_status = 126;
580 CtrlMsg_Req_GetDhcpDnsStatus req_get_dhcp_dns_status = 127;
581 CtrlMsg_Req_CustomRpcUnserialisedMsg req_custom_rpc_unserialised_msg = 128;
398 582
399 /** Responses **/ 583 /** Responses **/
400 CtrlMsg_Resp_GetMacAddress resp_get_mac_address = 201; 584 CtrlMsg_Resp_GetMacAddress resp_get_mac_address = 201;
@@ -422,11 +606,22 @@ message CtrlMsg {
422 CtrlMsg_Resp_SetWifiMaxTxPower resp_set_wifi_max_tx_power = 219; 606 CtrlMsg_Resp_SetWifiMaxTxPower resp_set_wifi_max_tx_power = 219;
423 CtrlMsg_Resp_GetWifiCurrTxPower resp_get_wifi_curr_tx_power = 220; 607 CtrlMsg_Resp_GetWifiCurrTxPower resp_get_wifi_curr_tx_power = 220;
424 CtrlMsg_Resp_ConfigHeartbeat resp_config_heartbeat = 221; 608 CtrlMsg_Resp_ConfigHeartbeat resp_config_heartbeat = 221;
609 CtrlMsg_Resp_EnableDisable resp_enable_disable_feat = 222;
610 CtrlMsg_Resp_GetFwVersion resp_get_fw_version = 223;
611 CtrlMsg_Resp_SetCountryCode resp_set_country_code = 224;
612 CtrlMsg_Resp_GetCountryCode resp_get_country_code = 225;
613 CtrlMsg_Resp_SetDhcpDnsStatus resp_set_dhcp_dns_status = 226;
614 CtrlMsg_Resp_GetDhcpDnsStatus resp_get_dhcp_dns_status = 227;
615 CtrlMsg_Resp_CustomRpcUnserialisedMsg resp_custom_rpc_unserialised_msg = 228;
425 616
426 /** Notifications **/ 617 /** Notifications **/
427 CtrlMsg_Event_ESPInit event_esp_init = 301; 618 CtrlMsg_Event_ESPInit event_esp_init = 301;
428 CtrlMsg_Event_Heartbeat event_heartbeat = 302; 619 CtrlMsg_Event_Heartbeat event_heartbeat = 302;
429 CtrlMsg_Event_StationDisconnectFromAP event_station_disconnect_from_AP = 303; 620 CtrlMsg_Event_StationDisconnectFromAP event_station_disconnect_from_AP = 303;
430 CtrlMsg_Event_StationDisconnectFromESPSoftAP event_station_disconnect_from_ESP_SoftAP = 304; 621 CtrlMsg_Event_StationDisconnectFromESPSoftAP event_station_disconnect_from_ESP_SoftAP = 304;
622 CtrlMsg_Event_StationConnectedToAP event_station_connected_to_AP = 305;
623 CtrlMsg_Event_StationConnectedToESPSoftAP event_station_connected_to_ESP_SoftAP = 306;
624 CtrlMsg_Event_SetDhcpDnsStatus event_set_dhcp_dns_status = 307;
625 CtrlMsg_Event_CustomRpcUnserialisedMsg event_custom_rpc_unserialised_msg = 308;
431 } 626 }
432} 627}
diff --git a/embassy-net-esp-hosted/src/iface.rs b/embassy-net-esp-hosted/src/iface.rs
new file mode 100644
index 000000000..1f57851e0
--- /dev/null
+++ b/embassy-net-esp-hosted/src/iface.rs
@@ -0,0 +1,62 @@
1use embassy_time::Timer;
2use embedded_hal::digital::InputPin;
3use embedded_hal_async::digital::Wait;
4use embedded_hal_async::spi::SpiDevice;
5
6/// Physical interface trait for communicating with the ESP chip.
7pub trait Interface {
8 /// Wait for the HANDSHAKE signal indicating the ESP is ready for a new transaction.
9 async fn wait_for_handshake(&mut self);
10
11 /// Wait for the READY signal indicating the ESP has data to send.
12 async fn wait_for_ready(&mut self);
13
14 /// Perform a SPI transfer, exchanging data with the ESP chip.
15 async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]);
16}
17
18/// Standard SPI interface.
19///
20/// This interface is what's implemented in the upstream `esp-hosted-fg` firmware. It uses:
21/// - An `SpiDevice` for SPI communication (CS is handled by the device)
22/// - A handshake pin that signals when the ESP is ready for a new transaction
23/// - A ready pin that indicates when the ESP has data to send
24pub struct SpiInterface<SPI, IN> {
25 spi: SPI,
26 handshake: IN,
27 ready: IN,
28}
29
30impl<SPI, IN> SpiInterface<SPI, IN>
31where
32 SPI: SpiDevice,
33 IN: InputPin + Wait,
34{
35 /// Create a new SpiInterface.
36 pub fn new(spi: SPI, handshake: IN, ready: IN) -> Self {
37 Self { spi, handshake, ready }
38 }
39}
40
41impl<SPI, IN> Interface for SpiInterface<SPI, IN>
42where
43 SPI: SpiDevice,
44 IN: InputPin + Wait,
45{
46 async fn wait_for_handshake(&mut self) {
47 self.handshake.wait_for_high().await.unwrap();
48 }
49
50 async fn wait_for_ready(&mut self) {
51 self.ready.wait_for_high().await.unwrap();
52 }
53
54 async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) {
55 self.spi.transfer(rx, tx).await.unwrap();
56
57 // The esp-hosted firmware deasserts the HANDSHAKE pin a few us AFTER ending the SPI transfer
58 // If we check it again too fast, we'll see it's high from the previous transfer, and if we send it
59 // data it will get lost.
60 Timer::after_micros(100).await;
61 }
62}
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs
index 4405d9f77..d882af8cf 100644
--- a/embassy-net-esp-hosted/src/lib.rs
+++ b/embassy-net-esp-hosted/src/lib.rs
@@ -1,27 +1,34 @@
1#![no_std] 1#![no_std]
2#![doc = include_str!("../README.md")] 2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4#![allow(async_fn_in_trait)]
4 5
5use embassy_futures::select::{Either4, select4}; 6use embassy_futures::select::{Either4, select4};
6use embassy_net_driver_channel as ch; 7use embassy_net_driver_channel as ch;
7use embassy_net_driver_channel::driver::LinkState; 8use embassy_net_driver_channel::driver::LinkState;
8use embassy_time::{Duration, Instant, Timer}; 9use embassy_time::{Duration, Instant, Timer};
9use embedded_hal::digital::{InputPin, OutputPin}; 10use embedded_hal::digital::OutputPin;
10use embedded_hal_async::digital::Wait;
11use embedded_hal_async::spi::SpiDevice;
12 11
13use crate::ioctl::{PendingIoctl, Shared}; 12use crate::ioctl::{PendingIoctl, Shared};
14use crate::proto::{CtrlMsg, CtrlMsgPayload}; 13use crate::proto::{CtrlMsg, CtrlMsg_};
15 14
15#[allow(unused)]
16#[allow(non_snake_case)]
17#[allow(non_camel_case_types)]
18#[allow(non_upper_case_globals)]
19#[allow(missing_docs)]
20#[allow(clippy::all)]
16mod proto; 21mod proto;
17 22
18// must be first 23// must be first
19mod fmt; 24mod fmt;
20 25
21mod control; 26mod control;
27mod iface;
22mod ioctl; 28mod ioctl;
23 29
24pub use control::*; 30pub use control::*;
31pub use iface::*;
25 32
26const MTU: usize = 1514; 33const MTU: usize = 1514;
27 34
@@ -118,20 +125,17 @@ impl State {
118/// Type alias for network driver. 125/// Type alias for network driver.
119pub type NetDriver<'a> = ch::Device<'a, MTU>; 126pub type NetDriver<'a> = ch::Device<'a, MTU>;
120 127
121/// Create a new esp-hosted driver using the provided state, SPI peripheral and pins. 128/// Create a new esp-hosted driver using the provided state, interface, and reset pin.
122/// 129///
123/// Returns a device handle for interfacing with embassy-net, a control handle for 130/// Returns a device handle for interfacing with embassy-net, a control handle for
124/// interacting with the driver, and a runner for communicating with the WiFi device. 131/// interacting with the driver, and a runner for communicating with the WiFi device.
125pub async fn new<'a, SPI, IN, OUT>( 132pub async fn new<'a, I, OUT>(
126 state: &'a mut State, 133 state: &'a mut State,
127 spi: SPI, 134 iface: I,
128 handshake: IN,
129 ready: IN,
130 reset: OUT, 135 reset: OUT,
131) -> (NetDriver<'a>, Control<'a>, Runner<'a, SPI, IN, OUT>) 136) -> (NetDriver<'a>, Control<'a>, Runner<'a, I, OUT>)
132where 137where
133 SPI: SpiDevice, 138 I: Interface,
134 IN: InputPin + Wait,
135 OUT: OutputPin, 139 OUT: OutputPin,
136{ 140{
137 let (ch_runner, device) = ch::new(&mut state.ch, ch::driver::HardwareAddress::Ethernet([0; 6])); 141 let (ch_runner, device) = ch::new(&mut state.ch, ch::driver::HardwareAddress::Ethernet([0; 6]));
@@ -142,10 +146,8 @@ where
142 state_ch, 146 state_ch,
143 shared: &state.shared, 147 shared: &state.shared,
144 next_seq: 1, 148 next_seq: 1,
145 handshake,
146 ready,
147 reset, 149 reset,
148 spi, 150 iface,
149 heartbeat_deadline: Instant::now() + HEARTBEAT_MAX_GAP, 151 heartbeat_deadline: Instant::now() + HEARTBEAT_MAX_GAP,
150 }; 152 };
151 153
@@ -153,7 +155,7 @@ where
153} 155}
154 156
155/// Runner for communicating with the WiFi device. 157/// Runner for communicating with the WiFi device.
156pub struct Runner<'a, SPI, IN, OUT> { 158pub struct Runner<'a, I, OUT> {
157 ch: ch::Runner<'a, MTU>, 159 ch: ch::Runner<'a, MTU>,
158 state_ch: ch::StateRunner<'a>, 160 state_ch: ch::StateRunner<'a>,
159 shared: &'a Shared, 161 shared: &'a Shared,
@@ -161,16 +163,13 @@ pub struct Runner<'a, SPI, IN, OUT> {
161 next_seq: u16, 163 next_seq: u16,
162 heartbeat_deadline: Instant, 164 heartbeat_deadline: Instant,
163 165
164 spi: SPI, 166 iface: I,
165 handshake: IN,
166 ready: IN,
167 reset: OUT, 167 reset: OUT,
168} 168}
169 169
170impl<'a, SPI, IN, OUT> Runner<'a, SPI, IN, OUT> 170impl<'a, I, OUT> Runner<'a, I, OUT>
171where 171where
172 SPI: SpiDevice, 172 I: Interface,
173 IN: InputPin + Wait,
174 OUT: OutputPin, 173 OUT: OutputPin,
175{ 174{
176 /// Run the packet processing. 175 /// Run the packet processing.
@@ -185,11 +184,11 @@ where
185 let mut rx_buf = [0u8; MAX_SPI_BUFFER_SIZE]; 184 let mut rx_buf = [0u8; MAX_SPI_BUFFER_SIZE];
186 185
187 loop { 186 loop {
188 self.handshake.wait_for_high().await.unwrap(); 187 self.iface.wait_for_handshake().await;
189 188
190 let ioctl = self.shared.ioctl_wait_pending(); 189 let ioctl = self.shared.ioctl_wait_pending();
191 let tx = self.ch.tx_buf(); 190 let tx = self.ch.tx_buf();
192 let ev = async { self.ready.wait_for_high().await.unwrap() }; 191 let ev = async { self.iface.wait_for_ready().await };
193 let hb = Timer::at(self.heartbeat_deadline); 192 let hb = Timer::at(self.heartbeat_deadline);
194 193
195 match select4(ioctl, tx, ev, hb).await { 194 match select4(ioctl, tx, ev, hb).await {
@@ -243,15 +242,9 @@ where
243 trace!("tx: {:02x}", &tx_buf[..40]); 242 trace!("tx: {:02x}", &tx_buf[..40]);
244 } 243 }
245 244
246 self.spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); 245 self.iface.transfer(&mut rx_buf, &tx_buf).await;
247 246
248 // The esp-hosted firmware deasserts the HANSHAKE pin a few us AFTER ending the SPI transfer
249 // If we check it again too fast, we'll see it's high from the previous transfer, and if we send it
250 // data it will get lost.
251 // Make sure we check it after 100us at minimum.
252 let delay_until = Instant::now() + Duration::from_micros(100);
253 self.handle_rx(&mut rx_buf); 247 self.handle_rx(&mut rx_buf);
254 Timer::at(delay_until).await;
255 } 248 }
256 } 249 }
257 250
@@ -326,10 +319,12 @@ where
326 } 319 }
327 320
328 fn handle_event(&mut self, data: &[u8]) { 321 fn handle_event(&mut self, data: &[u8]) {
329 let Ok(event) = noproto::read::<CtrlMsg>(data) else { 322 use micropb::MessageDecode;
323 let mut event = CtrlMsg::default();
324 if event.decode_from_bytes(data).is_err() {
330 warn!("failed to parse event"); 325 warn!("failed to parse event");
331 return; 326 return;
332 }; 327 }
333 328
334 debug!("event: {:?}", &event); 329 debug!("event: {:?}", &event);
335 330
@@ -339,9 +334,13 @@ where
339 }; 334 };
340 335
341 match payload { 336 match payload {
342 CtrlMsgPayload::EventEspInit(_) => self.shared.init_done(), 337 CtrlMsg_::Payload::EventEspInit(_) => self.shared.init_done(),
343 CtrlMsgPayload::EventHeartbeat(_) => self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP, 338 CtrlMsg_::Payload::EventHeartbeat(_) => self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP,
344 CtrlMsgPayload::EventStationDisconnectFromAp(e) => { 339 CtrlMsg_::Payload::EventStationConnectedToAp(e) => {
340 info!("connected, code {}", e.resp);
341 self.state_ch.set_link_state(LinkState::Up);
342 }
343 CtrlMsg_::Payload::EventStationDisconnectFromAp(e) => {
345 info!("disconnected, code {}", e.resp); 344 info!("disconnected, code {}", e.resp);
346 self.state_ch.set_link_state(LinkState::Down); 345 self.state_ch.set_link_state(LinkState::Down);
347 } 346 }
diff --git a/embassy-net-esp-hosted/src/proto.rs b/embassy-net-esp-hosted/src/proto.rs
index 089ded677..74c67bd61 100644
--- a/embassy-net-esp-hosted/src/proto.rs
+++ b/embassy-net-esp-hosted/src/proto.rs
@@ -1,656 +1,13764 @@
1#![allow(unused)] 1/*
2Generated with the following snippet.
3Switch to a proper script when https://github.com/YuhanLiin/micropb/issues/30 is done
2 4
3use heapless::{String, Vec}; 5 let mut g = micropb_gen::Generator::new();
6 g.use_container_heapless();
4 7
5/// internal supporting structures for CtrlMsg 8 g.configure(
9 ".",
10 micropb_gen::Config::new()
11 .max_bytes(32) // For ssid, mac, etc - strings
12 .max_len(16) // For repeated fields
13 .type_attributes("#[cfg_attr(feature = \"defmt\", derive(defmt::Format))]"),
14 );
6 15
7#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 16 // Special config for things that need to be larger
8#[cfg_attr(feature = "defmt", derive(defmt::Format))] 17 g.configure(
9pub(crate) struct ScanResult { 18 ".CtrlMsg_Req_OTAWrite.ota_data",
10 #[noproto(tag = "1")] 19 micropb_gen::Config::new().max_bytes(1024),
11 pub ssid: String<32>, 20 );
12 #[noproto(tag = "2")] 21 g.configure(
13 pub chnl: u32, 22 ".CtrlMsg_Event_ESPInit.init_data",
14 #[noproto(tag = "3")] 23 micropb_gen::Config::new().max_bytes(64),
15 pub rssi: u32, 24 );
16 #[noproto(tag = "4")] 25 g.configure(
17 pub bssid: String<32>, 26 ".CtrlMsg_Req_VendorIEData.payload",
18 #[noproto(tag = "5")] 27 micropb_gen::Config::new().max_bytes(64),
19 pub sec_prot: CtrlWifiSecProt, 28 );
20} 29
30 g.compile_protos(&["src/esp_hosted_config.proto"], format!("{}/proto.rs", out_dir))
31 .unwrap();
32
33*/
21 34
22#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 35#[derive(Debug, Default, PartialEq, Clone)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))] 36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub(crate) struct ConnectedStaList { 37pub struct ScanResult {
25 #[noproto(tag = "1")] 38 pub r#ssid: ::micropb::heapless::Vec<u8, 32>,
26 pub mac: String<32>, 39 pub r#chnl: u32,
27 #[noproto(tag = "2")] 40 pub r#rssi: i32,
28 pub rssi: u32, 41 pub r#bssid: ::micropb::heapless::Vec<u8, 32>,
42 pub r#sec_prot: Ctrl_WifiSecProt,
29} 43}
30/// * Req/Resp structure * 44impl ScanResult {
31 45 ///Return a reference to `ssid`
32#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 46 #[inline]
47 pub fn r#ssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
48 &self.r#ssid
49 }
50 ///Return a mutable reference to `ssid`
51 #[inline]
52 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
53 &mut self.r#ssid
54 }
55 ///Set the value of `ssid`
56 #[inline]
57 pub fn set_ssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
58 self.r#ssid = value.into();
59 self
60 }
61 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
62 #[inline]
63 pub fn init_ssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
64 self.r#ssid = value.into();
65 self
66 }
67 ///Return a reference to `chnl`
68 #[inline]
69 pub fn r#chnl(&self) -> &u32 {
70 &self.r#chnl
71 }
72 ///Return a mutable reference to `chnl`
73 #[inline]
74 pub fn mut_chnl(&mut self) -> &mut u32 {
75 &mut self.r#chnl
76 }
77 ///Set the value of `chnl`
78 #[inline]
79 pub fn set_chnl(&mut self, value: u32) -> &mut Self {
80 self.r#chnl = value.into();
81 self
82 }
83 ///Builder method that sets the value of `chnl`. Useful for initializing the message.
84 #[inline]
85 pub fn init_chnl(mut self, value: u32) -> Self {
86 self.r#chnl = value.into();
87 self
88 }
89 ///Return a reference to `rssi`
90 #[inline]
91 pub fn r#rssi(&self) -> &i32 {
92 &self.r#rssi
93 }
94 ///Return a mutable reference to `rssi`
95 #[inline]
96 pub fn mut_rssi(&mut self) -> &mut i32 {
97 &mut self.r#rssi
98 }
99 ///Set the value of `rssi`
100 #[inline]
101 pub fn set_rssi(&mut self, value: i32) -> &mut Self {
102 self.r#rssi = value.into();
103 self
104 }
105 ///Builder method that sets the value of `rssi`. Useful for initializing the message.
106 #[inline]
107 pub fn init_rssi(mut self, value: i32) -> Self {
108 self.r#rssi = value.into();
109 self
110 }
111 ///Return a reference to `bssid`
112 #[inline]
113 pub fn r#bssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
114 &self.r#bssid
115 }
116 ///Return a mutable reference to `bssid`
117 #[inline]
118 pub fn mut_bssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
119 &mut self.r#bssid
120 }
121 ///Set the value of `bssid`
122 #[inline]
123 pub fn set_bssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
124 self.r#bssid = value.into();
125 self
126 }
127 ///Builder method that sets the value of `bssid`. Useful for initializing the message.
128 #[inline]
129 pub fn init_bssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
130 self.r#bssid = value.into();
131 self
132 }
133 ///Return a reference to `sec_prot`
134 #[inline]
135 pub fn r#sec_prot(&self) -> &Ctrl_WifiSecProt {
136 &self.r#sec_prot
137 }
138 ///Return a mutable reference to `sec_prot`
139 #[inline]
140 pub fn mut_sec_prot(&mut self) -> &mut Ctrl_WifiSecProt {
141 &mut self.r#sec_prot
142 }
143 ///Set the value of `sec_prot`
144 #[inline]
145 pub fn set_sec_prot(&mut self, value: Ctrl_WifiSecProt) -> &mut Self {
146 self.r#sec_prot = value.into();
147 self
148 }
149 ///Builder method that sets the value of `sec_prot`. Useful for initializing the message.
150 #[inline]
151 pub fn init_sec_prot(mut self, value: Ctrl_WifiSecProt) -> Self {
152 self.r#sec_prot = value.into();
153 self
154 }
155}
156impl ::micropb::MessageDecode for ScanResult {
157 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
158 &mut self,
159 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
160 len: usize,
161 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
162 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
163 let before = decoder.bytes_read();
164 while decoder.bytes_read() - before < len {
165 let tag = decoder.decode_tag()?;
166 match tag.field_num() {
167 0 => return Err(::micropb::DecodeError::ZeroField),
168 1u32 => {
169 let mut_ref = &mut self.r#ssid;
170 {
171 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
172 };
173 }
174 2u32 => {
175 let mut_ref = &mut self.r#chnl;
176 {
177 let val = decoder.decode_varint32()?;
178 let val_ref = &val;
179 if *val_ref != 0 {
180 *mut_ref = val as _;
181 }
182 };
183 }
184 3u32 => {
185 let mut_ref = &mut self.r#rssi;
186 {
187 let val = decoder.decode_int32()?;
188 let val_ref = &val;
189 if *val_ref != 0 {
190 *mut_ref = val as _;
191 }
192 };
193 }
194 4u32 => {
195 let mut_ref = &mut self.r#bssid;
196 {
197 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
198 };
199 }
200 5u32 => {
201 let mut_ref = &mut self.r#sec_prot;
202 {
203 let val = decoder.decode_int32().map(|n| Ctrl_WifiSecProt(n as _))?;
204 let val_ref = &val;
205 if val_ref.0 != 0 {
206 *mut_ref = val as _;
207 }
208 };
209 }
210 _ => {
211 decoder.skip_wire_value(tag.wire_type())?;
212 }
213 }
214 }
215 Ok(())
216 }
217}
218impl ::micropb::MessageEncode for ScanResult {
219 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
220 let mut max_size = 0;
221 if let ::core::option::Option::Some(size) =
222 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
223 {
224 max_size += size;
225 } else {
226 break 'msg (::core::option::Option::<usize>::None);
227 };
228 if let ::core::option::Option::Some(size) =
229 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
230 {
231 max_size += size;
232 } else {
233 break 'msg (::core::option::Option::<usize>::None);
234 };
235 if let ::core::option::Option::Some(size) =
236 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
237 {
238 max_size += size;
239 } else {
240 break 'msg (::core::option::Option::<usize>::None);
241 };
242 if let ::core::option::Option::Some(size) =
243 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
244 {
245 max_size += size;
246 } else {
247 break 'msg (::core::option::Option::<usize>::None);
248 };
249 if let ::core::option::Option::Some(size) =
250 ::micropb::const_map!(::core::option::Option::Some(Ctrl_WifiSecProt::_MAX_SIZE), |size| size
251 + 1usize)
252 {
253 max_size += size;
254 } else {
255 break 'msg (::core::option::Option::<usize>::None);
256 };
257 ::core::option::Option::Some(max_size)
258 };
259 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
260 &self,
261 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
262 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
263 use ::micropb::{FieldEncode, PbMap};
264 {
265 let val_ref = &self.r#ssid;
266 if !val_ref.is_empty() {
267 encoder.encode_varint32(10u32)?;
268 encoder.encode_bytes(val_ref)?;
269 }
270 }
271 {
272 let val_ref = &self.r#chnl;
273 if *val_ref != 0 {
274 encoder.encode_varint32(16u32)?;
275 encoder.encode_varint32(*val_ref as _)?;
276 }
277 }
278 {
279 let val_ref = &self.r#rssi;
280 if *val_ref != 0 {
281 encoder.encode_varint32(24u32)?;
282 encoder.encode_int32(*val_ref as _)?;
283 }
284 }
285 {
286 let val_ref = &self.r#bssid;
287 if !val_ref.is_empty() {
288 encoder.encode_varint32(34u32)?;
289 encoder.encode_bytes(val_ref)?;
290 }
291 }
292 {
293 let val_ref = &self.r#sec_prot;
294 if val_ref.0 != 0 {
295 encoder.encode_varint32(40u32)?;
296 encoder.encode_int32(val_ref.0 as _)?;
297 }
298 }
299 Ok(())
300 }
301 fn compute_size(&self) -> usize {
302 use ::micropb::{FieldEncode, PbMap};
303 let mut size = 0;
304 {
305 let val_ref = &self.r#ssid;
306 if !val_ref.is_empty() {
307 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
308 }
309 }
310 {
311 let val_ref = &self.r#chnl;
312 if *val_ref != 0 {
313 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
314 }
315 }
316 {
317 let val_ref = &self.r#rssi;
318 if *val_ref != 0 {
319 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
320 }
321 }
322 {
323 let val_ref = &self.r#bssid;
324 if !val_ref.is_empty() {
325 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
326 }
327 }
328 {
329 let val_ref = &self.r#sec_prot;
330 if val_ref.0 != 0 {
331 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
332 }
333 }
334 size
335 }
336}
337#[derive(Debug, Default, PartialEq, Clone)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))] 338#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub(crate) struct CtrlMsgReqGetMacAddress { 339pub struct ConnectedSTAList {
35 #[noproto(tag = "1")] 340 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
36 pub mode: u32, 341 pub r#rssi: i32,
37} 342}
38 343impl ConnectedSTAList {
39#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 344 ///Return a reference to `mac`
345 #[inline]
346 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
347 &self.r#mac
348 }
349 ///Return a mutable reference to `mac`
350 #[inline]
351 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
352 &mut self.r#mac
353 }
354 ///Set the value of `mac`
355 #[inline]
356 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
357 self.r#mac = value.into();
358 self
359 }
360 ///Builder method that sets the value of `mac`. Useful for initializing the message.
361 #[inline]
362 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
363 self.r#mac = value.into();
364 self
365 }
366 ///Return a reference to `rssi`
367 #[inline]
368 pub fn r#rssi(&self) -> &i32 {
369 &self.r#rssi
370 }
371 ///Return a mutable reference to `rssi`
372 #[inline]
373 pub fn mut_rssi(&mut self) -> &mut i32 {
374 &mut self.r#rssi
375 }
376 ///Set the value of `rssi`
377 #[inline]
378 pub fn set_rssi(&mut self, value: i32) -> &mut Self {
379 self.r#rssi = value.into();
380 self
381 }
382 ///Builder method that sets the value of `rssi`. Useful for initializing the message.
383 #[inline]
384 pub fn init_rssi(mut self, value: i32) -> Self {
385 self.r#rssi = value.into();
386 self
387 }
388}
389impl ::micropb::MessageDecode for ConnectedSTAList {
390 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
391 &mut self,
392 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
393 len: usize,
394 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
395 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
396 let before = decoder.bytes_read();
397 while decoder.bytes_read() - before < len {
398 let tag = decoder.decode_tag()?;
399 match tag.field_num() {
400 0 => return Err(::micropb::DecodeError::ZeroField),
401 1u32 => {
402 let mut_ref = &mut self.r#mac;
403 {
404 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
405 };
406 }
407 2u32 => {
408 let mut_ref = &mut self.r#rssi;
409 {
410 let val = decoder.decode_int32()?;
411 let val_ref = &val;
412 if *val_ref != 0 {
413 *mut_ref = val as _;
414 }
415 };
416 }
417 _ => {
418 decoder.skip_wire_value(tag.wire_type())?;
419 }
420 }
421 }
422 Ok(())
423 }
424}
425impl ::micropb::MessageEncode for ConnectedSTAList {
426 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
427 let mut max_size = 0;
428 if let ::core::option::Option::Some(size) =
429 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
430 {
431 max_size += size;
432 } else {
433 break 'msg (::core::option::Option::<usize>::None);
434 };
435 if let ::core::option::Option::Some(size) =
436 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
437 {
438 max_size += size;
439 } else {
440 break 'msg (::core::option::Option::<usize>::None);
441 };
442 ::core::option::Option::Some(max_size)
443 };
444 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
445 &self,
446 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
447 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
448 use ::micropb::{FieldEncode, PbMap};
449 {
450 let val_ref = &self.r#mac;
451 if !val_ref.is_empty() {
452 encoder.encode_varint32(10u32)?;
453 encoder.encode_bytes(val_ref)?;
454 }
455 }
456 {
457 let val_ref = &self.r#rssi;
458 if *val_ref != 0 {
459 encoder.encode_varint32(16u32)?;
460 encoder.encode_int32(*val_ref as _)?;
461 }
462 }
463 Ok(())
464 }
465 fn compute_size(&self) -> usize {
466 use ::micropb::{FieldEncode, PbMap};
467 let mut size = 0;
468 {
469 let val_ref = &self.r#mac;
470 if !val_ref.is_empty() {
471 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
472 }
473 }
474 {
475 let val_ref = &self.r#rssi;
476 if *val_ref != 0 {
477 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
478 }
479 }
480 size
481 }
482}
483#[derive(Debug, Default, PartialEq, Clone)]
40#[cfg_attr(feature = "defmt", derive(defmt::Format))] 484#[cfg_attr(feature = "defmt", derive(defmt::Format))]
41pub(crate) struct CtrlMsgRespGetMacAddress { 485pub struct CtrlMsg_Req_GetMacAddress {
42 #[noproto(tag = "1")] 486 pub r#mode: i32,
43 pub mac: String<32>,
44 #[noproto(tag = "2")]
45 pub resp: u32,
46} 487}
47 488impl CtrlMsg_Req_GetMacAddress {
48#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 489 ///Return a reference to `mode`
490 #[inline]
491 pub fn r#mode(&self) -> &i32 {
492 &self.r#mode
493 }
494 ///Return a mutable reference to `mode`
495 #[inline]
496 pub fn mut_mode(&mut self) -> &mut i32 {
497 &mut self.r#mode
498 }
499 ///Set the value of `mode`
500 #[inline]
501 pub fn set_mode(&mut self, value: i32) -> &mut Self {
502 self.r#mode = value.into();
503 self
504 }
505 ///Builder method that sets the value of `mode`. Useful for initializing the message.
506 #[inline]
507 pub fn init_mode(mut self, value: i32) -> Self {
508 self.r#mode = value.into();
509 self
510 }
511}
512impl ::micropb::MessageDecode for CtrlMsg_Req_GetMacAddress {
513 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
514 &mut self,
515 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
516 len: usize,
517 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
518 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
519 let before = decoder.bytes_read();
520 while decoder.bytes_read() - before < len {
521 let tag = decoder.decode_tag()?;
522 match tag.field_num() {
523 0 => return Err(::micropb::DecodeError::ZeroField),
524 1u32 => {
525 let mut_ref = &mut self.r#mode;
526 {
527 let val = decoder.decode_int32()?;
528 let val_ref = &val;
529 if *val_ref != 0 {
530 *mut_ref = val as _;
531 }
532 };
533 }
534 _ => {
535 decoder.skip_wire_value(tag.wire_type())?;
536 }
537 }
538 }
539 Ok(())
540 }
541}
542impl ::micropb::MessageEncode for CtrlMsg_Req_GetMacAddress {
543 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
544 let mut max_size = 0;
545 if let ::core::option::Option::Some(size) =
546 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
547 {
548 max_size += size;
549 } else {
550 break 'msg (::core::option::Option::<usize>::None);
551 };
552 ::core::option::Option::Some(max_size)
553 };
554 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
555 &self,
556 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
557 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
558 use ::micropb::{FieldEncode, PbMap};
559 {
560 let val_ref = &self.r#mode;
561 if *val_ref != 0 {
562 encoder.encode_varint32(8u32)?;
563 encoder.encode_int32(*val_ref as _)?;
564 }
565 }
566 Ok(())
567 }
568 fn compute_size(&self) -> usize {
569 use ::micropb::{FieldEncode, PbMap};
570 let mut size = 0;
571 {
572 let val_ref = &self.r#mode;
573 if *val_ref != 0 {
574 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
575 }
576 }
577 size
578 }
579}
580#[derive(Debug, Default, PartialEq, Clone)]
49#[cfg_attr(feature = "defmt", derive(defmt::Format))] 581#[cfg_attr(feature = "defmt", derive(defmt::Format))]
50pub(crate) struct CtrlMsgReqGetMode {} 582pub struct CtrlMsg_Resp_GetMacAddress {
51 583 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
52#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 584 pub r#resp: i32,
585}
586impl CtrlMsg_Resp_GetMacAddress {
587 ///Return a reference to `mac`
588 #[inline]
589 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
590 &self.r#mac
591 }
592 ///Return a mutable reference to `mac`
593 #[inline]
594 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
595 &mut self.r#mac
596 }
597 ///Set the value of `mac`
598 #[inline]
599 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
600 self.r#mac = value.into();
601 self
602 }
603 ///Builder method that sets the value of `mac`. Useful for initializing the message.
604 #[inline]
605 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
606 self.r#mac = value.into();
607 self
608 }
609 ///Return a reference to `resp`
610 #[inline]
611 pub fn r#resp(&self) -> &i32 {
612 &self.r#resp
613 }
614 ///Return a mutable reference to `resp`
615 #[inline]
616 pub fn mut_resp(&mut self) -> &mut i32 {
617 &mut self.r#resp
618 }
619 ///Set the value of `resp`
620 #[inline]
621 pub fn set_resp(&mut self, value: i32) -> &mut Self {
622 self.r#resp = value.into();
623 self
624 }
625 ///Builder method that sets the value of `resp`. Useful for initializing the message.
626 #[inline]
627 pub fn init_resp(mut self, value: i32) -> Self {
628 self.r#resp = value.into();
629 self
630 }
631}
632impl ::micropb::MessageDecode for CtrlMsg_Resp_GetMacAddress {
633 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
634 &mut self,
635 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
636 len: usize,
637 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
638 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
639 let before = decoder.bytes_read();
640 while decoder.bytes_read() - before < len {
641 let tag = decoder.decode_tag()?;
642 match tag.field_num() {
643 0 => return Err(::micropb::DecodeError::ZeroField),
644 1u32 => {
645 let mut_ref = &mut self.r#mac;
646 {
647 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
648 };
649 }
650 2u32 => {
651 let mut_ref = &mut self.r#resp;
652 {
653 let val = decoder.decode_int32()?;
654 let val_ref = &val;
655 if *val_ref != 0 {
656 *mut_ref = val as _;
657 }
658 };
659 }
660 _ => {
661 decoder.skip_wire_value(tag.wire_type())?;
662 }
663 }
664 }
665 Ok(())
666 }
667}
668impl ::micropb::MessageEncode for CtrlMsg_Resp_GetMacAddress {
669 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
670 let mut max_size = 0;
671 if let ::core::option::Option::Some(size) =
672 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
673 {
674 max_size += size;
675 } else {
676 break 'msg (::core::option::Option::<usize>::None);
677 };
678 if let ::core::option::Option::Some(size) =
679 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
680 {
681 max_size += size;
682 } else {
683 break 'msg (::core::option::Option::<usize>::None);
684 };
685 ::core::option::Option::Some(max_size)
686 };
687 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
688 &self,
689 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
690 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
691 use ::micropb::{FieldEncode, PbMap};
692 {
693 let val_ref = &self.r#mac;
694 if !val_ref.is_empty() {
695 encoder.encode_varint32(10u32)?;
696 encoder.encode_bytes(val_ref)?;
697 }
698 }
699 {
700 let val_ref = &self.r#resp;
701 if *val_ref != 0 {
702 encoder.encode_varint32(16u32)?;
703 encoder.encode_int32(*val_ref as _)?;
704 }
705 }
706 Ok(())
707 }
708 fn compute_size(&self) -> usize {
709 use ::micropb::{FieldEncode, PbMap};
710 let mut size = 0;
711 {
712 let val_ref = &self.r#mac;
713 if !val_ref.is_empty() {
714 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
715 }
716 }
717 {
718 let val_ref = &self.r#resp;
719 if *val_ref != 0 {
720 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
721 }
722 }
723 size
724 }
725}
726#[derive(Debug, Default, PartialEq, Clone)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))] 727#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54pub(crate) struct CtrlMsgRespGetMode { 728pub struct CtrlMsg_Req_GetMode {}
55 #[noproto(tag = "1")] 729impl CtrlMsg_Req_GetMode {}
56 pub mode: u32, 730impl ::micropb::MessageDecode for CtrlMsg_Req_GetMode {
57 #[noproto(tag = "2")] 731 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
58 pub resp: u32, 732 &mut self,
733 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
734 len: usize,
735 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
736 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
737 let before = decoder.bytes_read();
738 while decoder.bytes_read() - before < len {
739 let tag = decoder.decode_tag()?;
740 match tag.field_num() {
741 0 => return Err(::micropb::DecodeError::ZeroField),
742 _ => {
743 decoder.skip_wire_value(tag.wire_type())?;
744 }
745 }
746 }
747 Ok(())
748 }
59} 749}
60 750impl ::micropb::MessageEncode for CtrlMsg_Req_GetMode {
61#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 751 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
752 let mut max_size = 0;
753 ::core::option::Option::Some(max_size)
754 };
755 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
756 &self,
757 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
758 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
759 use ::micropb::{FieldEncode, PbMap};
760 Ok(())
761 }
762 fn compute_size(&self) -> usize {
763 use ::micropb::{FieldEncode, PbMap};
764 let mut size = 0;
765 size
766 }
767}
768#[derive(Debug, Default, PartialEq, Clone)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))] 769#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub(crate) struct CtrlMsgReqSetMode { 770pub struct CtrlMsg_Resp_GetMode {
64 #[noproto(tag = "1")] 771 pub r#mode: i32,
65 pub mode: u32, 772 pub r#resp: i32,
66} 773}
67 774impl CtrlMsg_Resp_GetMode {
68#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 775 ///Return a reference to `mode`
776 #[inline]
777 pub fn r#mode(&self) -> &i32 {
778 &self.r#mode
779 }
780 ///Return a mutable reference to `mode`
781 #[inline]
782 pub fn mut_mode(&mut self) -> &mut i32 {
783 &mut self.r#mode
784 }
785 ///Set the value of `mode`
786 #[inline]
787 pub fn set_mode(&mut self, value: i32) -> &mut Self {
788 self.r#mode = value.into();
789 self
790 }
791 ///Builder method that sets the value of `mode`. Useful for initializing the message.
792 #[inline]
793 pub fn init_mode(mut self, value: i32) -> Self {
794 self.r#mode = value.into();
795 self
796 }
797 ///Return a reference to `resp`
798 #[inline]
799 pub fn r#resp(&self) -> &i32 {
800 &self.r#resp
801 }
802 ///Return a mutable reference to `resp`
803 #[inline]
804 pub fn mut_resp(&mut self) -> &mut i32 {
805 &mut self.r#resp
806 }
807 ///Set the value of `resp`
808 #[inline]
809 pub fn set_resp(&mut self, value: i32) -> &mut Self {
810 self.r#resp = value.into();
811 self
812 }
813 ///Builder method that sets the value of `resp`. Useful for initializing the message.
814 #[inline]
815 pub fn init_resp(mut self, value: i32) -> Self {
816 self.r#resp = value.into();
817 self
818 }
819}
820impl ::micropb::MessageDecode for CtrlMsg_Resp_GetMode {
821 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
822 &mut self,
823 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
824 len: usize,
825 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
826 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
827 let before = decoder.bytes_read();
828 while decoder.bytes_read() - before < len {
829 let tag = decoder.decode_tag()?;
830 match tag.field_num() {
831 0 => return Err(::micropb::DecodeError::ZeroField),
832 1u32 => {
833 let mut_ref = &mut self.r#mode;
834 {
835 let val = decoder.decode_int32()?;
836 let val_ref = &val;
837 if *val_ref != 0 {
838 *mut_ref = val as _;
839 }
840 };
841 }
842 2u32 => {
843 let mut_ref = &mut self.r#resp;
844 {
845 let val = decoder.decode_int32()?;
846 let val_ref = &val;
847 if *val_ref != 0 {
848 *mut_ref = val as _;
849 }
850 };
851 }
852 _ => {
853 decoder.skip_wire_value(tag.wire_type())?;
854 }
855 }
856 }
857 Ok(())
858 }
859}
860impl ::micropb::MessageEncode for CtrlMsg_Resp_GetMode {
861 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
862 let mut max_size = 0;
863 if let ::core::option::Option::Some(size) =
864 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
865 {
866 max_size += size;
867 } else {
868 break 'msg (::core::option::Option::<usize>::None);
869 };
870 if let ::core::option::Option::Some(size) =
871 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
872 {
873 max_size += size;
874 } else {
875 break 'msg (::core::option::Option::<usize>::None);
876 };
877 ::core::option::Option::Some(max_size)
878 };
879 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
880 &self,
881 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
882 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
883 use ::micropb::{FieldEncode, PbMap};
884 {
885 let val_ref = &self.r#mode;
886 if *val_ref != 0 {
887 encoder.encode_varint32(8u32)?;
888 encoder.encode_int32(*val_ref as _)?;
889 }
890 }
891 {
892 let val_ref = &self.r#resp;
893 if *val_ref != 0 {
894 encoder.encode_varint32(16u32)?;
895 encoder.encode_int32(*val_ref as _)?;
896 }
897 }
898 Ok(())
899 }
900 fn compute_size(&self) -> usize {
901 use ::micropb::{FieldEncode, PbMap};
902 let mut size = 0;
903 {
904 let val_ref = &self.r#mode;
905 if *val_ref != 0 {
906 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
907 }
908 }
909 {
910 let val_ref = &self.r#resp;
911 if *val_ref != 0 {
912 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
913 }
914 }
915 size
916 }
917}
918#[derive(Debug, Default, PartialEq, Clone)]
69#[cfg_attr(feature = "defmt", derive(defmt::Format))] 919#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70pub(crate) struct CtrlMsgRespSetMode { 920pub struct CtrlMsg_Req_SetMode {
71 #[noproto(tag = "1")] 921 pub r#mode: i32,
72 pub resp: u32,
73} 922}
74 923impl CtrlMsg_Req_SetMode {
75#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 924 ///Return a reference to `mode`
925 #[inline]
926 pub fn r#mode(&self) -> &i32 {
927 &self.r#mode
928 }
929 ///Return a mutable reference to `mode`
930 #[inline]
931 pub fn mut_mode(&mut self) -> &mut i32 {
932 &mut self.r#mode
933 }
934 ///Set the value of `mode`
935 #[inline]
936 pub fn set_mode(&mut self, value: i32) -> &mut Self {
937 self.r#mode = value.into();
938 self
939 }
940 ///Builder method that sets the value of `mode`. Useful for initializing the message.
941 #[inline]
942 pub fn init_mode(mut self, value: i32) -> Self {
943 self.r#mode = value.into();
944 self
945 }
946}
947impl ::micropb::MessageDecode for CtrlMsg_Req_SetMode {
948 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
949 &mut self,
950 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
951 len: usize,
952 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
953 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
954 let before = decoder.bytes_read();
955 while decoder.bytes_read() - before < len {
956 let tag = decoder.decode_tag()?;
957 match tag.field_num() {
958 0 => return Err(::micropb::DecodeError::ZeroField),
959 1u32 => {
960 let mut_ref = &mut self.r#mode;
961 {
962 let val = decoder.decode_int32()?;
963 let val_ref = &val;
964 if *val_ref != 0 {
965 *mut_ref = val as _;
966 }
967 };
968 }
969 _ => {
970 decoder.skip_wire_value(tag.wire_type())?;
971 }
972 }
973 }
974 Ok(())
975 }
976}
977impl ::micropb::MessageEncode for CtrlMsg_Req_SetMode {
978 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
979 let mut max_size = 0;
980 if let ::core::option::Option::Some(size) =
981 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
982 {
983 max_size += size;
984 } else {
985 break 'msg (::core::option::Option::<usize>::None);
986 };
987 ::core::option::Option::Some(max_size)
988 };
989 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
990 &self,
991 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
992 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
993 use ::micropb::{FieldEncode, PbMap};
994 {
995 let val_ref = &self.r#mode;
996 if *val_ref != 0 {
997 encoder.encode_varint32(8u32)?;
998 encoder.encode_int32(*val_ref as _)?;
999 }
1000 }
1001 Ok(())
1002 }
1003 fn compute_size(&self) -> usize {
1004 use ::micropb::{FieldEncode, PbMap};
1005 let mut size = 0;
1006 {
1007 let val_ref = &self.r#mode;
1008 if *val_ref != 0 {
1009 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1010 }
1011 }
1012 size
1013 }
1014}
1015#[derive(Debug, Default, PartialEq, Clone)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1016#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77pub(crate) struct CtrlMsgReqGetStatus {} 1017pub struct CtrlMsg_Resp_SetMode {
78 1018 pub r#resp: i32,
79#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1019}
1020impl CtrlMsg_Resp_SetMode {
1021 ///Return a reference to `resp`
1022 #[inline]
1023 pub fn r#resp(&self) -> &i32 {
1024 &self.r#resp
1025 }
1026 ///Return a mutable reference to `resp`
1027 #[inline]
1028 pub fn mut_resp(&mut self) -> &mut i32 {
1029 &mut self.r#resp
1030 }
1031 ///Set the value of `resp`
1032 #[inline]
1033 pub fn set_resp(&mut self, value: i32) -> &mut Self {
1034 self.r#resp = value.into();
1035 self
1036 }
1037 ///Builder method that sets the value of `resp`. Useful for initializing the message.
1038 #[inline]
1039 pub fn init_resp(mut self, value: i32) -> Self {
1040 self.r#resp = value.into();
1041 self
1042 }
1043}
1044impl ::micropb::MessageDecode for CtrlMsg_Resp_SetMode {
1045 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1046 &mut self,
1047 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1048 len: usize,
1049 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1050 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1051 let before = decoder.bytes_read();
1052 while decoder.bytes_read() - before < len {
1053 let tag = decoder.decode_tag()?;
1054 match tag.field_num() {
1055 0 => return Err(::micropb::DecodeError::ZeroField),
1056 1u32 => {
1057 let mut_ref = &mut self.r#resp;
1058 {
1059 let val = decoder.decode_int32()?;
1060 let val_ref = &val;
1061 if *val_ref != 0 {
1062 *mut_ref = val as _;
1063 }
1064 };
1065 }
1066 _ => {
1067 decoder.skip_wire_value(tag.wire_type())?;
1068 }
1069 }
1070 }
1071 Ok(())
1072 }
1073}
1074impl ::micropb::MessageEncode for CtrlMsg_Resp_SetMode {
1075 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1076 let mut max_size = 0;
1077 if let ::core::option::Option::Some(size) =
1078 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1079 {
1080 max_size += size;
1081 } else {
1082 break 'msg (::core::option::Option::<usize>::None);
1083 };
1084 ::core::option::Option::Some(max_size)
1085 };
1086 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1087 &self,
1088 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1089 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1090 use ::micropb::{FieldEncode, PbMap};
1091 {
1092 let val_ref = &self.r#resp;
1093 if *val_ref != 0 {
1094 encoder.encode_varint32(8u32)?;
1095 encoder.encode_int32(*val_ref as _)?;
1096 }
1097 }
1098 Ok(())
1099 }
1100 fn compute_size(&self) -> usize {
1101 use ::micropb::{FieldEncode, PbMap};
1102 let mut size = 0;
1103 {
1104 let val_ref = &self.r#resp;
1105 if *val_ref != 0 {
1106 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1107 }
1108 }
1109 size
1110 }
1111}
1112#[derive(Debug, Default, PartialEq, Clone)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1113#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub(crate) struct CtrlMsgRespGetStatus { 1114pub struct CtrlMsg_Req_GetStatus {}
82 #[noproto(tag = "1")] 1115impl CtrlMsg_Req_GetStatus {}
83 pub resp: u32, 1116impl ::micropb::MessageDecode for CtrlMsg_Req_GetStatus {
1117 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1118 &mut self,
1119 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1120 len: usize,
1121 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1122 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1123 let before = decoder.bytes_read();
1124 while decoder.bytes_read() - before < len {
1125 let tag = decoder.decode_tag()?;
1126 match tag.field_num() {
1127 0 => return Err(::micropb::DecodeError::ZeroField),
1128 _ => {
1129 decoder.skip_wire_value(tag.wire_type())?;
1130 }
1131 }
1132 }
1133 Ok(())
1134 }
84} 1135}
85 1136impl ::micropb::MessageEncode for CtrlMsg_Req_GetStatus {
86#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1137 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1138 let mut max_size = 0;
1139 ::core::option::Option::Some(max_size)
1140 };
1141 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1142 &self,
1143 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1144 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1145 use ::micropb::{FieldEncode, PbMap};
1146 Ok(())
1147 }
1148 fn compute_size(&self) -> usize {
1149 use ::micropb::{FieldEncode, PbMap};
1150 let mut size = 0;
1151 size
1152 }
1153}
1154#[derive(Debug, Default, PartialEq, Clone)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1155#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub(crate) struct CtrlMsgReqSetMacAddress { 1156pub struct CtrlMsg_Resp_GetStatus {
89 #[noproto(tag = "1")] 1157 pub r#resp: i32,
90 pub mac: String<32>,
91 #[noproto(tag = "2")]
92 pub mode: u32,
93} 1158}
94 1159impl CtrlMsg_Resp_GetStatus {
95#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1160 ///Return a reference to `resp`
1161 #[inline]
1162 pub fn r#resp(&self) -> &i32 {
1163 &self.r#resp
1164 }
1165 ///Return a mutable reference to `resp`
1166 #[inline]
1167 pub fn mut_resp(&mut self) -> &mut i32 {
1168 &mut self.r#resp
1169 }
1170 ///Set the value of `resp`
1171 #[inline]
1172 pub fn set_resp(&mut self, value: i32) -> &mut Self {
1173 self.r#resp = value.into();
1174 self
1175 }
1176 ///Builder method that sets the value of `resp`. Useful for initializing the message.
1177 #[inline]
1178 pub fn init_resp(mut self, value: i32) -> Self {
1179 self.r#resp = value.into();
1180 self
1181 }
1182}
1183impl ::micropb::MessageDecode for CtrlMsg_Resp_GetStatus {
1184 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1185 &mut self,
1186 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1187 len: usize,
1188 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1189 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1190 let before = decoder.bytes_read();
1191 while decoder.bytes_read() - before < len {
1192 let tag = decoder.decode_tag()?;
1193 match tag.field_num() {
1194 0 => return Err(::micropb::DecodeError::ZeroField),
1195 1u32 => {
1196 let mut_ref = &mut self.r#resp;
1197 {
1198 let val = decoder.decode_int32()?;
1199 let val_ref = &val;
1200 if *val_ref != 0 {
1201 *mut_ref = val as _;
1202 }
1203 };
1204 }
1205 _ => {
1206 decoder.skip_wire_value(tag.wire_type())?;
1207 }
1208 }
1209 }
1210 Ok(())
1211 }
1212}
1213impl ::micropb::MessageEncode for CtrlMsg_Resp_GetStatus {
1214 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1215 let mut max_size = 0;
1216 if let ::core::option::Option::Some(size) =
1217 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1218 {
1219 max_size += size;
1220 } else {
1221 break 'msg (::core::option::Option::<usize>::None);
1222 };
1223 ::core::option::Option::Some(max_size)
1224 };
1225 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1226 &self,
1227 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1228 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1229 use ::micropb::{FieldEncode, PbMap};
1230 {
1231 let val_ref = &self.r#resp;
1232 if *val_ref != 0 {
1233 encoder.encode_varint32(8u32)?;
1234 encoder.encode_int32(*val_ref as _)?;
1235 }
1236 }
1237 Ok(())
1238 }
1239 fn compute_size(&self) -> usize {
1240 use ::micropb::{FieldEncode, PbMap};
1241 let mut size = 0;
1242 {
1243 let val_ref = &self.r#resp;
1244 if *val_ref != 0 {
1245 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1246 }
1247 }
1248 size
1249 }
1250}
1251#[derive(Debug, Default, PartialEq, Clone)]
96#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1252#[cfg_attr(feature = "defmt", derive(defmt::Format))]
97pub(crate) struct CtrlMsgRespSetMacAddress { 1253pub struct CtrlMsg_Req_SetMacAddress {
98 #[noproto(tag = "1")] 1254 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
99 pub resp: u32, 1255 pub r#mode: i32,
100} 1256}
101 1257impl CtrlMsg_Req_SetMacAddress {
102#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1258 ///Return a reference to `mac`
1259 #[inline]
1260 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
1261 &self.r#mac
1262 }
1263 ///Return a mutable reference to `mac`
1264 #[inline]
1265 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
1266 &mut self.r#mac
1267 }
1268 ///Set the value of `mac`
1269 #[inline]
1270 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
1271 self.r#mac = value.into();
1272 self
1273 }
1274 ///Builder method that sets the value of `mac`. Useful for initializing the message.
1275 #[inline]
1276 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
1277 self.r#mac = value.into();
1278 self
1279 }
1280 ///Return a reference to `mode`
1281 #[inline]
1282 pub fn r#mode(&self) -> &i32 {
1283 &self.r#mode
1284 }
1285 ///Return a mutable reference to `mode`
1286 #[inline]
1287 pub fn mut_mode(&mut self) -> &mut i32 {
1288 &mut self.r#mode
1289 }
1290 ///Set the value of `mode`
1291 #[inline]
1292 pub fn set_mode(&mut self, value: i32) -> &mut Self {
1293 self.r#mode = value.into();
1294 self
1295 }
1296 ///Builder method that sets the value of `mode`. Useful for initializing the message.
1297 #[inline]
1298 pub fn init_mode(mut self, value: i32) -> Self {
1299 self.r#mode = value.into();
1300 self
1301 }
1302}
1303impl ::micropb::MessageDecode for CtrlMsg_Req_SetMacAddress {
1304 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1305 &mut self,
1306 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1307 len: usize,
1308 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1309 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1310 let before = decoder.bytes_read();
1311 while decoder.bytes_read() - before < len {
1312 let tag = decoder.decode_tag()?;
1313 match tag.field_num() {
1314 0 => return Err(::micropb::DecodeError::ZeroField),
1315 1u32 => {
1316 let mut_ref = &mut self.r#mac;
1317 {
1318 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
1319 };
1320 }
1321 2u32 => {
1322 let mut_ref = &mut self.r#mode;
1323 {
1324 let val = decoder.decode_int32()?;
1325 let val_ref = &val;
1326 if *val_ref != 0 {
1327 *mut_ref = val as _;
1328 }
1329 };
1330 }
1331 _ => {
1332 decoder.skip_wire_value(tag.wire_type())?;
1333 }
1334 }
1335 }
1336 Ok(())
1337 }
1338}
1339impl ::micropb::MessageEncode for CtrlMsg_Req_SetMacAddress {
1340 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1341 let mut max_size = 0;
1342 if let ::core::option::Option::Some(size) =
1343 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
1344 {
1345 max_size += size;
1346 } else {
1347 break 'msg (::core::option::Option::<usize>::None);
1348 };
1349 if let ::core::option::Option::Some(size) =
1350 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1351 {
1352 max_size += size;
1353 } else {
1354 break 'msg (::core::option::Option::<usize>::None);
1355 };
1356 ::core::option::Option::Some(max_size)
1357 };
1358 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1359 &self,
1360 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1361 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1362 use ::micropb::{FieldEncode, PbMap};
1363 {
1364 let val_ref = &self.r#mac;
1365 if !val_ref.is_empty() {
1366 encoder.encode_varint32(10u32)?;
1367 encoder.encode_bytes(val_ref)?;
1368 }
1369 }
1370 {
1371 let val_ref = &self.r#mode;
1372 if *val_ref != 0 {
1373 encoder.encode_varint32(16u32)?;
1374 encoder.encode_int32(*val_ref as _)?;
1375 }
1376 }
1377 Ok(())
1378 }
1379 fn compute_size(&self) -> usize {
1380 use ::micropb::{FieldEncode, PbMap};
1381 let mut size = 0;
1382 {
1383 let val_ref = &self.r#mac;
1384 if !val_ref.is_empty() {
1385 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
1386 }
1387 }
1388 {
1389 let val_ref = &self.r#mode;
1390 if *val_ref != 0 {
1391 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1392 }
1393 }
1394 size
1395 }
1396}
1397#[derive(Debug, Default, PartialEq, Clone)]
103#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1398#[cfg_attr(feature = "defmt", derive(defmt::Format))]
104pub(crate) struct CtrlMsgReqGetApConfig {} 1399pub struct CtrlMsg_Resp_SetMacAddress {
105 1400 pub r#resp: i32,
106#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub(crate) struct CtrlMsgRespGetApConfig {
109 #[noproto(tag = "1")]
110 pub ssid: String<32>,
111 #[noproto(tag = "2")]
112 pub bssid: String<32>,
113 #[noproto(tag = "3")]
114 pub rssi: u32,
115 #[noproto(tag = "4")]
116 pub chnl: u32,
117 #[noproto(tag = "5")]
118 pub sec_prot: CtrlWifiSecProt,
119 #[noproto(tag = "6")]
120 pub resp: u32,
121} 1401}
122 1402impl CtrlMsg_Resp_SetMacAddress {
123#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1403 ///Return a reference to `resp`
124#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1404 #[inline]
125pub(crate) struct CtrlMsgReqConnectAp { 1405 pub fn r#resp(&self) -> &i32 {
126 #[noproto(tag = "1")] 1406 &self.r#resp
127 pub ssid: String<32>, 1407 }
128 #[noproto(tag = "2")] 1408 ///Return a mutable reference to `resp`
129 pub pwd: String<32>, 1409 #[inline]
130 #[noproto(tag = "3")] 1410 pub fn mut_resp(&mut self) -> &mut i32 {
131 pub bssid: String<32>, 1411 &mut self.r#resp
132 #[noproto(tag = "4")] 1412 }
133 pub is_wpa3_supported: bool, 1413 ///Set the value of `resp`
134 #[noproto(tag = "5")] 1414 #[inline]
135 pub listen_interval: u32, 1415 pub fn set_resp(&mut self, value: i32) -> &mut Self {
1416 self.r#resp = value.into();
1417 self
1418 }
1419 ///Builder method that sets the value of `resp`. Useful for initializing the message.
1420 #[inline]
1421 pub fn init_resp(mut self, value: i32) -> Self {
1422 self.r#resp = value.into();
1423 self
1424 }
136} 1425}
137 1426impl ::micropb::MessageDecode for CtrlMsg_Resp_SetMacAddress {
138#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1427 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1428 &mut self,
1429 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1430 len: usize,
1431 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1432 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1433 let before = decoder.bytes_read();
1434 while decoder.bytes_read() - before < len {
1435 let tag = decoder.decode_tag()?;
1436 match tag.field_num() {
1437 0 => return Err(::micropb::DecodeError::ZeroField),
1438 1u32 => {
1439 let mut_ref = &mut self.r#resp;
1440 {
1441 let val = decoder.decode_int32()?;
1442 let val_ref = &val;
1443 if *val_ref != 0 {
1444 *mut_ref = val as _;
1445 }
1446 };
1447 }
1448 _ => {
1449 decoder.skip_wire_value(tag.wire_type())?;
1450 }
1451 }
1452 }
1453 Ok(())
1454 }
1455}
1456impl ::micropb::MessageEncode for CtrlMsg_Resp_SetMacAddress {
1457 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1458 let mut max_size = 0;
1459 if let ::core::option::Option::Some(size) =
1460 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1461 {
1462 max_size += size;
1463 } else {
1464 break 'msg (::core::option::Option::<usize>::None);
1465 };
1466 ::core::option::Option::Some(max_size)
1467 };
1468 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1469 &self,
1470 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1471 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1472 use ::micropb::{FieldEncode, PbMap};
1473 {
1474 let val_ref = &self.r#resp;
1475 if *val_ref != 0 {
1476 encoder.encode_varint32(8u32)?;
1477 encoder.encode_int32(*val_ref as _)?;
1478 }
1479 }
1480 Ok(())
1481 }
1482 fn compute_size(&self) -> usize {
1483 use ::micropb::{FieldEncode, PbMap};
1484 let mut size = 0;
1485 {
1486 let val_ref = &self.r#resp;
1487 if *val_ref != 0 {
1488 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1489 }
1490 }
1491 size
1492 }
1493}
1494#[derive(Debug, Default, PartialEq, Clone)]
139#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1495#[cfg_attr(feature = "defmt", derive(defmt::Format))]
140pub(crate) struct CtrlMsgRespConnectAp { 1496pub struct CtrlMsg_Req_GetAPConfig {}
141 #[noproto(tag = "1")] 1497impl CtrlMsg_Req_GetAPConfig {}
142 pub resp: u32, 1498impl ::micropb::MessageDecode for CtrlMsg_Req_GetAPConfig {
143 #[noproto(tag = "2")] 1499 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
144 pub mac: String<32>, 1500 &mut self,
1501 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1502 len: usize,
1503 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1504 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1505 let before = decoder.bytes_read();
1506 while decoder.bytes_read() - before < len {
1507 let tag = decoder.decode_tag()?;
1508 match tag.field_num() {
1509 0 => return Err(::micropb::DecodeError::ZeroField),
1510 _ => {
1511 decoder.skip_wire_value(tag.wire_type())?;
1512 }
1513 }
1514 }
1515 Ok(())
1516 }
145} 1517}
146 1518impl ::micropb::MessageEncode for CtrlMsg_Req_GetAPConfig {
147#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1519 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1520 let mut max_size = 0;
1521 ::core::option::Option::Some(max_size)
1522 };
1523 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1524 &self,
1525 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1526 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1527 use ::micropb::{FieldEncode, PbMap};
1528 Ok(())
1529 }
1530 fn compute_size(&self) -> usize {
1531 use ::micropb::{FieldEncode, PbMap};
1532 let mut size = 0;
1533 size
1534 }
1535}
1536#[derive(Debug, Default, PartialEq, Clone)]
148#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1537#[cfg_attr(feature = "defmt", derive(defmt::Format))]
149pub(crate) struct CtrlMsgReqGetSoftApConfig {} 1538pub struct CtrlMsg_Resp_GetAPConfig {
150 1539 pub r#ssid: ::micropb::heapless::Vec<u8, 32>,
151#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1540 pub r#bssid: ::micropb::heapless::Vec<u8, 32>,
152#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1541 pub r#rssi: i32,
153pub(crate) struct CtrlMsgRespGetSoftApConfig { 1542 pub r#chnl: i32,
154 #[noproto(tag = "1")] 1543 pub r#sec_prot: Ctrl_WifiSecProt,
155 pub ssid: String<32>, 1544 pub r#resp: i32,
156 #[noproto(tag = "2")] 1545 pub r#band_mode: i32,
157 pub pwd: String<32>,
158 #[noproto(tag = "3")]
159 pub chnl: u32,
160 #[noproto(tag = "4")]
161 pub sec_prot: CtrlWifiSecProt,
162 #[noproto(tag = "5")]
163 pub max_conn: u32,
164 #[noproto(tag = "6")]
165 pub ssid_hidden: bool,
166 #[noproto(tag = "7")]
167 pub bw: u32,
168 #[noproto(tag = "8")]
169 pub resp: u32,
170} 1546}
171 1547impl CtrlMsg_Resp_GetAPConfig {
172#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1548 ///Return a reference to `ssid`
173#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1549 #[inline]
174pub(crate) struct CtrlMsgReqStartSoftAp { 1550 pub fn r#ssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
175 #[noproto(tag = "1")] 1551 &self.r#ssid
176 pub ssid: String<32>, 1552 }
177 #[noproto(tag = "2")] 1553 ///Return a mutable reference to `ssid`
178 pub pwd: String<32>, 1554 #[inline]
179 #[noproto(tag = "3")] 1555 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
180 pub chnl: u32, 1556 &mut self.r#ssid
181 #[noproto(tag = "4")] 1557 }
182 pub sec_prot: CtrlWifiSecProt, 1558 ///Set the value of `ssid`
183 #[noproto(tag = "5")] 1559 #[inline]
184 pub max_conn: u32, 1560 pub fn set_ssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
185 #[noproto(tag = "6")] 1561 self.r#ssid = value.into();
186 pub ssid_hidden: bool, 1562 self
187 #[noproto(tag = "7")] 1563 }
188 pub bw: u32, 1564 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
1565 #[inline]
1566 pub fn init_ssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
1567 self.r#ssid = value.into();
1568 self
1569 }
1570 ///Return a reference to `bssid`
1571 #[inline]
1572 pub fn r#bssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
1573 &self.r#bssid
1574 }
1575 ///Return a mutable reference to `bssid`
1576 #[inline]
1577 pub fn mut_bssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
1578 &mut self.r#bssid
1579 }
1580 ///Set the value of `bssid`
1581 #[inline]
1582 pub fn set_bssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
1583 self.r#bssid = value.into();
1584 self
1585 }
1586 ///Builder method that sets the value of `bssid`. Useful for initializing the message.
1587 #[inline]
1588 pub fn init_bssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
1589 self.r#bssid = value.into();
1590 self
1591 }
1592 ///Return a reference to `rssi`
1593 #[inline]
1594 pub fn r#rssi(&self) -> &i32 {
1595 &self.r#rssi
1596 }
1597 ///Return a mutable reference to `rssi`
1598 #[inline]
1599 pub fn mut_rssi(&mut self) -> &mut i32 {
1600 &mut self.r#rssi
1601 }
1602 ///Set the value of `rssi`
1603 #[inline]
1604 pub fn set_rssi(&mut self, value: i32) -> &mut Self {
1605 self.r#rssi = value.into();
1606 self
1607 }
1608 ///Builder method that sets the value of `rssi`. Useful for initializing the message.
1609 #[inline]
1610 pub fn init_rssi(mut self, value: i32) -> Self {
1611 self.r#rssi = value.into();
1612 self
1613 }
1614 ///Return a reference to `chnl`
1615 #[inline]
1616 pub fn r#chnl(&self) -> &i32 {
1617 &self.r#chnl
1618 }
1619 ///Return a mutable reference to `chnl`
1620 #[inline]
1621 pub fn mut_chnl(&mut self) -> &mut i32 {
1622 &mut self.r#chnl
1623 }
1624 ///Set the value of `chnl`
1625 #[inline]
1626 pub fn set_chnl(&mut self, value: i32) -> &mut Self {
1627 self.r#chnl = value.into();
1628 self
1629 }
1630 ///Builder method that sets the value of `chnl`. Useful for initializing the message.
1631 #[inline]
1632 pub fn init_chnl(mut self, value: i32) -> Self {
1633 self.r#chnl = value.into();
1634 self
1635 }
1636 ///Return a reference to `sec_prot`
1637 #[inline]
1638 pub fn r#sec_prot(&self) -> &Ctrl_WifiSecProt {
1639 &self.r#sec_prot
1640 }
1641 ///Return a mutable reference to `sec_prot`
1642 #[inline]
1643 pub fn mut_sec_prot(&mut self) -> &mut Ctrl_WifiSecProt {
1644 &mut self.r#sec_prot
1645 }
1646 ///Set the value of `sec_prot`
1647 #[inline]
1648 pub fn set_sec_prot(&mut self, value: Ctrl_WifiSecProt) -> &mut Self {
1649 self.r#sec_prot = value.into();
1650 self
1651 }
1652 ///Builder method that sets the value of `sec_prot`. Useful for initializing the message.
1653 #[inline]
1654 pub fn init_sec_prot(mut self, value: Ctrl_WifiSecProt) -> Self {
1655 self.r#sec_prot = value.into();
1656 self
1657 }
1658 ///Return a reference to `resp`
1659 #[inline]
1660 pub fn r#resp(&self) -> &i32 {
1661 &self.r#resp
1662 }
1663 ///Return a mutable reference to `resp`
1664 #[inline]
1665 pub fn mut_resp(&mut self) -> &mut i32 {
1666 &mut self.r#resp
1667 }
1668 ///Set the value of `resp`
1669 #[inline]
1670 pub fn set_resp(&mut self, value: i32) -> &mut Self {
1671 self.r#resp = value.into();
1672 self
1673 }
1674 ///Builder method that sets the value of `resp`. Useful for initializing the message.
1675 #[inline]
1676 pub fn init_resp(mut self, value: i32) -> Self {
1677 self.r#resp = value.into();
1678 self
1679 }
1680 ///Return a reference to `band_mode`
1681 #[inline]
1682 pub fn r#band_mode(&self) -> &i32 {
1683 &self.r#band_mode
1684 }
1685 ///Return a mutable reference to `band_mode`
1686 #[inline]
1687 pub fn mut_band_mode(&mut self) -> &mut i32 {
1688 &mut self.r#band_mode
1689 }
1690 ///Set the value of `band_mode`
1691 #[inline]
1692 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
1693 self.r#band_mode = value.into();
1694 self
1695 }
1696 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
1697 #[inline]
1698 pub fn init_band_mode(mut self, value: i32) -> Self {
1699 self.r#band_mode = value.into();
1700 self
1701 }
189} 1702}
190 1703impl ::micropb::MessageDecode for CtrlMsg_Resp_GetAPConfig {
191#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1704 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
1705 &mut self,
1706 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
1707 len: usize,
1708 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
1709 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
1710 let before = decoder.bytes_read();
1711 while decoder.bytes_read() - before < len {
1712 let tag = decoder.decode_tag()?;
1713 match tag.field_num() {
1714 0 => return Err(::micropb::DecodeError::ZeroField),
1715 1u32 => {
1716 let mut_ref = &mut self.r#ssid;
1717 {
1718 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
1719 };
1720 }
1721 2u32 => {
1722 let mut_ref = &mut self.r#bssid;
1723 {
1724 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
1725 };
1726 }
1727 3u32 => {
1728 let mut_ref = &mut self.r#rssi;
1729 {
1730 let val = decoder.decode_int32()?;
1731 let val_ref = &val;
1732 if *val_ref != 0 {
1733 *mut_ref = val as _;
1734 }
1735 };
1736 }
1737 4u32 => {
1738 let mut_ref = &mut self.r#chnl;
1739 {
1740 let val = decoder.decode_int32()?;
1741 let val_ref = &val;
1742 if *val_ref != 0 {
1743 *mut_ref = val as _;
1744 }
1745 };
1746 }
1747 5u32 => {
1748 let mut_ref = &mut self.r#sec_prot;
1749 {
1750 let val = decoder.decode_int32().map(|n| Ctrl_WifiSecProt(n as _))?;
1751 let val_ref = &val;
1752 if val_ref.0 != 0 {
1753 *mut_ref = val as _;
1754 }
1755 };
1756 }
1757 6u32 => {
1758 let mut_ref = &mut self.r#resp;
1759 {
1760 let val = decoder.decode_int32()?;
1761 let val_ref = &val;
1762 if *val_ref != 0 {
1763 *mut_ref = val as _;
1764 }
1765 };
1766 }
1767 7u32 => {
1768 let mut_ref = &mut self.r#band_mode;
1769 {
1770 let val = decoder.decode_int32()?;
1771 let val_ref = &val;
1772 if *val_ref != 0 {
1773 *mut_ref = val as _;
1774 }
1775 };
1776 }
1777 _ => {
1778 decoder.skip_wire_value(tag.wire_type())?;
1779 }
1780 }
1781 }
1782 Ok(())
1783 }
1784}
1785impl ::micropb::MessageEncode for CtrlMsg_Resp_GetAPConfig {
1786 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
1787 let mut max_size = 0;
1788 if let ::core::option::Option::Some(size) =
1789 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
1790 {
1791 max_size += size;
1792 } else {
1793 break 'msg (::core::option::Option::<usize>::None);
1794 };
1795 if let ::core::option::Option::Some(size) =
1796 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
1797 {
1798 max_size += size;
1799 } else {
1800 break 'msg (::core::option::Option::<usize>::None);
1801 };
1802 if let ::core::option::Option::Some(size) =
1803 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1804 {
1805 max_size += size;
1806 } else {
1807 break 'msg (::core::option::Option::<usize>::None);
1808 };
1809 if let ::core::option::Option::Some(size) =
1810 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1811 {
1812 max_size += size;
1813 } else {
1814 break 'msg (::core::option::Option::<usize>::None);
1815 };
1816 if let ::core::option::Option::Some(size) =
1817 ::micropb::const_map!(::core::option::Option::Some(Ctrl_WifiSecProt::_MAX_SIZE), |size| size
1818 + 1usize)
1819 {
1820 max_size += size;
1821 } else {
1822 break 'msg (::core::option::Option::<usize>::None);
1823 };
1824 if let ::core::option::Option::Some(size) =
1825 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1826 {
1827 max_size += size;
1828 } else {
1829 break 'msg (::core::option::Option::<usize>::None);
1830 };
1831 if let ::core::option::Option::Some(size) =
1832 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
1833 {
1834 max_size += size;
1835 } else {
1836 break 'msg (::core::option::Option::<usize>::None);
1837 };
1838 ::core::option::Option::Some(max_size)
1839 };
1840 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
1841 &self,
1842 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
1843 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
1844 use ::micropb::{FieldEncode, PbMap};
1845 {
1846 let val_ref = &self.r#ssid;
1847 if !val_ref.is_empty() {
1848 encoder.encode_varint32(10u32)?;
1849 encoder.encode_bytes(val_ref)?;
1850 }
1851 }
1852 {
1853 let val_ref = &self.r#bssid;
1854 if !val_ref.is_empty() {
1855 encoder.encode_varint32(18u32)?;
1856 encoder.encode_bytes(val_ref)?;
1857 }
1858 }
1859 {
1860 let val_ref = &self.r#rssi;
1861 if *val_ref != 0 {
1862 encoder.encode_varint32(24u32)?;
1863 encoder.encode_int32(*val_ref as _)?;
1864 }
1865 }
1866 {
1867 let val_ref = &self.r#chnl;
1868 if *val_ref != 0 {
1869 encoder.encode_varint32(32u32)?;
1870 encoder.encode_int32(*val_ref as _)?;
1871 }
1872 }
1873 {
1874 let val_ref = &self.r#sec_prot;
1875 if val_ref.0 != 0 {
1876 encoder.encode_varint32(40u32)?;
1877 encoder.encode_int32(val_ref.0 as _)?;
1878 }
1879 }
1880 {
1881 let val_ref = &self.r#resp;
1882 if *val_ref != 0 {
1883 encoder.encode_varint32(48u32)?;
1884 encoder.encode_int32(*val_ref as _)?;
1885 }
1886 }
1887 {
1888 let val_ref = &self.r#band_mode;
1889 if *val_ref != 0 {
1890 encoder.encode_varint32(56u32)?;
1891 encoder.encode_int32(*val_ref as _)?;
1892 }
1893 }
1894 Ok(())
1895 }
1896 fn compute_size(&self) -> usize {
1897 use ::micropb::{FieldEncode, PbMap};
1898 let mut size = 0;
1899 {
1900 let val_ref = &self.r#ssid;
1901 if !val_ref.is_empty() {
1902 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
1903 }
1904 }
1905 {
1906 let val_ref = &self.r#bssid;
1907 if !val_ref.is_empty() {
1908 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
1909 }
1910 }
1911 {
1912 let val_ref = &self.r#rssi;
1913 if *val_ref != 0 {
1914 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1915 }
1916 }
1917 {
1918 let val_ref = &self.r#chnl;
1919 if *val_ref != 0 {
1920 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1921 }
1922 }
1923 {
1924 let val_ref = &self.r#sec_prot;
1925 if val_ref.0 != 0 {
1926 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
1927 }
1928 }
1929 {
1930 let val_ref = &self.r#resp;
1931 if *val_ref != 0 {
1932 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1933 }
1934 }
1935 {
1936 let val_ref = &self.r#band_mode;
1937 if *val_ref != 0 {
1938 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
1939 }
1940 }
1941 size
1942 }
1943}
1944#[derive(Debug, Default, PartialEq, Clone)]
192#[cfg_attr(feature = "defmt", derive(defmt::Format))] 1945#[cfg_attr(feature = "defmt", derive(defmt::Format))]
193pub(crate) struct CtrlMsgRespStartSoftAp { 1946pub struct CtrlMsg_Req_ConnectAP {
194 #[noproto(tag = "1")] 1947 pub r#ssid: ::micropb::heapless::String<32>,
195 pub resp: u32, 1948 pub r#pwd: ::micropb::heapless::String<32>,
196 #[noproto(tag = "2")] 1949 pub r#bssid: ::micropb::heapless::String<32>,
197 pub mac: String<32>, 1950 pub r#is_wpa3_supported: bool,
1951 pub r#listen_interval: i32,
1952 pub r#band_mode: i32,
198} 1953}
199 1954impl CtrlMsg_Req_ConnectAP {
200#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 1955 ///Return a reference to `ssid`
1956 #[inline]
1957 pub fn r#ssid(&self) -> &::micropb::heapless::String<32> {
1958 &self.r#ssid
1959 }
1960 ///Return a mutable reference to `ssid`
1961 #[inline]
1962 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::String<32> {
1963 &mut self.r#ssid
1964 }
1965 ///Set the value of `ssid`
1966 #[inline]
1967 pub fn set_ssid(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
1968 self.r#ssid = value.into();
1969 self
1970 }
1971 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
1972 #[inline]
1973 pub fn init_ssid(mut self, value: ::micropb::heapless::String<32>) -> Self {
1974 self.r#ssid = value.into();
1975 self
1976 }
1977 ///Return a reference to `pwd`
1978 #[inline]
1979 pub fn r#pwd(&self) -> &::micropb::heapless::String<32> {
1980 &self.r#pwd
1981 }
1982 ///Return a mutable reference to `pwd`
1983 #[inline]
1984 pub fn mut_pwd(&mut self) -> &mut ::micropb::heapless::String<32> {
1985 &mut self.r#pwd
1986 }
1987 ///Set the value of `pwd`
1988 #[inline]
1989 pub fn set_pwd(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
1990 self.r#pwd = value.into();
1991 self
1992 }
1993 ///Builder method that sets the value of `pwd`. Useful for initializing the message.
1994 #[inline]
1995 pub fn init_pwd(mut self, value: ::micropb::heapless::String<32>) -> Self {
1996 self.r#pwd = value.into();
1997 self
1998 }
1999 ///Return a reference to `bssid`
2000 #[inline]
2001 pub fn r#bssid(&self) -> &::micropb::heapless::String<32> {
2002 &self.r#bssid
2003 }
2004 ///Return a mutable reference to `bssid`
2005 #[inline]
2006 pub fn mut_bssid(&mut self) -> &mut ::micropb::heapless::String<32> {
2007 &mut self.r#bssid
2008 }
2009 ///Set the value of `bssid`
2010 #[inline]
2011 pub fn set_bssid(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
2012 self.r#bssid = value.into();
2013 self
2014 }
2015 ///Builder method that sets the value of `bssid`. Useful for initializing the message.
2016 #[inline]
2017 pub fn init_bssid(mut self, value: ::micropb::heapless::String<32>) -> Self {
2018 self.r#bssid = value.into();
2019 self
2020 }
2021 ///Return a reference to `is_wpa3_supported`
2022 #[inline]
2023 pub fn r#is_wpa3_supported(&self) -> &bool {
2024 &self.r#is_wpa3_supported
2025 }
2026 ///Return a mutable reference to `is_wpa3_supported`
2027 #[inline]
2028 pub fn mut_is_wpa3_supported(&mut self) -> &mut bool {
2029 &mut self.r#is_wpa3_supported
2030 }
2031 ///Set the value of `is_wpa3_supported`
2032 #[inline]
2033 pub fn set_is_wpa3_supported(&mut self, value: bool) -> &mut Self {
2034 self.r#is_wpa3_supported = value.into();
2035 self
2036 }
2037 ///Builder method that sets the value of `is_wpa3_supported`. Useful for initializing the message.
2038 #[inline]
2039 pub fn init_is_wpa3_supported(mut self, value: bool) -> Self {
2040 self.r#is_wpa3_supported = value.into();
2041 self
2042 }
2043 ///Return a reference to `listen_interval`
2044 #[inline]
2045 pub fn r#listen_interval(&self) -> &i32 {
2046 &self.r#listen_interval
2047 }
2048 ///Return a mutable reference to `listen_interval`
2049 #[inline]
2050 pub fn mut_listen_interval(&mut self) -> &mut i32 {
2051 &mut self.r#listen_interval
2052 }
2053 ///Set the value of `listen_interval`
2054 #[inline]
2055 pub fn set_listen_interval(&mut self, value: i32) -> &mut Self {
2056 self.r#listen_interval = value.into();
2057 self
2058 }
2059 ///Builder method that sets the value of `listen_interval`. Useful for initializing the message.
2060 #[inline]
2061 pub fn init_listen_interval(mut self, value: i32) -> Self {
2062 self.r#listen_interval = value.into();
2063 self
2064 }
2065 ///Return a reference to `band_mode`
2066 #[inline]
2067 pub fn r#band_mode(&self) -> &i32 {
2068 &self.r#band_mode
2069 }
2070 ///Return a mutable reference to `band_mode`
2071 #[inline]
2072 pub fn mut_band_mode(&mut self) -> &mut i32 {
2073 &mut self.r#band_mode
2074 }
2075 ///Set the value of `band_mode`
2076 #[inline]
2077 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
2078 self.r#band_mode = value.into();
2079 self
2080 }
2081 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
2082 #[inline]
2083 pub fn init_band_mode(mut self, value: i32) -> Self {
2084 self.r#band_mode = value.into();
2085 self
2086 }
2087}
2088impl ::micropb::MessageDecode for CtrlMsg_Req_ConnectAP {
2089 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
2090 &mut self,
2091 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
2092 len: usize,
2093 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
2094 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
2095 let before = decoder.bytes_read();
2096 while decoder.bytes_read() - before < len {
2097 let tag = decoder.decode_tag()?;
2098 match tag.field_num() {
2099 0 => return Err(::micropb::DecodeError::ZeroField),
2100 1u32 => {
2101 let mut_ref = &mut self.r#ssid;
2102 {
2103 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
2104 };
2105 }
2106 2u32 => {
2107 let mut_ref = &mut self.r#pwd;
2108 {
2109 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
2110 };
2111 }
2112 3u32 => {
2113 let mut_ref = &mut self.r#bssid;
2114 {
2115 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
2116 };
2117 }
2118 4u32 => {
2119 let mut_ref = &mut self.r#is_wpa3_supported;
2120 {
2121 let val = decoder.decode_bool()?;
2122 let val_ref = &val;
2123 if *val_ref {
2124 *mut_ref = val as _;
2125 }
2126 };
2127 }
2128 5u32 => {
2129 let mut_ref = &mut self.r#listen_interval;
2130 {
2131 let val = decoder.decode_int32()?;
2132 let val_ref = &val;
2133 if *val_ref != 0 {
2134 *mut_ref = val as _;
2135 }
2136 };
2137 }
2138 6u32 => {
2139 let mut_ref = &mut self.r#band_mode;
2140 {
2141 let val = decoder.decode_int32()?;
2142 let val_ref = &val;
2143 if *val_ref != 0 {
2144 *mut_ref = val as _;
2145 }
2146 };
2147 }
2148 _ => {
2149 decoder.skip_wire_value(tag.wire_type())?;
2150 }
2151 }
2152 }
2153 Ok(())
2154 }
2155}
2156impl ::micropb::MessageEncode for CtrlMsg_Req_ConnectAP {
2157 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
2158 let mut max_size = 0;
2159 if let ::core::option::Option::Some(size) =
2160 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2161 {
2162 max_size += size;
2163 } else {
2164 break 'msg (::core::option::Option::<usize>::None);
2165 };
2166 if let ::core::option::Option::Some(size) =
2167 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2168 {
2169 max_size += size;
2170 } else {
2171 break 'msg (::core::option::Option::<usize>::None);
2172 };
2173 if let ::core::option::Option::Some(size) =
2174 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2175 {
2176 max_size += size;
2177 } else {
2178 break 'msg (::core::option::Option::<usize>::None);
2179 };
2180 if let ::core::option::Option::Some(size) =
2181 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
2182 {
2183 max_size += size;
2184 } else {
2185 break 'msg (::core::option::Option::<usize>::None);
2186 };
2187 if let ::core::option::Option::Some(size) =
2188 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2189 {
2190 max_size += size;
2191 } else {
2192 break 'msg (::core::option::Option::<usize>::None);
2193 };
2194 if let ::core::option::Option::Some(size) =
2195 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2196 {
2197 max_size += size;
2198 } else {
2199 break 'msg (::core::option::Option::<usize>::None);
2200 };
2201 ::core::option::Option::Some(max_size)
2202 };
2203 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
2204 &self,
2205 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
2206 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
2207 use ::micropb::{FieldEncode, PbMap};
2208 {
2209 let val_ref = &self.r#ssid;
2210 if !val_ref.is_empty() {
2211 encoder.encode_varint32(10u32)?;
2212 encoder.encode_string(val_ref)?;
2213 }
2214 }
2215 {
2216 let val_ref = &self.r#pwd;
2217 if !val_ref.is_empty() {
2218 encoder.encode_varint32(18u32)?;
2219 encoder.encode_string(val_ref)?;
2220 }
2221 }
2222 {
2223 let val_ref = &self.r#bssid;
2224 if !val_ref.is_empty() {
2225 encoder.encode_varint32(26u32)?;
2226 encoder.encode_string(val_ref)?;
2227 }
2228 }
2229 {
2230 let val_ref = &self.r#is_wpa3_supported;
2231 if *val_ref {
2232 encoder.encode_varint32(32u32)?;
2233 encoder.encode_bool(*val_ref)?;
2234 }
2235 }
2236 {
2237 let val_ref = &self.r#listen_interval;
2238 if *val_ref != 0 {
2239 encoder.encode_varint32(40u32)?;
2240 encoder.encode_int32(*val_ref as _)?;
2241 }
2242 }
2243 {
2244 let val_ref = &self.r#band_mode;
2245 if *val_ref != 0 {
2246 encoder.encode_varint32(48u32)?;
2247 encoder.encode_int32(*val_ref as _)?;
2248 }
2249 }
2250 Ok(())
2251 }
2252 fn compute_size(&self) -> usize {
2253 use ::micropb::{FieldEncode, PbMap};
2254 let mut size = 0;
2255 {
2256 let val_ref = &self.r#ssid;
2257 if !val_ref.is_empty() {
2258 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
2259 }
2260 }
2261 {
2262 let val_ref = &self.r#pwd;
2263 if !val_ref.is_empty() {
2264 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
2265 }
2266 }
2267 {
2268 let val_ref = &self.r#bssid;
2269 if !val_ref.is_empty() {
2270 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
2271 }
2272 }
2273 {
2274 let val_ref = &self.r#is_wpa3_supported;
2275 if *val_ref {
2276 size += 1usize + 1;
2277 }
2278 }
2279 {
2280 let val_ref = &self.r#listen_interval;
2281 if *val_ref != 0 {
2282 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
2283 }
2284 }
2285 {
2286 let val_ref = &self.r#band_mode;
2287 if *val_ref != 0 {
2288 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
2289 }
2290 }
2291 size
2292 }
2293}
2294#[derive(Debug, Default, PartialEq, Clone)]
201#[cfg_attr(feature = "defmt", derive(defmt::Format))] 2295#[cfg_attr(feature = "defmt", derive(defmt::Format))]
202pub(crate) struct CtrlMsgReqScanResult {} 2296pub struct CtrlMsg_Resp_ConnectAP {
203 2297 pub r#resp: i32,
204#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 2298 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
2299 pub r#band_mode: i32,
2300}
2301impl CtrlMsg_Resp_ConnectAP {
2302 ///Return a reference to `resp`
2303 #[inline]
2304 pub fn r#resp(&self) -> &i32 {
2305 &self.r#resp
2306 }
2307 ///Return a mutable reference to `resp`
2308 #[inline]
2309 pub fn mut_resp(&mut self) -> &mut i32 {
2310 &mut self.r#resp
2311 }
2312 ///Set the value of `resp`
2313 #[inline]
2314 pub fn set_resp(&mut self, value: i32) -> &mut Self {
2315 self.r#resp = value.into();
2316 self
2317 }
2318 ///Builder method that sets the value of `resp`. Useful for initializing the message.
2319 #[inline]
2320 pub fn init_resp(mut self, value: i32) -> Self {
2321 self.r#resp = value.into();
2322 self
2323 }
2324 ///Return a reference to `mac`
2325 #[inline]
2326 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
2327 &self.r#mac
2328 }
2329 ///Return a mutable reference to `mac`
2330 #[inline]
2331 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
2332 &mut self.r#mac
2333 }
2334 ///Set the value of `mac`
2335 #[inline]
2336 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
2337 self.r#mac = value.into();
2338 self
2339 }
2340 ///Builder method that sets the value of `mac`. Useful for initializing the message.
2341 #[inline]
2342 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
2343 self.r#mac = value.into();
2344 self
2345 }
2346 ///Return a reference to `band_mode`
2347 #[inline]
2348 pub fn r#band_mode(&self) -> &i32 {
2349 &self.r#band_mode
2350 }
2351 ///Return a mutable reference to `band_mode`
2352 #[inline]
2353 pub fn mut_band_mode(&mut self) -> &mut i32 {
2354 &mut self.r#band_mode
2355 }
2356 ///Set the value of `band_mode`
2357 #[inline]
2358 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
2359 self.r#band_mode = value.into();
2360 self
2361 }
2362 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
2363 #[inline]
2364 pub fn init_band_mode(mut self, value: i32) -> Self {
2365 self.r#band_mode = value.into();
2366 self
2367 }
2368}
2369impl ::micropb::MessageDecode for CtrlMsg_Resp_ConnectAP {
2370 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
2371 &mut self,
2372 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
2373 len: usize,
2374 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
2375 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
2376 let before = decoder.bytes_read();
2377 while decoder.bytes_read() - before < len {
2378 let tag = decoder.decode_tag()?;
2379 match tag.field_num() {
2380 0 => return Err(::micropb::DecodeError::ZeroField),
2381 1u32 => {
2382 let mut_ref = &mut self.r#resp;
2383 {
2384 let val = decoder.decode_int32()?;
2385 let val_ref = &val;
2386 if *val_ref != 0 {
2387 *mut_ref = val as _;
2388 }
2389 };
2390 }
2391 2u32 => {
2392 let mut_ref = &mut self.r#mac;
2393 {
2394 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
2395 };
2396 }
2397 3u32 => {
2398 let mut_ref = &mut self.r#band_mode;
2399 {
2400 let val = decoder.decode_int32()?;
2401 let val_ref = &val;
2402 if *val_ref != 0 {
2403 *mut_ref = val as _;
2404 }
2405 };
2406 }
2407 _ => {
2408 decoder.skip_wire_value(tag.wire_type())?;
2409 }
2410 }
2411 }
2412 Ok(())
2413 }
2414}
2415impl ::micropb::MessageEncode for CtrlMsg_Resp_ConnectAP {
2416 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
2417 let mut max_size = 0;
2418 if let ::core::option::Option::Some(size) =
2419 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2420 {
2421 max_size += size;
2422 } else {
2423 break 'msg (::core::option::Option::<usize>::None);
2424 };
2425 if let ::core::option::Option::Some(size) =
2426 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2427 {
2428 max_size += size;
2429 } else {
2430 break 'msg (::core::option::Option::<usize>::None);
2431 };
2432 if let ::core::option::Option::Some(size) =
2433 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2434 {
2435 max_size += size;
2436 } else {
2437 break 'msg (::core::option::Option::<usize>::None);
2438 };
2439 ::core::option::Option::Some(max_size)
2440 };
2441 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
2442 &self,
2443 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
2444 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
2445 use ::micropb::{FieldEncode, PbMap};
2446 {
2447 let val_ref = &self.r#resp;
2448 if *val_ref != 0 {
2449 encoder.encode_varint32(8u32)?;
2450 encoder.encode_int32(*val_ref as _)?;
2451 }
2452 }
2453 {
2454 let val_ref = &self.r#mac;
2455 if !val_ref.is_empty() {
2456 encoder.encode_varint32(18u32)?;
2457 encoder.encode_bytes(val_ref)?;
2458 }
2459 }
2460 {
2461 let val_ref = &self.r#band_mode;
2462 if *val_ref != 0 {
2463 encoder.encode_varint32(24u32)?;
2464 encoder.encode_int32(*val_ref as _)?;
2465 }
2466 }
2467 Ok(())
2468 }
2469 fn compute_size(&self) -> usize {
2470 use ::micropb::{FieldEncode, PbMap};
2471 let mut size = 0;
2472 {
2473 let val_ref = &self.r#resp;
2474 if *val_ref != 0 {
2475 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
2476 }
2477 }
2478 {
2479 let val_ref = &self.r#mac;
2480 if !val_ref.is_empty() {
2481 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
2482 }
2483 }
2484 {
2485 let val_ref = &self.r#band_mode;
2486 if *val_ref != 0 {
2487 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
2488 }
2489 }
2490 size
2491 }
2492}
2493#[derive(Debug, Default, PartialEq, Clone)]
205#[cfg_attr(feature = "defmt", derive(defmt::Format))] 2494#[cfg_attr(feature = "defmt", derive(defmt::Format))]
206pub(crate) struct CtrlMsgRespScanResult { 2495pub struct CtrlMsg_Req_GetSoftAPConfig {}
207 #[noproto(tag = "1")] 2496impl CtrlMsg_Req_GetSoftAPConfig {}
208 pub count: u32, 2497impl ::micropb::MessageDecode for CtrlMsg_Req_GetSoftAPConfig {
209 #[noproto(repeated, tag = "2")] 2498 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
210 pub entries: Vec<ScanResult, 16>, 2499 &mut self,
211 #[noproto(tag = "3")] 2500 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
212 pub resp: u32, 2501 len: usize,
2502 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
2503 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
2504 let before = decoder.bytes_read();
2505 while decoder.bytes_read() - before < len {
2506 let tag = decoder.decode_tag()?;
2507 match tag.field_num() {
2508 0 => return Err(::micropb::DecodeError::ZeroField),
2509 _ => {
2510 decoder.skip_wire_value(tag.wire_type())?;
2511 }
2512 }
2513 }
2514 Ok(())
2515 }
213} 2516}
214 2517impl ::micropb::MessageEncode for CtrlMsg_Req_GetSoftAPConfig {
215#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 2518 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
2519 let mut max_size = 0;
2520 ::core::option::Option::Some(max_size)
2521 };
2522 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
2523 &self,
2524 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
2525 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
2526 use ::micropb::{FieldEncode, PbMap};
2527 Ok(())
2528 }
2529 fn compute_size(&self) -> usize {
2530 use ::micropb::{FieldEncode, PbMap};
2531 let mut size = 0;
2532 size
2533 }
2534}
2535#[derive(Debug, Default, PartialEq, Clone)]
216#[cfg_attr(feature = "defmt", derive(defmt::Format))] 2536#[cfg_attr(feature = "defmt", derive(defmt::Format))]
217pub(crate) struct CtrlMsgReqSoftApConnectedSta {} 2537pub struct CtrlMsg_Resp_GetSoftAPConfig {
218 2538 pub r#ssid: ::micropb::heapless::Vec<u8, 32>,
219#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 2539 pub r#pwd: ::micropb::heapless::Vec<u8, 32>,
2540 pub r#chnl: i32,
2541 pub r#sec_prot: Ctrl_WifiSecProt,
2542 pub r#max_conn: i32,
2543 pub r#ssid_hidden: bool,
2544 pub r#bw: i32,
2545 pub r#resp: i32,
2546 pub r#band_mode: i32,
2547}
2548impl CtrlMsg_Resp_GetSoftAPConfig {
2549 ///Return a reference to `ssid`
2550 #[inline]
2551 pub fn r#ssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
2552 &self.r#ssid
2553 }
2554 ///Return a mutable reference to `ssid`
2555 #[inline]
2556 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
2557 &mut self.r#ssid
2558 }
2559 ///Set the value of `ssid`
2560 #[inline]
2561 pub fn set_ssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
2562 self.r#ssid = value.into();
2563 self
2564 }
2565 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
2566 #[inline]
2567 pub fn init_ssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
2568 self.r#ssid = value.into();
2569 self
2570 }
2571 ///Return a reference to `pwd`
2572 #[inline]
2573 pub fn r#pwd(&self) -> &::micropb::heapless::Vec<u8, 32> {
2574 &self.r#pwd
2575 }
2576 ///Return a mutable reference to `pwd`
2577 #[inline]
2578 pub fn mut_pwd(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
2579 &mut self.r#pwd
2580 }
2581 ///Set the value of `pwd`
2582 #[inline]
2583 pub fn set_pwd(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
2584 self.r#pwd = value.into();
2585 self
2586 }
2587 ///Builder method that sets the value of `pwd`. Useful for initializing the message.
2588 #[inline]
2589 pub fn init_pwd(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
2590 self.r#pwd = value.into();
2591 self
2592 }
2593 ///Return a reference to `chnl`
2594 #[inline]
2595 pub fn r#chnl(&self) -> &i32 {
2596 &self.r#chnl
2597 }
2598 ///Return a mutable reference to `chnl`
2599 #[inline]
2600 pub fn mut_chnl(&mut self) -> &mut i32 {
2601 &mut self.r#chnl
2602 }
2603 ///Set the value of `chnl`
2604 #[inline]
2605 pub fn set_chnl(&mut self, value: i32) -> &mut Self {
2606 self.r#chnl = value.into();
2607 self
2608 }
2609 ///Builder method that sets the value of `chnl`. Useful for initializing the message.
2610 #[inline]
2611 pub fn init_chnl(mut self, value: i32) -> Self {
2612 self.r#chnl = value.into();
2613 self
2614 }
2615 ///Return a reference to `sec_prot`
2616 #[inline]
2617 pub fn r#sec_prot(&self) -> &Ctrl_WifiSecProt {
2618 &self.r#sec_prot
2619 }
2620 ///Return a mutable reference to `sec_prot`
2621 #[inline]
2622 pub fn mut_sec_prot(&mut self) -> &mut Ctrl_WifiSecProt {
2623 &mut self.r#sec_prot
2624 }
2625 ///Set the value of `sec_prot`
2626 #[inline]
2627 pub fn set_sec_prot(&mut self, value: Ctrl_WifiSecProt) -> &mut Self {
2628 self.r#sec_prot = value.into();
2629 self
2630 }
2631 ///Builder method that sets the value of `sec_prot`. Useful for initializing the message.
2632 #[inline]
2633 pub fn init_sec_prot(mut self, value: Ctrl_WifiSecProt) -> Self {
2634 self.r#sec_prot = value.into();
2635 self
2636 }
2637 ///Return a reference to `max_conn`
2638 #[inline]
2639 pub fn r#max_conn(&self) -> &i32 {
2640 &self.r#max_conn
2641 }
2642 ///Return a mutable reference to `max_conn`
2643 #[inline]
2644 pub fn mut_max_conn(&mut self) -> &mut i32 {
2645 &mut self.r#max_conn
2646 }
2647 ///Set the value of `max_conn`
2648 #[inline]
2649 pub fn set_max_conn(&mut self, value: i32) -> &mut Self {
2650 self.r#max_conn = value.into();
2651 self
2652 }
2653 ///Builder method that sets the value of `max_conn`. Useful for initializing the message.
2654 #[inline]
2655 pub fn init_max_conn(mut self, value: i32) -> Self {
2656 self.r#max_conn = value.into();
2657 self
2658 }
2659 ///Return a reference to `ssid_hidden`
2660 #[inline]
2661 pub fn r#ssid_hidden(&self) -> &bool {
2662 &self.r#ssid_hidden
2663 }
2664 ///Return a mutable reference to `ssid_hidden`
2665 #[inline]
2666 pub fn mut_ssid_hidden(&mut self) -> &mut bool {
2667 &mut self.r#ssid_hidden
2668 }
2669 ///Set the value of `ssid_hidden`
2670 #[inline]
2671 pub fn set_ssid_hidden(&mut self, value: bool) -> &mut Self {
2672 self.r#ssid_hidden = value.into();
2673 self
2674 }
2675 ///Builder method that sets the value of `ssid_hidden`. Useful for initializing the message.
2676 #[inline]
2677 pub fn init_ssid_hidden(mut self, value: bool) -> Self {
2678 self.r#ssid_hidden = value.into();
2679 self
2680 }
2681 ///Return a reference to `bw`
2682 #[inline]
2683 pub fn r#bw(&self) -> &i32 {
2684 &self.r#bw
2685 }
2686 ///Return a mutable reference to `bw`
2687 #[inline]
2688 pub fn mut_bw(&mut self) -> &mut i32 {
2689 &mut self.r#bw
2690 }
2691 ///Set the value of `bw`
2692 #[inline]
2693 pub fn set_bw(&mut self, value: i32) -> &mut Self {
2694 self.r#bw = value.into();
2695 self
2696 }
2697 ///Builder method that sets the value of `bw`. Useful for initializing the message.
2698 #[inline]
2699 pub fn init_bw(mut self, value: i32) -> Self {
2700 self.r#bw = value.into();
2701 self
2702 }
2703 ///Return a reference to `resp`
2704 #[inline]
2705 pub fn r#resp(&self) -> &i32 {
2706 &self.r#resp
2707 }
2708 ///Return a mutable reference to `resp`
2709 #[inline]
2710 pub fn mut_resp(&mut self) -> &mut i32 {
2711 &mut self.r#resp
2712 }
2713 ///Set the value of `resp`
2714 #[inline]
2715 pub fn set_resp(&mut self, value: i32) -> &mut Self {
2716 self.r#resp = value.into();
2717 self
2718 }
2719 ///Builder method that sets the value of `resp`. Useful for initializing the message.
2720 #[inline]
2721 pub fn init_resp(mut self, value: i32) -> Self {
2722 self.r#resp = value.into();
2723 self
2724 }
2725 ///Return a reference to `band_mode`
2726 #[inline]
2727 pub fn r#band_mode(&self) -> &i32 {
2728 &self.r#band_mode
2729 }
2730 ///Return a mutable reference to `band_mode`
2731 #[inline]
2732 pub fn mut_band_mode(&mut self) -> &mut i32 {
2733 &mut self.r#band_mode
2734 }
2735 ///Set the value of `band_mode`
2736 #[inline]
2737 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
2738 self.r#band_mode = value.into();
2739 self
2740 }
2741 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
2742 #[inline]
2743 pub fn init_band_mode(mut self, value: i32) -> Self {
2744 self.r#band_mode = value.into();
2745 self
2746 }
2747}
2748impl ::micropb::MessageDecode for CtrlMsg_Resp_GetSoftAPConfig {
2749 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
2750 &mut self,
2751 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
2752 len: usize,
2753 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
2754 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
2755 let before = decoder.bytes_read();
2756 while decoder.bytes_read() - before < len {
2757 let tag = decoder.decode_tag()?;
2758 match tag.field_num() {
2759 0 => return Err(::micropb::DecodeError::ZeroField),
2760 1u32 => {
2761 let mut_ref = &mut self.r#ssid;
2762 {
2763 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
2764 };
2765 }
2766 2u32 => {
2767 let mut_ref = &mut self.r#pwd;
2768 {
2769 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
2770 };
2771 }
2772 3u32 => {
2773 let mut_ref = &mut self.r#chnl;
2774 {
2775 let val = decoder.decode_int32()?;
2776 let val_ref = &val;
2777 if *val_ref != 0 {
2778 *mut_ref = val as _;
2779 }
2780 };
2781 }
2782 4u32 => {
2783 let mut_ref = &mut self.r#sec_prot;
2784 {
2785 let val = decoder.decode_int32().map(|n| Ctrl_WifiSecProt(n as _))?;
2786 let val_ref = &val;
2787 if val_ref.0 != 0 {
2788 *mut_ref = val as _;
2789 }
2790 };
2791 }
2792 5u32 => {
2793 let mut_ref = &mut self.r#max_conn;
2794 {
2795 let val = decoder.decode_int32()?;
2796 let val_ref = &val;
2797 if *val_ref != 0 {
2798 *mut_ref = val as _;
2799 }
2800 };
2801 }
2802 6u32 => {
2803 let mut_ref = &mut self.r#ssid_hidden;
2804 {
2805 let val = decoder.decode_bool()?;
2806 let val_ref = &val;
2807 if *val_ref {
2808 *mut_ref = val as _;
2809 }
2810 };
2811 }
2812 7u32 => {
2813 let mut_ref = &mut self.r#bw;
2814 {
2815 let val = decoder.decode_int32()?;
2816 let val_ref = &val;
2817 if *val_ref != 0 {
2818 *mut_ref = val as _;
2819 }
2820 };
2821 }
2822 8u32 => {
2823 let mut_ref = &mut self.r#resp;
2824 {
2825 let val = decoder.decode_int32()?;
2826 let val_ref = &val;
2827 if *val_ref != 0 {
2828 *mut_ref = val as _;
2829 }
2830 };
2831 }
2832 9u32 => {
2833 let mut_ref = &mut self.r#band_mode;
2834 {
2835 let val = decoder.decode_int32()?;
2836 let val_ref = &val;
2837 if *val_ref != 0 {
2838 *mut_ref = val as _;
2839 }
2840 };
2841 }
2842 _ => {
2843 decoder.skip_wire_value(tag.wire_type())?;
2844 }
2845 }
2846 }
2847 Ok(())
2848 }
2849}
2850impl ::micropb::MessageEncode for CtrlMsg_Resp_GetSoftAPConfig {
2851 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
2852 let mut max_size = 0;
2853 if let ::core::option::Option::Some(size) =
2854 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2855 {
2856 max_size += size;
2857 } else {
2858 break 'msg (::core::option::Option::<usize>::None);
2859 };
2860 if let ::core::option::Option::Some(size) =
2861 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
2862 {
2863 max_size += size;
2864 } else {
2865 break 'msg (::core::option::Option::<usize>::None);
2866 };
2867 if let ::core::option::Option::Some(size) =
2868 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2869 {
2870 max_size += size;
2871 } else {
2872 break 'msg (::core::option::Option::<usize>::None);
2873 };
2874 if let ::core::option::Option::Some(size) =
2875 ::micropb::const_map!(::core::option::Option::Some(Ctrl_WifiSecProt::_MAX_SIZE), |size| size
2876 + 1usize)
2877 {
2878 max_size += size;
2879 } else {
2880 break 'msg (::core::option::Option::<usize>::None);
2881 };
2882 if let ::core::option::Option::Some(size) =
2883 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2884 {
2885 max_size += size;
2886 } else {
2887 break 'msg (::core::option::Option::<usize>::None);
2888 };
2889 if let ::core::option::Option::Some(size) =
2890 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
2891 {
2892 max_size += size;
2893 } else {
2894 break 'msg (::core::option::Option::<usize>::None);
2895 };
2896 if let ::core::option::Option::Some(size) =
2897 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2898 {
2899 max_size += size;
2900 } else {
2901 break 'msg (::core::option::Option::<usize>::None);
2902 };
2903 if let ::core::option::Option::Some(size) =
2904 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2905 {
2906 max_size += size;
2907 } else {
2908 break 'msg (::core::option::Option::<usize>::None);
2909 };
2910 if let ::core::option::Option::Some(size) =
2911 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
2912 {
2913 max_size += size;
2914 } else {
2915 break 'msg (::core::option::Option::<usize>::None);
2916 };
2917 ::core::option::Option::Some(max_size)
2918 };
2919 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
2920 &self,
2921 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
2922 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
2923 use ::micropb::{FieldEncode, PbMap};
2924 {
2925 let val_ref = &self.r#ssid;
2926 if !val_ref.is_empty() {
2927 encoder.encode_varint32(10u32)?;
2928 encoder.encode_bytes(val_ref)?;
2929 }
2930 }
2931 {
2932 let val_ref = &self.r#pwd;
2933 if !val_ref.is_empty() {
2934 encoder.encode_varint32(18u32)?;
2935 encoder.encode_bytes(val_ref)?;
2936 }
2937 }
2938 {
2939 let val_ref = &self.r#chnl;
2940 if *val_ref != 0 {
2941 encoder.encode_varint32(24u32)?;
2942 encoder.encode_int32(*val_ref as _)?;
2943 }
2944 }
2945 {
2946 let val_ref = &self.r#sec_prot;
2947 if val_ref.0 != 0 {
2948 encoder.encode_varint32(32u32)?;
2949 encoder.encode_int32(val_ref.0 as _)?;
2950 }
2951 }
2952 {
2953 let val_ref = &self.r#max_conn;
2954 if *val_ref != 0 {
2955 encoder.encode_varint32(40u32)?;
2956 encoder.encode_int32(*val_ref as _)?;
2957 }
2958 }
2959 {
2960 let val_ref = &self.r#ssid_hidden;
2961 if *val_ref {
2962 encoder.encode_varint32(48u32)?;
2963 encoder.encode_bool(*val_ref)?;
2964 }
2965 }
2966 {
2967 let val_ref = &self.r#bw;
2968 if *val_ref != 0 {
2969 encoder.encode_varint32(56u32)?;
2970 encoder.encode_int32(*val_ref as _)?;
2971 }
2972 }
2973 {
2974 let val_ref = &self.r#resp;
2975 if *val_ref != 0 {
2976 encoder.encode_varint32(64u32)?;
2977 encoder.encode_int32(*val_ref as _)?;
2978 }
2979 }
2980 {
2981 let val_ref = &self.r#band_mode;
2982 if *val_ref != 0 {
2983 encoder.encode_varint32(72u32)?;
2984 encoder.encode_int32(*val_ref as _)?;
2985 }
2986 }
2987 Ok(())
2988 }
2989 fn compute_size(&self) -> usize {
2990 use ::micropb::{FieldEncode, PbMap};
2991 let mut size = 0;
2992 {
2993 let val_ref = &self.r#ssid;
2994 if !val_ref.is_empty() {
2995 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
2996 }
2997 }
2998 {
2999 let val_ref = &self.r#pwd;
3000 if !val_ref.is_empty() {
3001 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
3002 }
3003 }
3004 {
3005 let val_ref = &self.r#chnl;
3006 if *val_ref != 0 {
3007 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3008 }
3009 }
3010 {
3011 let val_ref = &self.r#sec_prot;
3012 if val_ref.0 != 0 {
3013 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
3014 }
3015 }
3016 {
3017 let val_ref = &self.r#max_conn;
3018 if *val_ref != 0 {
3019 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3020 }
3021 }
3022 {
3023 let val_ref = &self.r#ssid_hidden;
3024 if *val_ref {
3025 size += 1usize + 1;
3026 }
3027 }
3028 {
3029 let val_ref = &self.r#bw;
3030 if *val_ref != 0 {
3031 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3032 }
3033 }
3034 {
3035 let val_ref = &self.r#resp;
3036 if *val_ref != 0 {
3037 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3038 }
3039 }
3040 {
3041 let val_ref = &self.r#band_mode;
3042 if *val_ref != 0 {
3043 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3044 }
3045 }
3046 size
3047 }
3048}
3049#[derive(Debug, Default, PartialEq, Clone)]
220#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3050#[cfg_attr(feature = "defmt", derive(defmt::Format))]
221pub(crate) struct CtrlMsgRespSoftApConnectedSta { 3051pub struct CtrlMsg_Req_StartSoftAP {
222 #[noproto(tag = "1")] 3052 pub r#ssid: ::micropb::heapless::String<32>,
223 pub num: u32, 3053 pub r#pwd: ::micropb::heapless::String<32>,
224 #[noproto(repeated, tag = "2")] 3054 pub r#chnl: i32,
225 pub stations: Vec<ConnectedStaList, 16>, 3055 pub r#sec_prot: Ctrl_WifiSecProt,
226 #[noproto(tag = "3")] 3056 pub r#max_conn: i32,
227 pub resp: u32, 3057 pub r#ssid_hidden: bool,
3058 pub r#bw: i32,
3059 pub r#band_mode: i32,
228} 3060}
229 3061impl CtrlMsg_Req_StartSoftAP {
230#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3062 ///Return a reference to `ssid`
3063 #[inline]
3064 pub fn r#ssid(&self) -> &::micropb::heapless::String<32> {
3065 &self.r#ssid
3066 }
3067 ///Return a mutable reference to `ssid`
3068 #[inline]
3069 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::String<32> {
3070 &mut self.r#ssid
3071 }
3072 ///Set the value of `ssid`
3073 #[inline]
3074 pub fn set_ssid(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
3075 self.r#ssid = value.into();
3076 self
3077 }
3078 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
3079 #[inline]
3080 pub fn init_ssid(mut self, value: ::micropb::heapless::String<32>) -> Self {
3081 self.r#ssid = value.into();
3082 self
3083 }
3084 ///Return a reference to `pwd`
3085 #[inline]
3086 pub fn r#pwd(&self) -> &::micropb::heapless::String<32> {
3087 &self.r#pwd
3088 }
3089 ///Return a mutable reference to `pwd`
3090 #[inline]
3091 pub fn mut_pwd(&mut self) -> &mut ::micropb::heapless::String<32> {
3092 &mut self.r#pwd
3093 }
3094 ///Set the value of `pwd`
3095 #[inline]
3096 pub fn set_pwd(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
3097 self.r#pwd = value.into();
3098 self
3099 }
3100 ///Builder method that sets the value of `pwd`. Useful for initializing the message.
3101 #[inline]
3102 pub fn init_pwd(mut self, value: ::micropb::heapless::String<32>) -> Self {
3103 self.r#pwd = value.into();
3104 self
3105 }
3106 ///Return a reference to `chnl`
3107 #[inline]
3108 pub fn r#chnl(&self) -> &i32 {
3109 &self.r#chnl
3110 }
3111 ///Return a mutable reference to `chnl`
3112 #[inline]
3113 pub fn mut_chnl(&mut self) -> &mut i32 {
3114 &mut self.r#chnl
3115 }
3116 ///Set the value of `chnl`
3117 #[inline]
3118 pub fn set_chnl(&mut self, value: i32) -> &mut Self {
3119 self.r#chnl = value.into();
3120 self
3121 }
3122 ///Builder method that sets the value of `chnl`. Useful for initializing the message.
3123 #[inline]
3124 pub fn init_chnl(mut self, value: i32) -> Self {
3125 self.r#chnl = value.into();
3126 self
3127 }
3128 ///Return a reference to `sec_prot`
3129 #[inline]
3130 pub fn r#sec_prot(&self) -> &Ctrl_WifiSecProt {
3131 &self.r#sec_prot
3132 }
3133 ///Return a mutable reference to `sec_prot`
3134 #[inline]
3135 pub fn mut_sec_prot(&mut self) -> &mut Ctrl_WifiSecProt {
3136 &mut self.r#sec_prot
3137 }
3138 ///Set the value of `sec_prot`
3139 #[inline]
3140 pub fn set_sec_prot(&mut self, value: Ctrl_WifiSecProt) -> &mut Self {
3141 self.r#sec_prot = value.into();
3142 self
3143 }
3144 ///Builder method that sets the value of `sec_prot`. Useful for initializing the message.
3145 #[inline]
3146 pub fn init_sec_prot(mut self, value: Ctrl_WifiSecProt) -> Self {
3147 self.r#sec_prot = value.into();
3148 self
3149 }
3150 ///Return a reference to `max_conn`
3151 #[inline]
3152 pub fn r#max_conn(&self) -> &i32 {
3153 &self.r#max_conn
3154 }
3155 ///Return a mutable reference to `max_conn`
3156 #[inline]
3157 pub fn mut_max_conn(&mut self) -> &mut i32 {
3158 &mut self.r#max_conn
3159 }
3160 ///Set the value of `max_conn`
3161 #[inline]
3162 pub fn set_max_conn(&mut self, value: i32) -> &mut Self {
3163 self.r#max_conn = value.into();
3164 self
3165 }
3166 ///Builder method that sets the value of `max_conn`. Useful for initializing the message.
3167 #[inline]
3168 pub fn init_max_conn(mut self, value: i32) -> Self {
3169 self.r#max_conn = value.into();
3170 self
3171 }
3172 ///Return a reference to `ssid_hidden`
3173 #[inline]
3174 pub fn r#ssid_hidden(&self) -> &bool {
3175 &self.r#ssid_hidden
3176 }
3177 ///Return a mutable reference to `ssid_hidden`
3178 #[inline]
3179 pub fn mut_ssid_hidden(&mut self) -> &mut bool {
3180 &mut self.r#ssid_hidden
3181 }
3182 ///Set the value of `ssid_hidden`
3183 #[inline]
3184 pub fn set_ssid_hidden(&mut self, value: bool) -> &mut Self {
3185 self.r#ssid_hidden = value.into();
3186 self
3187 }
3188 ///Builder method that sets the value of `ssid_hidden`. Useful for initializing the message.
3189 #[inline]
3190 pub fn init_ssid_hidden(mut self, value: bool) -> Self {
3191 self.r#ssid_hidden = value.into();
3192 self
3193 }
3194 ///Return a reference to `bw`
3195 #[inline]
3196 pub fn r#bw(&self) -> &i32 {
3197 &self.r#bw
3198 }
3199 ///Return a mutable reference to `bw`
3200 #[inline]
3201 pub fn mut_bw(&mut self) -> &mut i32 {
3202 &mut self.r#bw
3203 }
3204 ///Set the value of `bw`
3205 #[inline]
3206 pub fn set_bw(&mut self, value: i32) -> &mut Self {
3207 self.r#bw = value.into();
3208 self
3209 }
3210 ///Builder method that sets the value of `bw`. Useful for initializing the message.
3211 #[inline]
3212 pub fn init_bw(mut self, value: i32) -> Self {
3213 self.r#bw = value.into();
3214 self
3215 }
3216 ///Return a reference to `band_mode`
3217 #[inline]
3218 pub fn r#band_mode(&self) -> &i32 {
3219 &self.r#band_mode
3220 }
3221 ///Return a mutable reference to `band_mode`
3222 #[inline]
3223 pub fn mut_band_mode(&mut self) -> &mut i32 {
3224 &mut self.r#band_mode
3225 }
3226 ///Set the value of `band_mode`
3227 #[inline]
3228 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
3229 self.r#band_mode = value.into();
3230 self
3231 }
3232 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
3233 #[inline]
3234 pub fn init_band_mode(mut self, value: i32) -> Self {
3235 self.r#band_mode = value.into();
3236 self
3237 }
3238}
3239impl ::micropb::MessageDecode for CtrlMsg_Req_StartSoftAP {
3240 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
3241 &mut self,
3242 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
3243 len: usize,
3244 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
3245 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
3246 let before = decoder.bytes_read();
3247 while decoder.bytes_read() - before < len {
3248 let tag = decoder.decode_tag()?;
3249 match tag.field_num() {
3250 0 => return Err(::micropb::DecodeError::ZeroField),
3251 1u32 => {
3252 let mut_ref = &mut self.r#ssid;
3253 {
3254 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
3255 };
3256 }
3257 2u32 => {
3258 let mut_ref = &mut self.r#pwd;
3259 {
3260 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
3261 };
3262 }
3263 3u32 => {
3264 let mut_ref = &mut self.r#chnl;
3265 {
3266 let val = decoder.decode_int32()?;
3267 let val_ref = &val;
3268 if *val_ref != 0 {
3269 *mut_ref = val as _;
3270 }
3271 };
3272 }
3273 4u32 => {
3274 let mut_ref = &mut self.r#sec_prot;
3275 {
3276 let val = decoder.decode_int32().map(|n| Ctrl_WifiSecProt(n as _))?;
3277 let val_ref = &val;
3278 if val_ref.0 != 0 {
3279 *mut_ref = val as _;
3280 }
3281 };
3282 }
3283 5u32 => {
3284 let mut_ref = &mut self.r#max_conn;
3285 {
3286 let val = decoder.decode_int32()?;
3287 let val_ref = &val;
3288 if *val_ref != 0 {
3289 *mut_ref = val as _;
3290 }
3291 };
3292 }
3293 6u32 => {
3294 let mut_ref = &mut self.r#ssid_hidden;
3295 {
3296 let val = decoder.decode_bool()?;
3297 let val_ref = &val;
3298 if *val_ref {
3299 *mut_ref = val as _;
3300 }
3301 };
3302 }
3303 7u32 => {
3304 let mut_ref = &mut self.r#bw;
3305 {
3306 let val = decoder.decode_int32()?;
3307 let val_ref = &val;
3308 if *val_ref != 0 {
3309 *mut_ref = val as _;
3310 }
3311 };
3312 }
3313 8u32 => {
3314 let mut_ref = &mut self.r#band_mode;
3315 {
3316 let val = decoder.decode_int32()?;
3317 let val_ref = &val;
3318 if *val_ref != 0 {
3319 *mut_ref = val as _;
3320 }
3321 };
3322 }
3323 _ => {
3324 decoder.skip_wire_value(tag.wire_type())?;
3325 }
3326 }
3327 }
3328 Ok(())
3329 }
3330}
3331impl ::micropb::MessageEncode for CtrlMsg_Req_StartSoftAP {
3332 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
3333 let mut max_size = 0;
3334 if let ::core::option::Option::Some(size) =
3335 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
3336 {
3337 max_size += size;
3338 } else {
3339 break 'msg (::core::option::Option::<usize>::None);
3340 };
3341 if let ::core::option::Option::Some(size) =
3342 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
3343 {
3344 max_size += size;
3345 } else {
3346 break 'msg (::core::option::Option::<usize>::None);
3347 };
3348 if let ::core::option::Option::Some(size) =
3349 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3350 {
3351 max_size += size;
3352 } else {
3353 break 'msg (::core::option::Option::<usize>::None);
3354 };
3355 if let ::core::option::Option::Some(size) =
3356 ::micropb::const_map!(::core::option::Option::Some(Ctrl_WifiSecProt::_MAX_SIZE), |size| size
3357 + 1usize)
3358 {
3359 max_size += size;
3360 } else {
3361 break 'msg (::core::option::Option::<usize>::None);
3362 };
3363 if let ::core::option::Option::Some(size) =
3364 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3365 {
3366 max_size += size;
3367 } else {
3368 break 'msg (::core::option::Option::<usize>::None);
3369 };
3370 if let ::core::option::Option::Some(size) =
3371 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
3372 {
3373 max_size += size;
3374 } else {
3375 break 'msg (::core::option::Option::<usize>::None);
3376 };
3377 if let ::core::option::Option::Some(size) =
3378 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3379 {
3380 max_size += size;
3381 } else {
3382 break 'msg (::core::option::Option::<usize>::None);
3383 };
3384 if let ::core::option::Option::Some(size) =
3385 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3386 {
3387 max_size += size;
3388 } else {
3389 break 'msg (::core::option::Option::<usize>::None);
3390 };
3391 ::core::option::Option::Some(max_size)
3392 };
3393 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
3394 &self,
3395 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
3396 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
3397 use ::micropb::{FieldEncode, PbMap};
3398 {
3399 let val_ref = &self.r#ssid;
3400 if !val_ref.is_empty() {
3401 encoder.encode_varint32(10u32)?;
3402 encoder.encode_string(val_ref)?;
3403 }
3404 }
3405 {
3406 let val_ref = &self.r#pwd;
3407 if !val_ref.is_empty() {
3408 encoder.encode_varint32(18u32)?;
3409 encoder.encode_string(val_ref)?;
3410 }
3411 }
3412 {
3413 let val_ref = &self.r#chnl;
3414 if *val_ref != 0 {
3415 encoder.encode_varint32(24u32)?;
3416 encoder.encode_int32(*val_ref as _)?;
3417 }
3418 }
3419 {
3420 let val_ref = &self.r#sec_prot;
3421 if val_ref.0 != 0 {
3422 encoder.encode_varint32(32u32)?;
3423 encoder.encode_int32(val_ref.0 as _)?;
3424 }
3425 }
3426 {
3427 let val_ref = &self.r#max_conn;
3428 if *val_ref != 0 {
3429 encoder.encode_varint32(40u32)?;
3430 encoder.encode_int32(*val_ref as _)?;
3431 }
3432 }
3433 {
3434 let val_ref = &self.r#ssid_hidden;
3435 if *val_ref {
3436 encoder.encode_varint32(48u32)?;
3437 encoder.encode_bool(*val_ref)?;
3438 }
3439 }
3440 {
3441 let val_ref = &self.r#bw;
3442 if *val_ref != 0 {
3443 encoder.encode_varint32(56u32)?;
3444 encoder.encode_int32(*val_ref as _)?;
3445 }
3446 }
3447 {
3448 let val_ref = &self.r#band_mode;
3449 if *val_ref != 0 {
3450 encoder.encode_varint32(64u32)?;
3451 encoder.encode_int32(*val_ref as _)?;
3452 }
3453 }
3454 Ok(())
3455 }
3456 fn compute_size(&self) -> usize {
3457 use ::micropb::{FieldEncode, PbMap};
3458 let mut size = 0;
3459 {
3460 let val_ref = &self.r#ssid;
3461 if !val_ref.is_empty() {
3462 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
3463 }
3464 }
3465 {
3466 let val_ref = &self.r#pwd;
3467 if !val_ref.is_empty() {
3468 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
3469 }
3470 }
3471 {
3472 let val_ref = &self.r#chnl;
3473 if *val_ref != 0 {
3474 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3475 }
3476 }
3477 {
3478 let val_ref = &self.r#sec_prot;
3479 if val_ref.0 != 0 {
3480 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
3481 }
3482 }
3483 {
3484 let val_ref = &self.r#max_conn;
3485 if *val_ref != 0 {
3486 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3487 }
3488 }
3489 {
3490 let val_ref = &self.r#ssid_hidden;
3491 if *val_ref {
3492 size += 1usize + 1;
3493 }
3494 }
3495 {
3496 let val_ref = &self.r#bw;
3497 if *val_ref != 0 {
3498 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3499 }
3500 }
3501 {
3502 let val_ref = &self.r#band_mode;
3503 if *val_ref != 0 {
3504 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3505 }
3506 }
3507 size
3508 }
3509}
3510#[derive(Debug, Default, PartialEq, Clone)]
231#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3511#[cfg_attr(feature = "defmt", derive(defmt::Format))]
232pub(crate) struct CtrlMsgReqOtaBegin {} 3512pub struct CtrlMsg_Resp_StartSoftAP {
233 3513 pub r#resp: i32,
234#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3514 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
3515 pub r#band_mode: i32,
3516}
3517impl CtrlMsg_Resp_StartSoftAP {
3518 ///Return a reference to `resp`
3519 #[inline]
3520 pub fn r#resp(&self) -> &i32 {
3521 &self.r#resp
3522 }
3523 ///Return a mutable reference to `resp`
3524 #[inline]
3525 pub fn mut_resp(&mut self) -> &mut i32 {
3526 &mut self.r#resp
3527 }
3528 ///Set the value of `resp`
3529 #[inline]
3530 pub fn set_resp(&mut self, value: i32) -> &mut Self {
3531 self.r#resp = value.into();
3532 self
3533 }
3534 ///Builder method that sets the value of `resp`. Useful for initializing the message.
3535 #[inline]
3536 pub fn init_resp(mut self, value: i32) -> Self {
3537 self.r#resp = value.into();
3538 self
3539 }
3540 ///Return a reference to `mac`
3541 #[inline]
3542 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
3543 &self.r#mac
3544 }
3545 ///Return a mutable reference to `mac`
3546 #[inline]
3547 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
3548 &mut self.r#mac
3549 }
3550 ///Set the value of `mac`
3551 #[inline]
3552 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
3553 self.r#mac = value.into();
3554 self
3555 }
3556 ///Builder method that sets the value of `mac`. Useful for initializing the message.
3557 #[inline]
3558 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
3559 self.r#mac = value.into();
3560 self
3561 }
3562 ///Return a reference to `band_mode`
3563 #[inline]
3564 pub fn r#band_mode(&self) -> &i32 {
3565 &self.r#band_mode
3566 }
3567 ///Return a mutable reference to `band_mode`
3568 #[inline]
3569 pub fn mut_band_mode(&mut self) -> &mut i32 {
3570 &mut self.r#band_mode
3571 }
3572 ///Set the value of `band_mode`
3573 #[inline]
3574 pub fn set_band_mode(&mut self, value: i32) -> &mut Self {
3575 self.r#band_mode = value.into();
3576 self
3577 }
3578 ///Builder method that sets the value of `band_mode`. Useful for initializing the message.
3579 #[inline]
3580 pub fn init_band_mode(mut self, value: i32) -> Self {
3581 self.r#band_mode = value.into();
3582 self
3583 }
3584}
3585impl ::micropb::MessageDecode for CtrlMsg_Resp_StartSoftAP {
3586 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
3587 &mut self,
3588 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
3589 len: usize,
3590 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
3591 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
3592 let before = decoder.bytes_read();
3593 while decoder.bytes_read() - before < len {
3594 let tag = decoder.decode_tag()?;
3595 match tag.field_num() {
3596 0 => return Err(::micropb::DecodeError::ZeroField),
3597 1u32 => {
3598 let mut_ref = &mut self.r#resp;
3599 {
3600 let val = decoder.decode_int32()?;
3601 let val_ref = &val;
3602 if *val_ref != 0 {
3603 *mut_ref = val as _;
3604 }
3605 };
3606 }
3607 2u32 => {
3608 let mut_ref = &mut self.r#mac;
3609 {
3610 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
3611 };
3612 }
3613 3u32 => {
3614 let mut_ref = &mut self.r#band_mode;
3615 {
3616 let val = decoder.decode_int32()?;
3617 let val_ref = &val;
3618 if *val_ref != 0 {
3619 *mut_ref = val as _;
3620 }
3621 };
3622 }
3623 _ => {
3624 decoder.skip_wire_value(tag.wire_type())?;
3625 }
3626 }
3627 }
3628 Ok(())
3629 }
3630}
3631impl ::micropb::MessageEncode for CtrlMsg_Resp_StartSoftAP {
3632 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
3633 let mut max_size = 0;
3634 if let ::core::option::Option::Some(size) =
3635 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3636 {
3637 max_size += size;
3638 } else {
3639 break 'msg (::core::option::Option::<usize>::None);
3640 };
3641 if let ::core::option::Option::Some(size) =
3642 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
3643 {
3644 max_size += size;
3645 } else {
3646 break 'msg (::core::option::Option::<usize>::None);
3647 };
3648 if let ::core::option::Option::Some(size) =
3649 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3650 {
3651 max_size += size;
3652 } else {
3653 break 'msg (::core::option::Option::<usize>::None);
3654 };
3655 ::core::option::Option::Some(max_size)
3656 };
3657 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
3658 &self,
3659 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
3660 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
3661 use ::micropb::{FieldEncode, PbMap};
3662 {
3663 let val_ref = &self.r#resp;
3664 if *val_ref != 0 {
3665 encoder.encode_varint32(8u32)?;
3666 encoder.encode_int32(*val_ref as _)?;
3667 }
3668 }
3669 {
3670 let val_ref = &self.r#mac;
3671 if !val_ref.is_empty() {
3672 encoder.encode_varint32(18u32)?;
3673 encoder.encode_bytes(val_ref)?;
3674 }
3675 }
3676 {
3677 let val_ref = &self.r#band_mode;
3678 if *val_ref != 0 {
3679 encoder.encode_varint32(24u32)?;
3680 encoder.encode_int32(*val_ref as _)?;
3681 }
3682 }
3683 Ok(())
3684 }
3685 fn compute_size(&self) -> usize {
3686 use ::micropb::{FieldEncode, PbMap};
3687 let mut size = 0;
3688 {
3689 let val_ref = &self.r#resp;
3690 if *val_ref != 0 {
3691 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3692 }
3693 }
3694 {
3695 let val_ref = &self.r#mac;
3696 if !val_ref.is_empty() {
3697 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
3698 }
3699 }
3700 {
3701 let val_ref = &self.r#band_mode;
3702 if *val_ref != 0 {
3703 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3704 }
3705 }
3706 size
3707 }
3708}
3709#[derive(Debug, Default, PartialEq, Clone)]
235#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3710#[cfg_attr(feature = "defmt", derive(defmt::Format))]
236pub(crate) struct CtrlMsgRespOtaBegin { 3711pub struct CtrlMsg_Req_ScanResult {}
237 #[noproto(tag = "1")] 3712impl CtrlMsg_Req_ScanResult {}
238 pub resp: u32, 3713impl ::micropb::MessageDecode for CtrlMsg_Req_ScanResult {
3714 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
3715 &mut self,
3716 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
3717 len: usize,
3718 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
3719 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
3720 let before = decoder.bytes_read();
3721 while decoder.bytes_read() - before < len {
3722 let tag = decoder.decode_tag()?;
3723 match tag.field_num() {
3724 0 => return Err(::micropb::DecodeError::ZeroField),
3725 _ => {
3726 decoder.skip_wire_value(tag.wire_type())?;
3727 }
3728 }
3729 }
3730 Ok(())
3731 }
239} 3732}
240 3733impl ::micropb::MessageEncode for CtrlMsg_Req_ScanResult {
241#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3734 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
3735 let mut max_size = 0;
3736 ::core::option::Option::Some(max_size)
3737 };
3738 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
3739 &self,
3740 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
3741 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
3742 use ::micropb::{FieldEncode, PbMap};
3743 Ok(())
3744 }
3745 fn compute_size(&self) -> usize {
3746 use ::micropb::{FieldEncode, PbMap};
3747 let mut size = 0;
3748 size
3749 }
3750}
3751#[derive(Debug, Default, PartialEq, Clone)]
242#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3752#[cfg_attr(feature = "defmt", derive(defmt::Format))]
243pub(crate) struct CtrlMsgReqOtaWrite { 3753pub struct CtrlMsg_Resp_ScanResult {
244 #[noproto(tag = "1")] 3754 pub r#count: u32,
245 pub ota_data: Vec<u8, 1024>, 3755 pub r#entries: ::micropb::heapless::Vec<ScanResult, 16>,
3756 pub r#resp: i32,
246} 3757}
247 3758impl CtrlMsg_Resp_ScanResult {
248#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3759 ///Return a reference to `count`
3760 #[inline]
3761 pub fn r#count(&self) -> &u32 {
3762 &self.r#count
3763 }
3764 ///Return a mutable reference to `count`
3765 #[inline]
3766 pub fn mut_count(&mut self) -> &mut u32 {
3767 &mut self.r#count
3768 }
3769 ///Set the value of `count`
3770 #[inline]
3771 pub fn set_count(&mut self, value: u32) -> &mut Self {
3772 self.r#count = value.into();
3773 self
3774 }
3775 ///Builder method that sets the value of `count`. Useful for initializing the message.
3776 #[inline]
3777 pub fn init_count(mut self, value: u32) -> Self {
3778 self.r#count = value.into();
3779 self
3780 }
3781 ///Return a reference to `resp`
3782 #[inline]
3783 pub fn r#resp(&self) -> &i32 {
3784 &self.r#resp
3785 }
3786 ///Return a mutable reference to `resp`
3787 #[inline]
3788 pub fn mut_resp(&mut self) -> &mut i32 {
3789 &mut self.r#resp
3790 }
3791 ///Set the value of `resp`
3792 #[inline]
3793 pub fn set_resp(&mut self, value: i32) -> &mut Self {
3794 self.r#resp = value.into();
3795 self
3796 }
3797 ///Builder method that sets the value of `resp`. Useful for initializing the message.
3798 #[inline]
3799 pub fn init_resp(mut self, value: i32) -> Self {
3800 self.r#resp = value.into();
3801 self
3802 }
3803}
3804impl ::micropb::MessageDecode for CtrlMsg_Resp_ScanResult {
3805 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
3806 &mut self,
3807 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
3808 len: usize,
3809 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
3810 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
3811 let before = decoder.bytes_read();
3812 while decoder.bytes_read() - before < len {
3813 let tag = decoder.decode_tag()?;
3814 match tag.field_num() {
3815 0 => return Err(::micropb::DecodeError::ZeroField),
3816 1u32 => {
3817 let mut_ref = &mut self.r#count;
3818 {
3819 let val = decoder.decode_varint32()?;
3820 let val_ref = &val;
3821 if *val_ref != 0 {
3822 *mut_ref = val as _;
3823 }
3824 };
3825 }
3826 2u32 => {
3827 let mut val: ScanResult = ::core::default::Default::default();
3828 let mut_ref = &mut val;
3829 {
3830 mut_ref.decode_len_delimited(decoder)?;
3831 };
3832 if let (Err(_), false) = (self.r#entries.pb_push(val), decoder.ignore_repeated_cap_err) {
3833 return Err(::micropb::DecodeError::Capacity);
3834 }
3835 }
3836 3u32 => {
3837 let mut_ref = &mut self.r#resp;
3838 {
3839 let val = decoder.decode_int32()?;
3840 let val_ref = &val;
3841 if *val_ref != 0 {
3842 *mut_ref = val as _;
3843 }
3844 };
3845 }
3846 _ => {
3847 decoder.skip_wire_value(tag.wire_type())?;
3848 }
3849 }
3850 }
3851 Ok(())
3852 }
3853}
3854impl ::micropb::MessageEncode for CtrlMsg_Resp_ScanResult {
3855 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
3856 let mut max_size = 0;
3857 if let ::core::option::Option::Some(size) =
3858 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
3859 {
3860 max_size += size;
3861 } else {
3862 break 'msg (::core::option::Option::<usize>::None);
3863 };
3864 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
3865 ::micropb::const_map!(<ScanResult as ::micropb::MessageEncode>::MAX_SIZE, |size| {
3866 ::micropb::size::sizeof_len_record(size)
3867 }),
3868 |size| (size + 1usize) * 16usize
3869 ) {
3870 max_size += size;
3871 } else {
3872 break 'msg (::core::option::Option::<usize>::None);
3873 };
3874 if let ::core::option::Option::Some(size) =
3875 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
3876 {
3877 max_size += size;
3878 } else {
3879 break 'msg (::core::option::Option::<usize>::None);
3880 };
3881 ::core::option::Option::Some(max_size)
3882 };
3883 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
3884 &self,
3885 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
3886 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
3887 use ::micropb::{FieldEncode, PbMap};
3888 {
3889 let val_ref = &self.r#count;
3890 if *val_ref != 0 {
3891 encoder.encode_varint32(8u32)?;
3892 encoder.encode_varint32(*val_ref as _)?;
3893 }
3894 }
3895 {
3896 for val_ref in self.r#entries.iter() {
3897 encoder.encode_varint32(18u32)?;
3898 val_ref.encode_len_delimited(encoder)?;
3899 }
3900 }
3901 {
3902 let val_ref = &self.r#resp;
3903 if *val_ref != 0 {
3904 encoder.encode_varint32(24u32)?;
3905 encoder.encode_int32(*val_ref as _)?;
3906 }
3907 }
3908 Ok(())
3909 }
3910 fn compute_size(&self) -> usize {
3911 use ::micropb::{FieldEncode, PbMap};
3912 let mut size = 0;
3913 {
3914 let val_ref = &self.r#count;
3915 if *val_ref != 0 {
3916 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
3917 }
3918 }
3919 {
3920 for val_ref in self.r#entries.iter() {
3921 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
3922 }
3923 }
3924 {
3925 let val_ref = &self.r#resp;
3926 if *val_ref != 0 {
3927 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
3928 }
3929 }
3930 size
3931 }
3932}
3933#[derive(Debug, Default, PartialEq, Clone)]
249#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3934#[cfg_attr(feature = "defmt", derive(defmt::Format))]
250pub(crate) struct CtrlMsgRespOtaWrite { 3935pub struct CtrlMsg_Req_SoftAPConnectedSTA {}
251 #[noproto(tag = "1")] 3936impl CtrlMsg_Req_SoftAPConnectedSTA {}
252 pub resp: u32, 3937impl ::micropb::MessageDecode for CtrlMsg_Req_SoftAPConnectedSTA {
3938 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
3939 &mut self,
3940 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
3941 len: usize,
3942 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
3943 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
3944 let before = decoder.bytes_read();
3945 while decoder.bytes_read() - before < len {
3946 let tag = decoder.decode_tag()?;
3947 match tag.field_num() {
3948 0 => return Err(::micropb::DecodeError::ZeroField),
3949 _ => {
3950 decoder.skip_wire_value(tag.wire_type())?;
3951 }
3952 }
3953 }
3954 Ok(())
3955 }
253} 3956}
254 3957impl ::micropb::MessageEncode for CtrlMsg_Req_SoftAPConnectedSTA {
255#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3958 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
3959 let mut max_size = 0;
3960 ::core::option::Option::Some(max_size)
3961 };
3962 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
3963 &self,
3964 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
3965 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
3966 use ::micropb::{FieldEncode, PbMap};
3967 Ok(())
3968 }
3969 fn compute_size(&self) -> usize {
3970 use ::micropb::{FieldEncode, PbMap};
3971 let mut size = 0;
3972 size
3973 }
3974}
3975#[derive(Debug, Default, PartialEq, Clone)]
256#[cfg_attr(feature = "defmt", derive(defmt::Format))] 3976#[cfg_attr(feature = "defmt", derive(defmt::Format))]
257pub(crate) struct CtrlMsgReqOtaEnd {} 3977pub struct CtrlMsg_Resp_SoftAPConnectedSTA {
258 3978 pub r#num: u32,
259#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 3979 pub r#stations: ::micropb::heapless::Vec<ConnectedSTAList, 16>,
3980 pub r#resp: i32,
3981}
3982impl CtrlMsg_Resp_SoftAPConnectedSTA {
3983 ///Return a reference to `num`
3984 #[inline]
3985 pub fn r#num(&self) -> &u32 {
3986 &self.r#num
3987 }
3988 ///Return a mutable reference to `num`
3989 #[inline]
3990 pub fn mut_num(&mut self) -> &mut u32 {
3991 &mut self.r#num
3992 }
3993 ///Set the value of `num`
3994 #[inline]
3995 pub fn set_num(&mut self, value: u32) -> &mut Self {
3996 self.r#num = value.into();
3997 self
3998 }
3999 ///Builder method that sets the value of `num`. Useful for initializing the message.
4000 #[inline]
4001 pub fn init_num(mut self, value: u32) -> Self {
4002 self.r#num = value.into();
4003 self
4004 }
4005 ///Return a reference to `resp`
4006 #[inline]
4007 pub fn r#resp(&self) -> &i32 {
4008 &self.r#resp
4009 }
4010 ///Return a mutable reference to `resp`
4011 #[inline]
4012 pub fn mut_resp(&mut self) -> &mut i32 {
4013 &mut self.r#resp
4014 }
4015 ///Set the value of `resp`
4016 #[inline]
4017 pub fn set_resp(&mut self, value: i32) -> &mut Self {
4018 self.r#resp = value.into();
4019 self
4020 }
4021 ///Builder method that sets the value of `resp`. Useful for initializing the message.
4022 #[inline]
4023 pub fn init_resp(mut self, value: i32) -> Self {
4024 self.r#resp = value.into();
4025 self
4026 }
4027}
4028impl ::micropb::MessageDecode for CtrlMsg_Resp_SoftAPConnectedSTA {
4029 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4030 &mut self,
4031 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4032 len: usize,
4033 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4034 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4035 let before = decoder.bytes_read();
4036 while decoder.bytes_read() - before < len {
4037 let tag = decoder.decode_tag()?;
4038 match tag.field_num() {
4039 0 => return Err(::micropb::DecodeError::ZeroField),
4040 1u32 => {
4041 let mut_ref = &mut self.r#num;
4042 {
4043 let val = decoder.decode_varint32()?;
4044 let val_ref = &val;
4045 if *val_ref != 0 {
4046 *mut_ref = val as _;
4047 }
4048 };
4049 }
4050 2u32 => {
4051 let mut val: ConnectedSTAList = ::core::default::Default::default();
4052 let mut_ref = &mut val;
4053 {
4054 mut_ref.decode_len_delimited(decoder)?;
4055 };
4056 if let (Err(_), false) = (self.r#stations.pb_push(val), decoder.ignore_repeated_cap_err) {
4057 return Err(::micropb::DecodeError::Capacity);
4058 }
4059 }
4060 3u32 => {
4061 let mut_ref = &mut self.r#resp;
4062 {
4063 let val = decoder.decode_int32()?;
4064 let val_ref = &val;
4065 if *val_ref != 0 {
4066 *mut_ref = val as _;
4067 }
4068 };
4069 }
4070 _ => {
4071 decoder.skip_wire_value(tag.wire_type())?;
4072 }
4073 }
4074 }
4075 Ok(())
4076 }
4077}
4078impl ::micropb::MessageEncode for CtrlMsg_Resp_SoftAPConnectedSTA {
4079 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4080 let mut max_size = 0;
4081 if let ::core::option::Option::Some(size) =
4082 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
4083 {
4084 max_size += size;
4085 } else {
4086 break 'msg (::core::option::Option::<usize>::None);
4087 };
4088 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
4089 ::micropb::const_map!(<ConnectedSTAList as ::micropb::MessageEncode>::MAX_SIZE, |size| {
4090 ::micropb::size::sizeof_len_record(size)
4091 }),
4092 |size| (size + 1usize) * 16usize
4093 ) {
4094 max_size += size;
4095 } else {
4096 break 'msg (::core::option::Option::<usize>::None);
4097 };
4098 if let ::core::option::Option::Some(size) =
4099 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4100 {
4101 max_size += size;
4102 } else {
4103 break 'msg (::core::option::Option::<usize>::None);
4104 };
4105 ::core::option::Option::Some(max_size)
4106 };
4107 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4108 &self,
4109 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4110 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4111 use ::micropb::{FieldEncode, PbMap};
4112 {
4113 let val_ref = &self.r#num;
4114 if *val_ref != 0 {
4115 encoder.encode_varint32(8u32)?;
4116 encoder.encode_varint32(*val_ref as _)?;
4117 }
4118 }
4119 {
4120 for val_ref in self.r#stations.iter() {
4121 encoder.encode_varint32(18u32)?;
4122 val_ref.encode_len_delimited(encoder)?;
4123 }
4124 }
4125 {
4126 let val_ref = &self.r#resp;
4127 if *val_ref != 0 {
4128 encoder.encode_varint32(24u32)?;
4129 encoder.encode_int32(*val_ref as _)?;
4130 }
4131 }
4132 Ok(())
4133 }
4134 fn compute_size(&self) -> usize {
4135 use ::micropb::{FieldEncode, PbMap};
4136 let mut size = 0;
4137 {
4138 let val_ref = &self.r#num;
4139 if *val_ref != 0 {
4140 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
4141 }
4142 }
4143 {
4144 for val_ref in self.r#stations.iter() {
4145 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
4146 }
4147 }
4148 {
4149 let val_ref = &self.r#resp;
4150 if *val_ref != 0 {
4151 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4152 }
4153 }
4154 size
4155 }
4156}
4157#[derive(Debug, Default, PartialEq, Clone)]
260#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4158#[cfg_attr(feature = "defmt", derive(defmt::Format))]
261pub(crate) struct CtrlMsgRespOtaEnd { 4159pub struct CtrlMsg_Req_OTABegin {}
262 #[noproto(tag = "1")] 4160impl CtrlMsg_Req_OTABegin {}
263 pub resp: u32, 4161impl ::micropb::MessageDecode for CtrlMsg_Req_OTABegin {
4162 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4163 &mut self,
4164 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4165 len: usize,
4166 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4167 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4168 let before = decoder.bytes_read();
4169 while decoder.bytes_read() - before < len {
4170 let tag = decoder.decode_tag()?;
4171 match tag.field_num() {
4172 0 => return Err(::micropb::DecodeError::ZeroField),
4173 _ => {
4174 decoder.skip_wire_value(tag.wire_type())?;
4175 }
4176 }
4177 }
4178 Ok(())
4179 }
264} 4180}
265 4181impl ::micropb::MessageEncode for CtrlMsg_Req_OTABegin {
266#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4182 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
267#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4183 let mut max_size = 0;
268pub(crate) struct CtrlMsgReqVendorIeData { 4184 ::core::option::Option::Some(max_size)
269 #[noproto(tag = "1")] 4185 };
270 pub element_id: u32, 4186 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
271 #[noproto(tag = "2")] 4187 &self,
272 pub length: u32, 4188 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
273 #[noproto(tag = "3")] 4189 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
274 pub vendor_oui: Vec<u8, 8>, 4190 use ::micropb::{FieldEncode, PbMap};
275 #[noproto(tag = "4")] 4191 Ok(())
276 pub vendor_oui_type: u32, 4192 }
277 #[noproto(tag = "5")] 4193 fn compute_size(&self) -> usize {
278 pub payload: Vec<u8, 64>, 4194 use ::micropb::{FieldEncode, PbMap};
4195 let mut size = 0;
4196 size
4197 }
279} 4198}
280 4199#[derive(Debug, Default, PartialEq, Clone)]
281#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4200#[cfg_attr(feature = "defmt", derive(defmt::Format))]
282#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4201pub struct CtrlMsg_Resp_OTABegin {
283pub(crate) struct CtrlMsgReqSetSoftApVendorSpecificIe { 4202 pub r#resp: i32,
284 #[noproto(tag = "1")]
285 pub enable: bool,
286 #[noproto(tag = "2")]
287 pub r#type: CtrlVendorIeType,
288 #[noproto(tag = "3")]
289 pub idx: CtrlVendorIeid,
290 #[noproto(optional, tag = "4")]
291 pub vendor_ie_data: Option<CtrlMsgReqVendorIeData>,
292} 4203}
293 4204impl CtrlMsg_Resp_OTABegin {
294#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4205 ///Return a reference to `resp`
4206 #[inline]
4207 pub fn r#resp(&self) -> &i32 {
4208 &self.r#resp
4209 }
4210 ///Return a mutable reference to `resp`
4211 #[inline]
4212 pub fn mut_resp(&mut self) -> &mut i32 {
4213 &mut self.r#resp
4214 }
4215 ///Set the value of `resp`
4216 #[inline]
4217 pub fn set_resp(&mut self, value: i32) -> &mut Self {
4218 self.r#resp = value.into();
4219 self
4220 }
4221 ///Builder method that sets the value of `resp`. Useful for initializing the message.
4222 #[inline]
4223 pub fn init_resp(mut self, value: i32) -> Self {
4224 self.r#resp = value.into();
4225 self
4226 }
4227}
4228impl ::micropb::MessageDecode for CtrlMsg_Resp_OTABegin {
4229 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4230 &mut self,
4231 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4232 len: usize,
4233 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4234 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4235 let before = decoder.bytes_read();
4236 while decoder.bytes_read() - before < len {
4237 let tag = decoder.decode_tag()?;
4238 match tag.field_num() {
4239 0 => return Err(::micropb::DecodeError::ZeroField),
4240 1u32 => {
4241 let mut_ref = &mut self.r#resp;
4242 {
4243 let val = decoder.decode_int32()?;
4244 let val_ref = &val;
4245 if *val_ref != 0 {
4246 *mut_ref = val as _;
4247 }
4248 };
4249 }
4250 _ => {
4251 decoder.skip_wire_value(tag.wire_type())?;
4252 }
4253 }
4254 }
4255 Ok(())
4256 }
4257}
4258impl ::micropb::MessageEncode for CtrlMsg_Resp_OTABegin {
4259 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4260 let mut max_size = 0;
4261 if let ::core::option::Option::Some(size) =
4262 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4263 {
4264 max_size += size;
4265 } else {
4266 break 'msg (::core::option::Option::<usize>::None);
4267 };
4268 ::core::option::Option::Some(max_size)
4269 };
4270 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4271 &self,
4272 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4273 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4274 use ::micropb::{FieldEncode, PbMap};
4275 {
4276 let val_ref = &self.r#resp;
4277 if *val_ref != 0 {
4278 encoder.encode_varint32(8u32)?;
4279 encoder.encode_int32(*val_ref as _)?;
4280 }
4281 }
4282 Ok(())
4283 }
4284 fn compute_size(&self) -> usize {
4285 use ::micropb::{FieldEncode, PbMap};
4286 let mut size = 0;
4287 {
4288 let val_ref = &self.r#resp;
4289 if *val_ref != 0 {
4290 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4291 }
4292 }
4293 size
4294 }
4295}
4296#[derive(Debug, Default, PartialEq, Clone)]
295#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4297#[cfg_attr(feature = "defmt", derive(defmt::Format))]
296pub(crate) struct CtrlMsgRespSetSoftApVendorSpecificIe { 4298pub struct CtrlMsg_Req_OTAWrite {
297 #[noproto(tag = "1")] 4299 pub r#ota_data: ::micropb::heapless::Vec<u8, 1024>,
298 pub resp: u32,
299} 4300}
300 4301impl CtrlMsg_Req_OTAWrite {
301#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4302 ///Return a reference to `ota_data`
4303 #[inline]
4304 pub fn r#ota_data(&self) -> &::micropb::heapless::Vec<u8, 1024> {
4305 &self.r#ota_data
4306 }
4307 ///Return a mutable reference to `ota_data`
4308 #[inline]
4309 pub fn mut_ota_data(&mut self) -> &mut ::micropb::heapless::Vec<u8, 1024> {
4310 &mut self.r#ota_data
4311 }
4312 ///Set the value of `ota_data`
4313 #[inline]
4314 pub fn set_ota_data(&mut self, value: ::micropb::heapless::Vec<u8, 1024>) -> &mut Self {
4315 self.r#ota_data = value.into();
4316 self
4317 }
4318 ///Builder method that sets the value of `ota_data`. Useful for initializing the message.
4319 #[inline]
4320 pub fn init_ota_data(mut self, value: ::micropb::heapless::Vec<u8, 1024>) -> Self {
4321 self.r#ota_data = value.into();
4322 self
4323 }
4324}
4325impl ::micropb::MessageDecode for CtrlMsg_Req_OTAWrite {
4326 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4327 &mut self,
4328 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4329 len: usize,
4330 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4331 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4332 let before = decoder.bytes_read();
4333 while decoder.bytes_read() - before < len {
4334 let tag = decoder.decode_tag()?;
4335 match tag.field_num() {
4336 0 => return Err(::micropb::DecodeError::ZeroField),
4337 1u32 => {
4338 let mut_ref = &mut self.r#ota_data;
4339 {
4340 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
4341 };
4342 }
4343 _ => {
4344 decoder.skip_wire_value(tag.wire_type())?;
4345 }
4346 }
4347 }
4348 Ok(())
4349 }
4350}
4351impl ::micropb::MessageEncode for CtrlMsg_Req_OTAWrite {
4352 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4353 let mut max_size = 0;
4354 if let ::core::option::Option::Some(size) =
4355 ::micropb::const_map!(::core::option::Option::Some(1026usize), |size| size + 1usize)
4356 {
4357 max_size += size;
4358 } else {
4359 break 'msg (::core::option::Option::<usize>::None);
4360 };
4361 ::core::option::Option::Some(max_size)
4362 };
4363 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4364 &self,
4365 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4366 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4367 use ::micropb::{FieldEncode, PbMap};
4368 {
4369 let val_ref = &self.r#ota_data;
4370 if !val_ref.is_empty() {
4371 encoder.encode_varint32(10u32)?;
4372 encoder.encode_bytes(val_ref)?;
4373 }
4374 }
4375 Ok(())
4376 }
4377 fn compute_size(&self) -> usize {
4378 use ::micropb::{FieldEncode, PbMap};
4379 let mut size = 0;
4380 {
4381 let val_ref = &self.r#ota_data;
4382 if !val_ref.is_empty() {
4383 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
4384 }
4385 }
4386 size
4387 }
4388}
4389#[derive(Debug, Default, PartialEq, Clone)]
302#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4390#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303pub(crate) struct CtrlMsgReqSetWifiMaxTxPower { 4391pub struct CtrlMsg_Resp_OTAWrite {
304 #[noproto(tag = "1")] 4392 pub r#resp: i32,
305 pub wifi_max_tx_power: u32,
306} 4393}
307 4394impl CtrlMsg_Resp_OTAWrite {
308#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4395 ///Return a reference to `resp`
4396 #[inline]
4397 pub fn r#resp(&self) -> &i32 {
4398 &self.r#resp
4399 }
4400 ///Return a mutable reference to `resp`
4401 #[inline]
4402 pub fn mut_resp(&mut self) -> &mut i32 {
4403 &mut self.r#resp
4404 }
4405 ///Set the value of `resp`
4406 #[inline]
4407 pub fn set_resp(&mut self, value: i32) -> &mut Self {
4408 self.r#resp = value.into();
4409 self
4410 }
4411 ///Builder method that sets the value of `resp`. Useful for initializing the message.
4412 #[inline]
4413 pub fn init_resp(mut self, value: i32) -> Self {
4414 self.r#resp = value.into();
4415 self
4416 }
4417}
4418impl ::micropb::MessageDecode for CtrlMsg_Resp_OTAWrite {
4419 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4420 &mut self,
4421 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4422 len: usize,
4423 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4424 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4425 let before = decoder.bytes_read();
4426 while decoder.bytes_read() - before < len {
4427 let tag = decoder.decode_tag()?;
4428 match tag.field_num() {
4429 0 => return Err(::micropb::DecodeError::ZeroField),
4430 1u32 => {
4431 let mut_ref = &mut self.r#resp;
4432 {
4433 let val = decoder.decode_int32()?;
4434 let val_ref = &val;
4435 if *val_ref != 0 {
4436 *mut_ref = val as _;
4437 }
4438 };
4439 }
4440 _ => {
4441 decoder.skip_wire_value(tag.wire_type())?;
4442 }
4443 }
4444 }
4445 Ok(())
4446 }
4447}
4448impl ::micropb::MessageEncode for CtrlMsg_Resp_OTAWrite {
4449 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4450 let mut max_size = 0;
4451 if let ::core::option::Option::Some(size) =
4452 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4453 {
4454 max_size += size;
4455 } else {
4456 break 'msg (::core::option::Option::<usize>::None);
4457 };
4458 ::core::option::Option::Some(max_size)
4459 };
4460 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4461 &self,
4462 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4463 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4464 use ::micropb::{FieldEncode, PbMap};
4465 {
4466 let val_ref = &self.r#resp;
4467 if *val_ref != 0 {
4468 encoder.encode_varint32(8u32)?;
4469 encoder.encode_int32(*val_ref as _)?;
4470 }
4471 }
4472 Ok(())
4473 }
4474 fn compute_size(&self) -> usize {
4475 use ::micropb::{FieldEncode, PbMap};
4476 let mut size = 0;
4477 {
4478 let val_ref = &self.r#resp;
4479 if *val_ref != 0 {
4480 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4481 }
4482 }
4483 size
4484 }
4485}
4486#[derive(Debug, Default, PartialEq, Clone)]
309#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4487#[cfg_attr(feature = "defmt", derive(defmt::Format))]
310pub(crate) struct CtrlMsgRespSetWifiMaxTxPower { 4488pub struct CtrlMsg_Req_OTAEnd {}
311 #[noproto(tag = "1")] 4489impl CtrlMsg_Req_OTAEnd {}
312 pub resp: u32, 4490impl ::micropb::MessageDecode for CtrlMsg_Req_OTAEnd {
4491 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4492 &mut self,
4493 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4494 len: usize,
4495 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4496 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4497 let before = decoder.bytes_read();
4498 while decoder.bytes_read() - before < len {
4499 let tag = decoder.decode_tag()?;
4500 match tag.field_num() {
4501 0 => return Err(::micropb::DecodeError::ZeroField),
4502 _ => {
4503 decoder.skip_wire_value(tag.wire_type())?;
4504 }
4505 }
4506 }
4507 Ok(())
4508 }
313} 4509}
314 4510impl ::micropb::MessageEncode for CtrlMsg_Req_OTAEnd {
315#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4511 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4512 let mut max_size = 0;
4513 ::core::option::Option::Some(max_size)
4514 };
4515 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4516 &self,
4517 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4518 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4519 use ::micropb::{FieldEncode, PbMap};
4520 Ok(())
4521 }
4522 fn compute_size(&self) -> usize {
4523 use ::micropb::{FieldEncode, PbMap};
4524 let mut size = 0;
4525 size
4526 }
4527}
4528#[derive(Debug, Default, PartialEq, Clone)]
316#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4529#[cfg_attr(feature = "defmt", derive(defmt::Format))]
317pub(crate) struct CtrlMsgReqGetWifiCurrTxPower {} 4530pub struct CtrlMsg_Resp_OTAEnd {
318 4531 pub r#resp: i32,
319#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4532}
4533impl CtrlMsg_Resp_OTAEnd {
4534 ///Return a reference to `resp`
4535 #[inline]
4536 pub fn r#resp(&self) -> &i32 {
4537 &self.r#resp
4538 }
4539 ///Return a mutable reference to `resp`
4540 #[inline]
4541 pub fn mut_resp(&mut self) -> &mut i32 {
4542 &mut self.r#resp
4543 }
4544 ///Set the value of `resp`
4545 #[inline]
4546 pub fn set_resp(&mut self, value: i32) -> &mut Self {
4547 self.r#resp = value.into();
4548 self
4549 }
4550 ///Builder method that sets the value of `resp`. Useful for initializing the message.
4551 #[inline]
4552 pub fn init_resp(mut self, value: i32) -> Self {
4553 self.r#resp = value.into();
4554 self
4555 }
4556}
4557impl ::micropb::MessageDecode for CtrlMsg_Resp_OTAEnd {
4558 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4559 &mut self,
4560 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4561 len: usize,
4562 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4563 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4564 let before = decoder.bytes_read();
4565 while decoder.bytes_read() - before < len {
4566 let tag = decoder.decode_tag()?;
4567 match tag.field_num() {
4568 0 => return Err(::micropb::DecodeError::ZeroField),
4569 1u32 => {
4570 let mut_ref = &mut self.r#resp;
4571 {
4572 let val = decoder.decode_int32()?;
4573 let val_ref = &val;
4574 if *val_ref != 0 {
4575 *mut_ref = val as _;
4576 }
4577 };
4578 }
4579 _ => {
4580 decoder.skip_wire_value(tag.wire_type())?;
4581 }
4582 }
4583 }
4584 Ok(())
4585 }
4586}
4587impl ::micropb::MessageEncode for CtrlMsg_Resp_OTAEnd {
4588 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4589 let mut max_size = 0;
4590 if let ::core::option::Option::Some(size) =
4591 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4592 {
4593 max_size += size;
4594 } else {
4595 break 'msg (::core::option::Option::<usize>::None);
4596 };
4597 ::core::option::Option::Some(max_size)
4598 };
4599 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4600 &self,
4601 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4602 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4603 use ::micropb::{FieldEncode, PbMap};
4604 {
4605 let val_ref = &self.r#resp;
4606 if *val_ref != 0 {
4607 encoder.encode_varint32(8u32)?;
4608 encoder.encode_int32(*val_ref as _)?;
4609 }
4610 }
4611 Ok(())
4612 }
4613 fn compute_size(&self) -> usize {
4614 use ::micropb::{FieldEncode, PbMap};
4615 let mut size = 0;
4616 {
4617 let val_ref = &self.r#resp;
4618 if *val_ref != 0 {
4619 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4620 }
4621 }
4622 size
4623 }
4624}
4625#[derive(Debug, Default, PartialEq, Clone)]
320#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4626#[cfg_attr(feature = "defmt", derive(defmt::Format))]
321pub(crate) struct CtrlMsgRespGetWifiCurrTxPower { 4627pub struct CtrlMsg_Req_VendorIEData {
322 #[noproto(tag = "1")] 4628 pub r#element_id: i32,
323 pub wifi_curr_tx_power: u32, 4629 pub r#length: i32,
324 #[noproto(tag = "2")] 4630 pub r#vendor_oui: ::micropb::heapless::Vec<u8, 32>,
325 pub resp: u32, 4631 pub r#vendor_oui_type: i32,
4632 pub r#payload: ::micropb::heapless::Vec<u8, 64>,
326} 4633}
327 4634impl CtrlMsg_Req_VendorIEData {
328#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4635 ///Return a reference to `element_id`
4636 #[inline]
4637 pub fn r#element_id(&self) -> &i32 {
4638 &self.r#element_id
4639 }
4640 ///Return a mutable reference to `element_id`
4641 #[inline]
4642 pub fn mut_element_id(&mut self) -> &mut i32 {
4643 &mut self.r#element_id
4644 }
4645 ///Set the value of `element_id`
4646 #[inline]
4647 pub fn set_element_id(&mut self, value: i32) -> &mut Self {
4648 self.r#element_id = value.into();
4649 self
4650 }
4651 ///Builder method that sets the value of `element_id`. Useful for initializing the message.
4652 #[inline]
4653 pub fn init_element_id(mut self, value: i32) -> Self {
4654 self.r#element_id = value.into();
4655 self
4656 }
4657 ///Return a reference to `length`
4658 #[inline]
4659 pub fn r#length(&self) -> &i32 {
4660 &self.r#length
4661 }
4662 ///Return a mutable reference to `length`
4663 #[inline]
4664 pub fn mut_length(&mut self) -> &mut i32 {
4665 &mut self.r#length
4666 }
4667 ///Set the value of `length`
4668 #[inline]
4669 pub fn set_length(&mut self, value: i32) -> &mut Self {
4670 self.r#length = value.into();
4671 self
4672 }
4673 ///Builder method that sets the value of `length`. Useful for initializing the message.
4674 #[inline]
4675 pub fn init_length(mut self, value: i32) -> Self {
4676 self.r#length = value.into();
4677 self
4678 }
4679 ///Return a reference to `vendor_oui`
4680 #[inline]
4681 pub fn r#vendor_oui(&self) -> &::micropb::heapless::Vec<u8, 32> {
4682 &self.r#vendor_oui
4683 }
4684 ///Return a mutable reference to `vendor_oui`
4685 #[inline]
4686 pub fn mut_vendor_oui(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
4687 &mut self.r#vendor_oui
4688 }
4689 ///Set the value of `vendor_oui`
4690 #[inline]
4691 pub fn set_vendor_oui(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
4692 self.r#vendor_oui = value.into();
4693 self
4694 }
4695 ///Builder method that sets the value of `vendor_oui`. Useful for initializing the message.
4696 #[inline]
4697 pub fn init_vendor_oui(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
4698 self.r#vendor_oui = value.into();
4699 self
4700 }
4701 ///Return a reference to `vendor_oui_type`
4702 #[inline]
4703 pub fn r#vendor_oui_type(&self) -> &i32 {
4704 &self.r#vendor_oui_type
4705 }
4706 ///Return a mutable reference to `vendor_oui_type`
4707 #[inline]
4708 pub fn mut_vendor_oui_type(&mut self) -> &mut i32 {
4709 &mut self.r#vendor_oui_type
4710 }
4711 ///Set the value of `vendor_oui_type`
4712 #[inline]
4713 pub fn set_vendor_oui_type(&mut self, value: i32) -> &mut Self {
4714 self.r#vendor_oui_type = value.into();
4715 self
4716 }
4717 ///Builder method that sets the value of `vendor_oui_type`. Useful for initializing the message.
4718 #[inline]
4719 pub fn init_vendor_oui_type(mut self, value: i32) -> Self {
4720 self.r#vendor_oui_type = value.into();
4721 self
4722 }
4723 ///Return a reference to `payload`
4724 #[inline]
4725 pub fn r#payload(&self) -> &::micropb::heapless::Vec<u8, 64> {
4726 &self.r#payload
4727 }
4728 ///Return a mutable reference to `payload`
4729 #[inline]
4730 pub fn mut_payload(&mut self) -> &mut ::micropb::heapless::Vec<u8, 64> {
4731 &mut self.r#payload
4732 }
4733 ///Set the value of `payload`
4734 #[inline]
4735 pub fn set_payload(&mut self, value: ::micropb::heapless::Vec<u8, 64>) -> &mut Self {
4736 self.r#payload = value.into();
4737 self
4738 }
4739 ///Builder method that sets the value of `payload`. Useful for initializing the message.
4740 #[inline]
4741 pub fn init_payload(mut self, value: ::micropb::heapless::Vec<u8, 64>) -> Self {
4742 self.r#payload = value.into();
4743 self
4744 }
4745}
4746impl ::micropb::MessageDecode for CtrlMsg_Req_VendorIEData {
4747 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
4748 &mut self,
4749 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
4750 len: usize,
4751 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
4752 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
4753 let before = decoder.bytes_read();
4754 while decoder.bytes_read() - before < len {
4755 let tag = decoder.decode_tag()?;
4756 match tag.field_num() {
4757 0 => return Err(::micropb::DecodeError::ZeroField),
4758 1u32 => {
4759 let mut_ref = &mut self.r#element_id;
4760 {
4761 let val = decoder.decode_int32()?;
4762 let val_ref = &val;
4763 if *val_ref != 0 {
4764 *mut_ref = val as _;
4765 }
4766 };
4767 }
4768 2u32 => {
4769 let mut_ref = &mut self.r#length;
4770 {
4771 let val = decoder.decode_int32()?;
4772 let val_ref = &val;
4773 if *val_ref != 0 {
4774 *mut_ref = val as _;
4775 }
4776 };
4777 }
4778 3u32 => {
4779 let mut_ref = &mut self.r#vendor_oui;
4780 {
4781 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
4782 };
4783 }
4784 4u32 => {
4785 let mut_ref = &mut self.r#vendor_oui_type;
4786 {
4787 let val = decoder.decode_int32()?;
4788 let val_ref = &val;
4789 if *val_ref != 0 {
4790 *mut_ref = val as _;
4791 }
4792 };
4793 }
4794 5u32 => {
4795 let mut_ref = &mut self.r#payload;
4796 {
4797 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
4798 };
4799 }
4800 _ => {
4801 decoder.skip_wire_value(tag.wire_type())?;
4802 }
4803 }
4804 }
4805 Ok(())
4806 }
4807}
4808impl ::micropb::MessageEncode for CtrlMsg_Req_VendorIEData {
4809 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
4810 let mut max_size = 0;
4811 if let ::core::option::Option::Some(size) =
4812 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4813 {
4814 max_size += size;
4815 } else {
4816 break 'msg (::core::option::Option::<usize>::None);
4817 };
4818 if let ::core::option::Option::Some(size) =
4819 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4820 {
4821 max_size += size;
4822 } else {
4823 break 'msg (::core::option::Option::<usize>::None);
4824 };
4825 if let ::core::option::Option::Some(size) =
4826 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
4827 {
4828 max_size += size;
4829 } else {
4830 break 'msg (::core::option::Option::<usize>::None);
4831 };
4832 if let ::core::option::Option::Some(size) =
4833 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
4834 {
4835 max_size += size;
4836 } else {
4837 break 'msg (::core::option::Option::<usize>::None);
4838 };
4839 if let ::core::option::Option::Some(size) =
4840 ::micropb::const_map!(::core::option::Option::Some(65usize), |size| size + 1usize)
4841 {
4842 max_size += size;
4843 } else {
4844 break 'msg (::core::option::Option::<usize>::None);
4845 };
4846 ::core::option::Option::Some(max_size)
4847 };
4848 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
4849 &self,
4850 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
4851 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
4852 use ::micropb::{FieldEncode, PbMap};
4853 {
4854 let val_ref = &self.r#element_id;
4855 if *val_ref != 0 {
4856 encoder.encode_varint32(8u32)?;
4857 encoder.encode_int32(*val_ref as _)?;
4858 }
4859 }
4860 {
4861 let val_ref = &self.r#length;
4862 if *val_ref != 0 {
4863 encoder.encode_varint32(16u32)?;
4864 encoder.encode_int32(*val_ref as _)?;
4865 }
4866 }
4867 {
4868 let val_ref = &self.r#vendor_oui;
4869 if !val_ref.is_empty() {
4870 encoder.encode_varint32(26u32)?;
4871 encoder.encode_bytes(val_ref)?;
4872 }
4873 }
4874 {
4875 let val_ref = &self.r#vendor_oui_type;
4876 if *val_ref != 0 {
4877 encoder.encode_varint32(32u32)?;
4878 encoder.encode_int32(*val_ref as _)?;
4879 }
4880 }
4881 {
4882 let val_ref = &self.r#payload;
4883 if !val_ref.is_empty() {
4884 encoder.encode_varint32(42u32)?;
4885 encoder.encode_bytes(val_ref)?;
4886 }
4887 }
4888 Ok(())
4889 }
4890 fn compute_size(&self) -> usize {
4891 use ::micropb::{FieldEncode, PbMap};
4892 let mut size = 0;
4893 {
4894 let val_ref = &self.r#element_id;
4895 if *val_ref != 0 {
4896 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4897 }
4898 }
4899 {
4900 let val_ref = &self.r#length;
4901 if *val_ref != 0 {
4902 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4903 }
4904 }
4905 {
4906 let val_ref = &self.r#vendor_oui;
4907 if !val_ref.is_empty() {
4908 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
4909 }
4910 }
4911 {
4912 let val_ref = &self.r#vendor_oui_type;
4913 if *val_ref != 0 {
4914 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
4915 }
4916 }
4917 {
4918 let val_ref = &self.r#payload;
4919 if !val_ref.is_empty() {
4920 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
4921 }
4922 }
4923 size
4924 }
4925}
4926pub mod CtrlMsg_Req_SetSoftAPVendorSpecificIE_ {
4927 #[derive(Debug, Default, PartialEq, Clone)]
4928 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
4929 pub struct _Hazzer([u8; 1]);
4930 impl _Hazzer {
4931 ///New hazzer with all fields set to off
4932 #[inline]
4933 pub const fn _new() -> Self {
4934 Self([0; 1])
4935 }
4936 ///Query presence of `vendor_ie_data`
4937 #[inline]
4938 pub const fn r#vendor_ie_data(&self) -> bool {
4939 (self.0[0] & 1) != 0
4940 }
4941 ///Set presence of `vendor_ie_data`
4942 #[inline]
4943 pub const fn set_vendor_ie_data(&mut self) -> &mut Self {
4944 let elem = &mut self.0[0];
4945 *elem |= 1;
4946 self
4947 }
4948 ///Clear presence of `vendor_ie_data`
4949 #[inline]
4950 pub const fn clear_vendor_ie_data(&mut self) -> &mut Self {
4951 let elem = &mut self.0[0];
4952 *elem &= !1;
4953 self
4954 }
4955 ///Builder method that sets the presence of `vendor_ie_data`. Useful for initializing the Hazzer.
4956 #[inline]
4957 pub const fn init_vendor_ie_data(mut self) -> Self {
4958 self.set_vendor_ie_data();
4959 self
4960 }
4961 }
4962}
4963#[derive(Debug, Default, Clone)]
329#[cfg_attr(feature = "defmt", derive(defmt::Format))] 4964#[cfg_attr(feature = "defmt", derive(defmt::Format))]
330pub(crate) struct CtrlMsgReqConfigHeartbeat { 4965pub struct CtrlMsg_Req_SetSoftAPVendorSpecificIE {
331 #[noproto(tag = "1")] 4966 pub r#enable: bool,
332 pub enable: bool, 4967 pub r#type: Ctrl_VendorIEType,
333 #[noproto(tag = "2")] 4968 pub r#idx: Ctrl_VendorIEID,
334 pub duration: u32, 4969 pub r#vendor_ie_data: CtrlMsg_Req_VendorIEData,
4970 pub _has: CtrlMsg_Req_SetSoftAPVendorSpecificIE_::_Hazzer,
335} 4971}
336 4972impl ::core::cmp::PartialEq for CtrlMsg_Req_SetSoftAPVendorSpecificIE {
337#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 4973 fn eq(&self, other: &Self) -> bool {
4974 let mut ret = true;
4975 ret &= (self.r#enable == other.r#enable);
4976 ret &= (self.r#type == other.r#type);
4977 ret &= (self.r#idx == other.r#idx);
4978 ret &= (self.r#vendor_ie_data() == other.r#vendor_ie_data());
4979 ret
4980 }
4981}
4982impl CtrlMsg_Req_SetSoftAPVendorSpecificIE {
4983 ///Return a reference to `enable`
4984 #[inline]
4985 pub fn r#enable(&self) -> &bool {
4986 &self.r#enable
4987 }
4988 ///Return a mutable reference to `enable`
4989 #[inline]
4990 pub fn mut_enable(&mut self) -> &mut bool {
4991 &mut self.r#enable
4992 }
4993 ///Set the value of `enable`
4994 #[inline]
4995 pub fn set_enable(&mut self, value: bool) -> &mut Self {
4996 self.r#enable = value.into();
4997 self
4998 }
4999 ///Builder method that sets the value of `enable`. Useful for initializing the message.
5000 #[inline]
5001 pub fn init_enable(mut self, value: bool) -> Self {
5002 self.r#enable = value.into();
5003 self
5004 }
5005 ///Return a reference to `type`
5006 #[inline]
5007 pub fn r#type(&self) -> &Ctrl_VendorIEType {
5008 &self.r#type
5009 }
5010 ///Return a mutable reference to `type`
5011 #[inline]
5012 pub fn mut_type(&mut self) -> &mut Ctrl_VendorIEType {
5013 &mut self.r#type
5014 }
5015 ///Set the value of `type`
5016 #[inline]
5017 pub fn set_type(&mut self, value: Ctrl_VendorIEType) -> &mut Self {
5018 self.r#type = value.into();
5019 self
5020 }
5021 ///Builder method that sets the value of `type`. Useful for initializing the message.
5022 #[inline]
5023 pub fn init_type(mut self, value: Ctrl_VendorIEType) -> Self {
5024 self.r#type = value.into();
5025 self
5026 }
5027 ///Return a reference to `idx`
5028 #[inline]
5029 pub fn r#idx(&self) -> &Ctrl_VendorIEID {
5030 &self.r#idx
5031 }
5032 ///Return a mutable reference to `idx`
5033 #[inline]
5034 pub fn mut_idx(&mut self) -> &mut Ctrl_VendorIEID {
5035 &mut self.r#idx
5036 }
5037 ///Set the value of `idx`
5038 #[inline]
5039 pub fn set_idx(&mut self, value: Ctrl_VendorIEID) -> &mut Self {
5040 self.r#idx = value.into();
5041 self
5042 }
5043 ///Builder method that sets the value of `idx`. Useful for initializing the message.
5044 #[inline]
5045 pub fn init_idx(mut self, value: Ctrl_VendorIEID) -> Self {
5046 self.r#idx = value.into();
5047 self
5048 }
5049 ///Return a reference to `vendor_ie_data` as an `Option`
5050 #[inline]
5051 pub fn r#vendor_ie_data(&self) -> ::core::option::Option<&CtrlMsg_Req_VendorIEData> {
5052 self._has.r#vendor_ie_data().then_some(&self.r#vendor_ie_data)
5053 }
5054 ///Set the value and presence of `vendor_ie_data`
5055 #[inline]
5056 pub fn set_vendor_ie_data(&mut self, value: CtrlMsg_Req_VendorIEData) -> &mut Self {
5057 self._has.set_vendor_ie_data();
5058 self.r#vendor_ie_data = value.into();
5059 self
5060 }
5061 ///Return a mutable reference to `vendor_ie_data` as an `Option`
5062 #[inline]
5063 pub fn mut_vendor_ie_data(&mut self) -> ::core::option::Option<&mut CtrlMsg_Req_VendorIEData> {
5064 self._has.r#vendor_ie_data().then_some(&mut self.r#vendor_ie_data)
5065 }
5066 ///Clear the presence of `vendor_ie_data`
5067 #[inline]
5068 pub fn clear_vendor_ie_data(&mut self) -> &mut Self {
5069 self._has.clear_vendor_ie_data();
5070 self
5071 }
5072 ///Take the value of `vendor_ie_data` and clear its presence
5073 #[inline]
5074 pub fn take_vendor_ie_data(&mut self) -> ::core::option::Option<CtrlMsg_Req_VendorIEData> {
5075 let val = self
5076 ._has
5077 .r#vendor_ie_data()
5078 .then(|| ::core::mem::take(&mut self.r#vendor_ie_data));
5079 self._has.clear_vendor_ie_data();
5080 val
5081 }
5082 ///Builder method that sets the value of `vendor_ie_data`. Useful for initializing the message.
5083 #[inline]
5084 pub fn init_vendor_ie_data(mut self, value: CtrlMsg_Req_VendorIEData) -> Self {
5085 self.set_vendor_ie_data(value);
5086 self
5087 }
5088}
5089impl ::micropb::MessageDecode for CtrlMsg_Req_SetSoftAPVendorSpecificIE {
5090 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5091 &mut self,
5092 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5093 len: usize,
5094 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5095 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5096 let before = decoder.bytes_read();
5097 while decoder.bytes_read() - before < len {
5098 let tag = decoder.decode_tag()?;
5099 match tag.field_num() {
5100 0 => return Err(::micropb::DecodeError::ZeroField),
5101 1u32 => {
5102 let mut_ref = &mut self.r#enable;
5103 {
5104 let val = decoder.decode_bool()?;
5105 let val_ref = &val;
5106 if *val_ref {
5107 *mut_ref = val as _;
5108 }
5109 };
5110 }
5111 2u32 => {
5112 let mut_ref = &mut self.r#type;
5113 {
5114 let val = decoder.decode_int32().map(|n| Ctrl_VendorIEType(n as _))?;
5115 let val_ref = &val;
5116 if val_ref.0 != 0 {
5117 *mut_ref = val as _;
5118 }
5119 };
5120 }
5121 3u32 => {
5122 let mut_ref = &mut self.r#idx;
5123 {
5124 let val = decoder.decode_int32().map(|n| Ctrl_VendorIEID(n as _))?;
5125 let val_ref = &val;
5126 if val_ref.0 != 0 {
5127 *mut_ref = val as _;
5128 }
5129 };
5130 }
5131 4u32 => {
5132 let mut_ref = &mut self.r#vendor_ie_data;
5133 {
5134 mut_ref.decode_len_delimited(decoder)?;
5135 };
5136 self._has.set_vendor_ie_data();
5137 }
5138 _ => {
5139 decoder.skip_wire_value(tag.wire_type())?;
5140 }
5141 }
5142 }
5143 Ok(())
5144 }
5145}
5146impl ::micropb::MessageEncode for CtrlMsg_Req_SetSoftAPVendorSpecificIE {
5147 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5148 let mut max_size = 0;
5149 if let ::core::option::Option::Some(size) =
5150 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
5151 {
5152 max_size += size;
5153 } else {
5154 break 'msg (::core::option::Option::<usize>::None);
5155 };
5156 if let ::core::option::Option::Some(size) =
5157 ::micropb::const_map!(::core::option::Option::Some(Ctrl_VendorIEType::_MAX_SIZE), |size| size
5158 + 1usize)
5159 {
5160 max_size += size;
5161 } else {
5162 break 'msg (::core::option::Option::<usize>::None);
5163 };
5164 if let ::core::option::Option::Some(size) =
5165 ::micropb::const_map!(::core::option::Option::Some(Ctrl_VendorIEID::_MAX_SIZE), |size| size
5166 + 1usize)
5167 {
5168 max_size += size;
5169 } else {
5170 break 'msg (::core::option::Option::<usize>::None);
5171 };
5172 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
5173 ::micropb::const_map!(
5174 <CtrlMsg_Req_VendorIEData as ::micropb::MessageEncode>::MAX_SIZE,
5175 |size| ::micropb::size::sizeof_len_record(size)
5176 ),
5177 |size| size + 1usize
5178 ) {
5179 max_size += size;
5180 } else {
5181 break 'msg (::core::option::Option::<usize>::None);
5182 };
5183 ::core::option::Option::Some(max_size)
5184 };
5185 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5186 &self,
5187 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5188 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5189 use ::micropb::{FieldEncode, PbMap};
5190 {
5191 let val_ref = &self.r#enable;
5192 if *val_ref {
5193 encoder.encode_varint32(8u32)?;
5194 encoder.encode_bool(*val_ref)?;
5195 }
5196 }
5197 {
5198 let val_ref = &self.r#type;
5199 if val_ref.0 != 0 {
5200 encoder.encode_varint32(16u32)?;
5201 encoder.encode_int32(val_ref.0 as _)?;
5202 }
5203 }
5204 {
5205 let val_ref = &self.r#idx;
5206 if val_ref.0 != 0 {
5207 encoder.encode_varint32(24u32)?;
5208 encoder.encode_int32(val_ref.0 as _)?;
5209 }
5210 }
5211 {
5212 if let ::core::option::Option::Some(val_ref) = self.r#vendor_ie_data() {
5213 encoder.encode_varint32(34u32)?;
5214 val_ref.encode_len_delimited(encoder)?;
5215 }
5216 }
5217 Ok(())
5218 }
5219 fn compute_size(&self) -> usize {
5220 use ::micropb::{FieldEncode, PbMap};
5221 let mut size = 0;
5222 {
5223 let val_ref = &self.r#enable;
5224 if *val_ref {
5225 size += 1usize + 1;
5226 }
5227 }
5228 {
5229 let val_ref = &self.r#type;
5230 if val_ref.0 != 0 {
5231 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
5232 }
5233 }
5234 {
5235 let val_ref = &self.r#idx;
5236 if val_ref.0 != 0 {
5237 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
5238 }
5239 }
5240 {
5241 if let ::core::option::Option::Some(val_ref) = self.r#vendor_ie_data() {
5242 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
5243 }
5244 }
5245 size
5246 }
5247}
5248#[derive(Debug, Default, PartialEq, Clone)]
338#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5249#[cfg_attr(feature = "defmt", derive(defmt::Format))]
339pub(crate) struct CtrlMsgRespConfigHeartbeat { 5250pub struct CtrlMsg_Resp_SetSoftAPVendorSpecificIE {
340 #[noproto(tag = "1")] 5251 pub r#resp: i32,
341 pub resp: u32,
342} 5252}
343/// * Event structure * 5253impl CtrlMsg_Resp_SetSoftAPVendorSpecificIE {
344 5254 ///Return a reference to `resp`
345#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5255 #[inline]
5256 pub fn r#resp(&self) -> &i32 {
5257 &self.r#resp
5258 }
5259 ///Return a mutable reference to `resp`
5260 #[inline]
5261 pub fn mut_resp(&mut self) -> &mut i32 {
5262 &mut self.r#resp
5263 }
5264 ///Set the value of `resp`
5265 #[inline]
5266 pub fn set_resp(&mut self, value: i32) -> &mut Self {
5267 self.r#resp = value.into();
5268 self
5269 }
5270 ///Builder method that sets the value of `resp`. Useful for initializing the message.
5271 #[inline]
5272 pub fn init_resp(mut self, value: i32) -> Self {
5273 self.r#resp = value.into();
5274 self
5275 }
5276}
5277impl ::micropb::MessageDecode for CtrlMsg_Resp_SetSoftAPVendorSpecificIE {
5278 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5279 &mut self,
5280 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5281 len: usize,
5282 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5283 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5284 let before = decoder.bytes_read();
5285 while decoder.bytes_read() - before < len {
5286 let tag = decoder.decode_tag()?;
5287 match tag.field_num() {
5288 0 => return Err(::micropb::DecodeError::ZeroField),
5289 1u32 => {
5290 let mut_ref = &mut self.r#resp;
5291 {
5292 let val = decoder.decode_int32()?;
5293 let val_ref = &val;
5294 if *val_ref != 0 {
5295 *mut_ref = val as _;
5296 }
5297 };
5298 }
5299 _ => {
5300 decoder.skip_wire_value(tag.wire_type())?;
5301 }
5302 }
5303 }
5304 Ok(())
5305 }
5306}
5307impl ::micropb::MessageEncode for CtrlMsg_Resp_SetSoftAPVendorSpecificIE {
5308 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5309 let mut max_size = 0;
5310 if let ::core::option::Option::Some(size) =
5311 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5312 {
5313 max_size += size;
5314 } else {
5315 break 'msg (::core::option::Option::<usize>::None);
5316 };
5317 ::core::option::Option::Some(max_size)
5318 };
5319 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5320 &self,
5321 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5322 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5323 use ::micropb::{FieldEncode, PbMap};
5324 {
5325 let val_ref = &self.r#resp;
5326 if *val_ref != 0 {
5327 encoder.encode_varint32(8u32)?;
5328 encoder.encode_int32(*val_ref as _)?;
5329 }
5330 }
5331 Ok(())
5332 }
5333 fn compute_size(&self) -> usize {
5334 use ::micropb::{FieldEncode, PbMap};
5335 let mut size = 0;
5336 {
5337 let val_ref = &self.r#resp;
5338 if *val_ref != 0 {
5339 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5340 }
5341 }
5342 size
5343 }
5344}
5345#[derive(Debug, Default, PartialEq, Clone)]
346#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5346#[cfg_attr(feature = "defmt", derive(defmt::Format))]
347pub(crate) struct CtrlMsgEventEspInit { 5347pub struct CtrlMsg_Req_SetWifiMaxTxPower {
348 #[noproto(tag = "1")] 5348 pub r#wifi_max_tx_power: i32,
349 pub init_data: Vec<u8, 64>,
350} 5349}
351 5350impl CtrlMsg_Req_SetWifiMaxTxPower {
352#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5351 ///Return a reference to `wifi_max_tx_power`
5352 #[inline]
5353 pub fn r#wifi_max_tx_power(&self) -> &i32 {
5354 &self.r#wifi_max_tx_power
5355 }
5356 ///Return a mutable reference to `wifi_max_tx_power`
5357 #[inline]
5358 pub fn mut_wifi_max_tx_power(&mut self) -> &mut i32 {
5359 &mut self.r#wifi_max_tx_power
5360 }
5361 ///Set the value of `wifi_max_tx_power`
5362 #[inline]
5363 pub fn set_wifi_max_tx_power(&mut self, value: i32) -> &mut Self {
5364 self.r#wifi_max_tx_power = value.into();
5365 self
5366 }
5367 ///Builder method that sets the value of `wifi_max_tx_power`. Useful for initializing the message.
5368 #[inline]
5369 pub fn init_wifi_max_tx_power(mut self, value: i32) -> Self {
5370 self.r#wifi_max_tx_power = value.into();
5371 self
5372 }
5373}
5374impl ::micropb::MessageDecode for CtrlMsg_Req_SetWifiMaxTxPower {
5375 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5376 &mut self,
5377 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5378 len: usize,
5379 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5380 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5381 let before = decoder.bytes_read();
5382 while decoder.bytes_read() - before < len {
5383 let tag = decoder.decode_tag()?;
5384 match tag.field_num() {
5385 0 => return Err(::micropb::DecodeError::ZeroField),
5386 1u32 => {
5387 let mut_ref = &mut self.r#wifi_max_tx_power;
5388 {
5389 let val = decoder.decode_int32()?;
5390 let val_ref = &val;
5391 if *val_ref != 0 {
5392 *mut_ref = val as _;
5393 }
5394 };
5395 }
5396 _ => {
5397 decoder.skip_wire_value(tag.wire_type())?;
5398 }
5399 }
5400 }
5401 Ok(())
5402 }
5403}
5404impl ::micropb::MessageEncode for CtrlMsg_Req_SetWifiMaxTxPower {
5405 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5406 let mut max_size = 0;
5407 if let ::core::option::Option::Some(size) =
5408 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5409 {
5410 max_size += size;
5411 } else {
5412 break 'msg (::core::option::Option::<usize>::None);
5413 };
5414 ::core::option::Option::Some(max_size)
5415 };
5416 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5417 &self,
5418 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5419 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5420 use ::micropb::{FieldEncode, PbMap};
5421 {
5422 let val_ref = &self.r#wifi_max_tx_power;
5423 if *val_ref != 0 {
5424 encoder.encode_varint32(8u32)?;
5425 encoder.encode_int32(*val_ref as _)?;
5426 }
5427 }
5428 Ok(())
5429 }
5430 fn compute_size(&self) -> usize {
5431 use ::micropb::{FieldEncode, PbMap};
5432 let mut size = 0;
5433 {
5434 let val_ref = &self.r#wifi_max_tx_power;
5435 if *val_ref != 0 {
5436 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5437 }
5438 }
5439 size
5440 }
5441}
5442#[derive(Debug, Default, PartialEq, Clone)]
353#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5443#[cfg_attr(feature = "defmt", derive(defmt::Format))]
354pub(crate) struct CtrlMsgEventHeartbeat { 5444pub struct CtrlMsg_Resp_SetWifiMaxTxPower {
355 #[noproto(tag = "1")] 5445 pub r#resp: i32,
356 pub hb_num: u32,
357} 5446}
358 5447impl CtrlMsg_Resp_SetWifiMaxTxPower {
359#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5448 ///Return a reference to `resp`
5449 #[inline]
5450 pub fn r#resp(&self) -> &i32 {
5451 &self.r#resp
5452 }
5453 ///Return a mutable reference to `resp`
5454 #[inline]
5455 pub fn mut_resp(&mut self) -> &mut i32 {
5456 &mut self.r#resp
5457 }
5458 ///Set the value of `resp`
5459 #[inline]
5460 pub fn set_resp(&mut self, value: i32) -> &mut Self {
5461 self.r#resp = value.into();
5462 self
5463 }
5464 ///Builder method that sets the value of `resp`. Useful for initializing the message.
5465 #[inline]
5466 pub fn init_resp(mut self, value: i32) -> Self {
5467 self.r#resp = value.into();
5468 self
5469 }
5470}
5471impl ::micropb::MessageDecode for CtrlMsg_Resp_SetWifiMaxTxPower {
5472 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5473 &mut self,
5474 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5475 len: usize,
5476 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5477 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5478 let before = decoder.bytes_read();
5479 while decoder.bytes_read() - before < len {
5480 let tag = decoder.decode_tag()?;
5481 match tag.field_num() {
5482 0 => return Err(::micropb::DecodeError::ZeroField),
5483 1u32 => {
5484 let mut_ref = &mut self.r#resp;
5485 {
5486 let val = decoder.decode_int32()?;
5487 let val_ref = &val;
5488 if *val_ref != 0 {
5489 *mut_ref = val as _;
5490 }
5491 };
5492 }
5493 _ => {
5494 decoder.skip_wire_value(tag.wire_type())?;
5495 }
5496 }
5497 }
5498 Ok(())
5499 }
5500}
5501impl ::micropb::MessageEncode for CtrlMsg_Resp_SetWifiMaxTxPower {
5502 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5503 let mut max_size = 0;
5504 if let ::core::option::Option::Some(size) =
5505 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5506 {
5507 max_size += size;
5508 } else {
5509 break 'msg (::core::option::Option::<usize>::None);
5510 };
5511 ::core::option::Option::Some(max_size)
5512 };
5513 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5514 &self,
5515 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5516 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5517 use ::micropb::{FieldEncode, PbMap};
5518 {
5519 let val_ref = &self.r#resp;
5520 if *val_ref != 0 {
5521 encoder.encode_varint32(8u32)?;
5522 encoder.encode_int32(*val_ref as _)?;
5523 }
5524 }
5525 Ok(())
5526 }
5527 fn compute_size(&self) -> usize {
5528 use ::micropb::{FieldEncode, PbMap};
5529 let mut size = 0;
5530 {
5531 let val_ref = &self.r#resp;
5532 if *val_ref != 0 {
5533 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5534 }
5535 }
5536 size
5537 }
5538}
5539#[derive(Debug, Default, PartialEq, Clone)]
360#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5540#[cfg_attr(feature = "defmt", derive(defmt::Format))]
361pub(crate) struct CtrlMsgEventStationDisconnectFromAp { 5541pub struct CtrlMsg_Req_GetWifiCurrTxPower {}
362 #[noproto(tag = "1")] 5542impl CtrlMsg_Req_GetWifiCurrTxPower {}
363 pub resp: u32, 5543impl ::micropb::MessageDecode for CtrlMsg_Req_GetWifiCurrTxPower {
5544 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5545 &mut self,
5546 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5547 len: usize,
5548 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5549 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5550 let before = decoder.bytes_read();
5551 while decoder.bytes_read() - before < len {
5552 let tag = decoder.decode_tag()?;
5553 match tag.field_num() {
5554 0 => return Err(::micropb::DecodeError::ZeroField),
5555 _ => {
5556 decoder.skip_wire_value(tag.wire_type())?;
5557 }
5558 }
5559 }
5560 Ok(())
5561 }
364} 5562}
365 5563impl ::micropb::MessageEncode for CtrlMsg_Req_GetWifiCurrTxPower {
366#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5564 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5565 let mut max_size = 0;
5566 ::core::option::Option::Some(max_size)
5567 };
5568 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5569 &self,
5570 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5571 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5572 use ::micropb::{FieldEncode, PbMap};
5573 Ok(())
5574 }
5575 fn compute_size(&self) -> usize {
5576 use ::micropb::{FieldEncode, PbMap};
5577 let mut size = 0;
5578 size
5579 }
5580}
5581#[derive(Debug, Default, PartialEq, Clone)]
367#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5582#[cfg_attr(feature = "defmt", derive(defmt::Format))]
368pub(crate) struct CtrlMsgEventStationDisconnectFromEspSoftAp { 5583pub struct CtrlMsg_Resp_GetWifiCurrTxPower {
369 #[noproto(tag = "1")] 5584 pub r#wifi_curr_tx_power: i32,
370 pub resp: u32, 5585 pub r#resp: i32,
371 #[noproto(tag = "2")]
372 pub mac: String<32>,
373} 5586}
374 5587impl CtrlMsg_Resp_GetWifiCurrTxPower {
375#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5588 ///Return a reference to `wifi_curr_tx_power`
376#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5589 #[inline]
377pub(crate) struct CtrlMsg { 5590 pub fn r#wifi_curr_tx_power(&self) -> &i32 {
378 /// msg_type could be req, resp or Event 5591 &self.r#wifi_curr_tx_power
379 #[noproto(tag = "1")] 5592 }
380 pub msg_type: CtrlMsgType, 5593 ///Return a mutable reference to `wifi_curr_tx_power`
381 /// msg id 5594 #[inline]
382 #[noproto(tag = "2")] 5595 pub fn mut_wifi_curr_tx_power(&mut self) -> &mut i32 {
383 pub msg_id: CtrlMsgId, 5596 &mut self.r#wifi_curr_tx_power
384 /// union of all msg ids 5597 }
385 #[noproto( 5598 ///Set the value of `wifi_curr_tx_power`
386 oneof, 5599 #[inline]
387 tags = "101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 301, 302, 303, 304" 5600 pub fn set_wifi_curr_tx_power(&mut self, value: i32) -> &mut Self {
388 )] 5601 self.r#wifi_curr_tx_power = value.into();
389 pub payload: Option<CtrlMsgPayload>, 5602 self
5603 }
5604 ///Builder method that sets the value of `wifi_curr_tx_power`. Useful for initializing the message.
5605 #[inline]
5606 pub fn init_wifi_curr_tx_power(mut self, value: i32) -> Self {
5607 self.r#wifi_curr_tx_power = value.into();
5608 self
5609 }
5610 ///Return a reference to `resp`
5611 #[inline]
5612 pub fn r#resp(&self) -> &i32 {
5613 &self.r#resp
5614 }
5615 ///Return a mutable reference to `resp`
5616 #[inline]
5617 pub fn mut_resp(&mut self) -> &mut i32 {
5618 &mut self.r#resp
5619 }
5620 ///Set the value of `resp`
5621 #[inline]
5622 pub fn set_resp(&mut self, value: i32) -> &mut Self {
5623 self.r#resp = value.into();
5624 self
5625 }
5626 ///Builder method that sets the value of `resp`. Useful for initializing the message.
5627 #[inline]
5628 pub fn init_resp(mut self, value: i32) -> Self {
5629 self.r#resp = value.into();
5630 self
5631 }
390} 5632}
391 5633impl ::micropb::MessageDecode for CtrlMsg_Resp_GetWifiCurrTxPower {
392/// union of all msg ids 5634 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
393#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)] 5635 &mut self,
394#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5636 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
395pub(crate) enum CtrlMsgPayload { 5637 len: usize,
396 /// * Requests * 5638 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
397 #[noproto(tag = "101")] 5639 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
398 ReqGetMacAddress(CtrlMsgReqGetMacAddress), 5640 let before = decoder.bytes_read();
399 #[noproto(tag = "102")] 5641 while decoder.bytes_read() - before < len {
400 ReqSetMacAddress(CtrlMsgReqSetMacAddress), 5642 let tag = decoder.decode_tag()?;
401 #[noproto(tag = "103")] 5643 match tag.field_num() {
402 ReqGetWifiMode(CtrlMsgReqGetMode), 5644 0 => return Err(::micropb::DecodeError::ZeroField),
403 #[noproto(tag = "104")] 5645 1u32 => {
404 ReqSetWifiMode(CtrlMsgReqSetMode), 5646 let mut_ref = &mut self.r#wifi_curr_tx_power;
405 #[noproto(tag = "105")] 5647 {
406 ReqScanApList(CtrlMsgReqScanResult), 5648 let val = decoder.decode_int32()?;
407 #[noproto(tag = "106")] 5649 let val_ref = &val;
408 ReqGetApConfig(CtrlMsgReqGetApConfig), 5650 if *val_ref != 0 {
409 #[noproto(tag = "107")] 5651 *mut_ref = val as _;
410 ReqConnectAp(CtrlMsgReqConnectAp), 5652 }
411 #[noproto(tag = "108")] 5653 };
412 ReqDisconnectAp(CtrlMsgReqGetStatus), 5654 }
413 #[noproto(tag = "109")] 5655 2u32 => {
414 ReqGetSoftapConfig(CtrlMsgReqGetSoftApConfig), 5656 let mut_ref = &mut self.r#resp;
415 #[noproto(tag = "110")] 5657 {
416 ReqSetSoftapVendorSpecificIe(CtrlMsgReqSetSoftApVendorSpecificIe), 5658 let val = decoder.decode_int32()?;
417 #[noproto(tag = "111")] 5659 let val_ref = &val;
418 ReqStartSoftap(CtrlMsgReqStartSoftAp), 5660 if *val_ref != 0 {
419 #[noproto(tag = "112")] 5661 *mut_ref = val as _;
420 ReqSoftapConnectedStasList(CtrlMsgReqSoftApConnectedSta), 5662 }
421 #[noproto(tag = "113")] 5663 };
422 ReqStopSoftap(CtrlMsgReqGetStatus), 5664 }
423 #[noproto(tag = "114")] 5665 _ => {
424 ReqSetPowerSaveMode(CtrlMsgReqSetMode), 5666 decoder.skip_wire_value(tag.wire_type())?;
425 #[noproto(tag = "115")] 5667 }
426 ReqGetPowerSaveMode(CtrlMsgReqGetMode), 5668 }
427 #[noproto(tag = "116")] 5669 }
428 ReqOtaBegin(CtrlMsgReqOtaBegin), 5670 Ok(())
429 #[noproto(tag = "117")] 5671 }
430 ReqOtaWrite(CtrlMsgReqOtaWrite),
431 #[noproto(tag = "118")]
432 ReqOtaEnd(CtrlMsgReqOtaEnd),
433 #[noproto(tag = "119")]
434 ReqSetWifiMaxTxPower(CtrlMsgReqSetWifiMaxTxPower),
435 #[noproto(tag = "120")]
436 ReqGetWifiCurrTxPower(CtrlMsgReqGetWifiCurrTxPower),
437 #[noproto(tag = "121")]
438 ReqConfigHeartbeat(CtrlMsgReqConfigHeartbeat),
439 /// * Responses *
440 #[noproto(tag = "201")]
441 RespGetMacAddress(CtrlMsgRespGetMacAddress),
442 #[noproto(tag = "202")]
443 RespSetMacAddress(CtrlMsgRespSetMacAddress),
444 #[noproto(tag = "203")]
445 RespGetWifiMode(CtrlMsgRespGetMode),
446 #[noproto(tag = "204")]
447 RespSetWifiMode(CtrlMsgRespSetMode),
448 #[noproto(tag = "205")]
449 RespScanApList(CtrlMsgRespScanResult),
450 #[noproto(tag = "206")]
451 RespGetApConfig(CtrlMsgRespGetApConfig),
452 #[noproto(tag = "207")]
453 RespConnectAp(CtrlMsgRespConnectAp),
454 #[noproto(tag = "208")]
455 RespDisconnectAp(CtrlMsgRespGetStatus),
456 #[noproto(tag = "209")]
457 RespGetSoftapConfig(CtrlMsgRespGetSoftApConfig),
458 #[noproto(tag = "210")]
459 RespSetSoftapVendorSpecificIe(CtrlMsgRespSetSoftApVendorSpecificIe),
460 #[noproto(tag = "211")]
461 RespStartSoftap(CtrlMsgRespStartSoftAp),
462 #[noproto(tag = "212")]
463 RespSoftapConnectedStasList(CtrlMsgRespSoftApConnectedSta),
464 #[noproto(tag = "213")]
465 RespStopSoftap(CtrlMsgRespGetStatus),
466 #[noproto(tag = "214")]
467 RespSetPowerSaveMode(CtrlMsgRespSetMode),
468 #[noproto(tag = "215")]
469 RespGetPowerSaveMode(CtrlMsgRespGetMode),
470 #[noproto(tag = "216")]
471 RespOtaBegin(CtrlMsgRespOtaBegin),
472 #[noproto(tag = "217")]
473 RespOtaWrite(CtrlMsgRespOtaWrite),
474 #[noproto(tag = "218")]
475 RespOtaEnd(CtrlMsgRespOtaEnd),
476 #[noproto(tag = "219")]
477 RespSetWifiMaxTxPower(CtrlMsgRespSetWifiMaxTxPower),
478 #[noproto(tag = "220")]
479 RespGetWifiCurrTxPower(CtrlMsgRespGetWifiCurrTxPower),
480 #[noproto(tag = "221")]
481 RespConfigHeartbeat(CtrlMsgRespConfigHeartbeat),
482 /// * Notifications *
483 #[noproto(tag = "301")]
484 EventEspInit(CtrlMsgEventEspInit),
485 #[noproto(tag = "302")]
486 EventHeartbeat(CtrlMsgEventHeartbeat),
487 #[noproto(tag = "303")]
488 EventStationDisconnectFromAp(CtrlMsgEventStationDisconnectFromAp),
489 #[noproto(tag = "304")]
490 EventStationDisconnectFromEspSoftAp(CtrlMsgEventStationDisconnectFromEspSoftAp),
491} 5672}
492 5673impl ::micropb::MessageEncode for CtrlMsg_Resp_GetWifiCurrTxPower {
493/// Enums similar to ESP IDF 5674 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
494#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 5675 let mut max_size = 0;
495#[repr(u32)] 5676 if let ::core::option::Option::Some(size) =
496#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5677 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
497pub(crate) enum CtrlVendorIeType { 5678 {
498 #[default] 5679 max_size += size;
499 Beacon = 0, 5680 } else {
500 ProbeReq = 1, 5681 break 'msg (::core::option::Option::<usize>::None);
501 ProbeResp = 2, 5682 };
502 AssocReq = 3, 5683 if let ::core::option::Option::Some(size) =
503 AssocResp = 4, 5684 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5685 {
5686 max_size += size;
5687 } else {
5688 break 'msg (::core::option::Option::<usize>::None);
5689 };
5690 ::core::option::Option::Some(max_size)
5691 };
5692 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5693 &self,
5694 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5695 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5696 use ::micropb::{FieldEncode, PbMap};
5697 {
5698 let val_ref = &self.r#wifi_curr_tx_power;
5699 if *val_ref != 0 {
5700 encoder.encode_varint32(8u32)?;
5701 encoder.encode_int32(*val_ref as _)?;
5702 }
5703 }
5704 {
5705 let val_ref = &self.r#resp;
5706 if *val_ref != 0 {
5707 encoder.encode_varint32(16u32)?;
5708 encoder.encode_int32(*val_ref as _)?;
5709 }
5710 }
5711 Ok(())
5712 }
5713 fn compute_size(&self) -> usize {
5714 use ::micropb::{FieldEncode, PbMap};
5715 let mut size = 0;
5716 {
5717 let val_ref = &self.r#wifi_curr_tx_power;
5718 if *val_ref != 0 {
5719 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5720 }
5721 }
5722 {
5723 let val_ref = &self.r#resp;
5724 if *val_ref != 0 {
5725 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5726 }
5727 }
5728 size
5729 }
504} 5730}
505 5731#[derive(Debug, Default, PartialEq, Clone)]
506#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
507#[repr(u32)]
508#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5732#[cfg_attr(feature = "defmt", derive(defmt::Format))]
509pub(crate) enum CtrlVendorIeid { 5733pub struct CtrlMsg_Req_ConfigHeartbeat {
510 #[default] 5734 pub r#enable: bool,
511 Id0 = 0, 5735 pub r#duration: i32,
512 Id1 = 1,
513} 5736}
514 5737impl CtrlMsg_Req_ConfigHeartbeat {
515#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 5738 ///Return a reference to `enable`
516#[repr(u32)] 5739 #[inline]
5740 pub fn r#enable(&self) -> &bool {
5741 &self.r#enable
5742 }
5743 ///Return a mutable reference to `enable`
5744 #[inline]
5745 pub fn mut_enable(&mut self) -> &mut bool {
5746 &mut self.r#enable
5747 }
5748 ///Set the value of `enable`
5749 #[inline]
5750 pub fn set_enable(&mut self, value: bool) -> &mut Self {
5751 self.r#enable = value.into();
5752 self
5753 }
5754 ///Builder method that sets the value of `enable`. Useful for initializing the message.
5755 #[inline]
5756 pub fn init_enable(mut self, value: bool) -> Self {
5757 self.r#enable = value.into();
5758 self
5759 }
5760 ///Return a reference to `duration`
5761 #[inline]
5762 pub fn r#duration(&self) -> &i32 {
5763 &self.r#duration
5764 }
5765 ///Return a mutable reference to `duration`
5766 #[inline]
5767 pub fn mut_duration(&mut self) -> &mut i32 {
5768 &mut self.r#duration
5769 }
5770 ///Set the value of `duration`
5771 #[inline]
5772 pub fn set_duration(&mut self, value: i32) -> &mut Self {
5773 self.r#duration = value.into();
5774 self
5775 }
5776 ///Builder method that sets the value of `duration`. Useful for initializing the message.
5777 #[inline]
5778 pub fn init_duration(mut self, value: i32) -> Self {
5779 self.r#duration = value.into();
5780 self
5781 }
5782}
5783impl ::micropb::MessageDecode for CtrlMsg_Req_ConfigHeartbeat {
5784 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5785 &mut self,
5786 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5787 len: usize,
5788 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5789 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5790 let before = decoder.bytes_read();
5791 while decoder.bytes_read() - before < len {
5792 let tag = decoder.decode_tag()?;
5793 match tag.field_num() {
5794 0 => return Err(::micropb::DecodeError::ZeroField),
5795 1u32 => {
5796 let mut_ref = &mut self.r#enable;
5797 {
5798 let val = decoder.decode_bool()?;
5799 let val_ref = &val;
5800 if *val_ref {
5801 *mut_ref = val as _;
5802 }
5803 };
5804 }
5805 2u32 => {
5806 let mut_ref = &mut self.r#duration;
5807 {
5808 let val = decoder.decode_int32()?;
5809 let val_ref = &val;
5810 if *val_ref != 0 {
5811 *mut_ref = val as _;
5812 }
5813 };
5814 }
5815 _ => {
5816 decoder.skip_wire_value(tag.wire_type())?;
5817 }
5818 }
5819 }
5820 Ok(())
5821 }
5822}
5823impl ::micropb::MessageEncode for CtrlMsg_Req_ConfigHeartbeat {
5824 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5825 let mut max_size = 0;
5826 if let ::core::option::Option::Some(size) =
5827 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
5828 {
5829 max_size += size;
5830 } else {
5831 break 'msg (::core::option::Option::<usize>::None);
5832 };
5833 if let ::core::option::Option::Some(size) =
5834 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5835 {
5836 max_size += size;
5837 } else {
5838 break 'msg (::core::option::Option::<usize>::None);
5839 };
5840 ::core::option::Option::Some(max_size)
5841 };
5842 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5843 &self,
5844 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5845 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5846 use ::micropb::{FieldEncode, PbMap};
5847 {
5848 let val_ref = &self.r#enable;
5849 if *val_ref {
5850 encoder.encode_varint32(8u32)?;
5851 encoder.encode_bool(*val_ref)?;
5852 }
5853 }
5854 {
5855 let val_ref = &self.r#duration;
5856 if *val_ref != 0 {
5857 encoder.encode_varint32(16u32)?;
5858 encoder.encode_int32(*val_ref as _)?;
5859 }
5860 }
5861 Ok(())
5862 }
5863 fn compute_size(&self) -> usize {
5864 use ::micropb::{FieldEncode, PbMap};
5865 let mut size = 0;
5866 {
5867 let val_ref = &self.r#enable;
5868 if *val_ref {
5869 size += 1usize + 1;
5870 }
5871 }
5872 {
5873 let val_ref = &self.r#duration;
5874 if *val_ref != 0 {
5875 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5876 }
5877 }
5878 size
5879 }
5880}
5881#[derive(Debug, Default, PartialEq, Clone)]
517#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5882#[cfg_attr(feature = "defmt", derive(defmt::Format))]
518pub(crate) enum CtrlWifiMode { 5883pub struct CtrlMsg_Resp_ConfigHeartbeat {
519 #[default] 5884 pub r#resp: i32,
520 None = 0,
521 Sta = 1,
522 Ap = 2,
523 Apsta = 3,
524} 5885}
525 5886impl CtrlMsg_Resp_ConfigHeartbeat {
526#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 5887 ///Return a reference to `resp`
527#[repr(u32)] 5888 #[inline]
5889 pub fn r#resp(&self) -> &i32 {
5890 &self.r#resp
5891 }
5892 ///Return a mutable reference to `resp`
5893 #[inline]
5894 pub fn mut_resp(&mut self) -> &mut i32 {
5895 &mut self.r#resp
5896 }
5897 ///Set the value of `resp`
5898 #[inline]
5899 pub fn set_resp(&mut self, value: i32) -> &mut Self {
5900 self.r#resp = value.into();
5901 self
5902 }
5903 ///Builder method that sets the value of `resp`. Useful for initializing the message.
5904 #[inline]
5905 pub fn init_resp(mut self, value: i32) -> Self {
5906 self.r#resp = value.into();
5907 self
5908 }
5909}
5910impl ::micropb::MessageDecode for CtrlMsg_Resp_ConfigHeartbeat {
5911 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
5912 &mut self,
5913 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
5914 len: usize,
5915 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
5916 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
5917 let before = decoder.bytes_read();
5918 while decoder.bytes_read() - before < len {
5919 let tag = decoder.decode_tag()?;
5920 match tag.field_num() {
5921 0 => return Err(::micropb::DecodeError::ZeroField),
5922 1u32 => {
5923 let mut_ref = &mut self.r#resp;
5924 {
5925 let val = decoder.decode_int32()?;
5926 let val_ref = &val;
5927 if *val_ref != 0 {
5928 *mut_ref = val as _;
5929 }
5930 };
5931 }
5932 _ => {
5933 decoder.skip_wire_value(tag.wire_type())?;
5934 }
5935 }
5936 }
5937 Ok(())
5938 }
5939}
5940impl ::micropb::MessageEncode for CtrlMsg_Resp_ConfigHeartbeat {
5941 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
5942 let mut max_size = 0;
5943 if let ::core::option::Option::Some(size) =
5944 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
5945 {
5946 max_size += size;
5947 } else {
5948 break 'msg (::core::option::Option::<usize>::None);
5949 };
5950 ::core::option::Option::Some(max_size)
5951 };
5952 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
5953 &self,
5954 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
5955 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
5956 use ::micropb::{FieldEncode, PbMap};
5957 {
5958 let val_ref = &self.r#resp;
5959 if *val_ref != 0 {
5960 encoder.encode_varint32(8u32)?;
5961 encoder.encode_int32(*val_ref as _)?;
5962 }
5963 }
5964 Ok(())
5965 }
5966 fn compute_size(&self) -> usize {
5967 use ::micropb::{FieldEncode, PbMap};
5968 let mut size = 0;
5969 {
5970 let val_ref = &self.r#resp;
5971 if *val_ref != 0 {
5972 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
5973 }
5974 }
5975 size
5976 }
5977}
5978#[derive(Debug, Default, PartialEq, Clone)]
528#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5979#[cfg_attr(feature = "defmt", derive(defmt::Format))]
529pub(crate) enum CtrlWifiBw { 5980pub struct CtrlMsg_Req_EnableDisable {
530 #[default] 5981 pub r#feature: u32,
531 BwInvalid = 0, 5982 pub r#enable: bool,
532 Ht20 = 1,
533 Ht40 = 2,
534} 5983}
535 5984impl CtrlMsg_Req_EnableDisable {
536#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 5985 ///Return a reference to `feature`
537#[repr(u32)] 5986 #[inline]
5987 pub fn r#feature(&self) -> &u32 {
5988 &self.r#feature
5989 }
5990 ///Return a mutable reference to `feature`
5991 #[inline]
5992 pub fn mut_feature(&mut self) -> &mut u32 {
5993 &mut self.r#feature
5994 }
5995 ///Set the value of `feature`
5996 #[inline]
5997 pub fn set_feature(&mut self, value: u32) -> &mut Self {
5998 self.r#feature = value.into();
5999 self
6000 }
6001 ///Builder method that sets the value of `feature`. Useful for initializing the message.
6002 #[inline]
6003 pub fn init_feature(mut self, value: u32) -> Self {
6004 self.r#feature = value.into();
6005 self
6006 }
6007 ///Return a reference to `enable`
6008 #[inline]
6009 pub fn r#enable(&self) -> &bool {
6010 &self.r#enable
6011 }
6012 ///Return a mutable reference to `enable`
6013 #[inline]
6014 pub fn mut_enable(&mut self) -> &mut bool {
6015 &mut self.r#enable
6016 }
6017 ///Set the value of `enable`
6018 #[inline]
6019 pub fn set_enable(&mut self, value: bool) -> &mut Self {
6020 self.r#enable = value.into();
6021 self
6022 }
6023 ///Builder method that sets the value of `enable`. Useful for initializing the message.
6024 #[inline]
6025 pub fn init_enable(mut self, value: bool) -> Self {
6026 self.r#enable = value.into();
6027 self
6028 }
6029}
6030impl ::micropb::MessageDecode for CtrlMsg_Req_EnableDisable {
6031 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
6032 &mut self,
6033 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
6034 len: usize,
6035 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6036 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6037 let before = decoder.bytes_read();
6038 while decoder.bytes_read() - before < len {
6039 let tag = decoder.decode_tag()?;
6040 match tag.field_num() {
6041 0 => return Err(::micropb::DecodeError::ZeroField),
6042 1u32 => {
6043 let mut_ref = &mut self.r#feature;
6044 {
6045 let val = decoder.decode_varint32()?;
6046 let val_ref = &val;
6047 if *val_ref != 0 {
6048 *mut_ref = val as _;
6049 }
6050 };
6051 }
6052 2u32 => {
6053 let mut_ref = &mut self.r#enable;
6054 {
6055 let val = decoder.decode_bool()?;
6056 let val_ref = &val;
6057 if *val_ref {
6058 *mut_ref = val as _;
6059 }
6060 };
6061 }
6062 _ => {
6063 decoder.skip_wire_value(tag.wire_type())?;
6064 }
6065 }
6066 }
6067 Ok(())
6068 }
6069}
6070impl ::micropb::MessageEncode for CtrlMsg_Req_EnableDisable {
6071 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
6072 let mut max_size = 0;
6073 if let ::core::option::Option::Some(size) =
6074 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6075 {
6076 max_size += size;
6077 } else {
6078 break 'msg (::core::option::Option::<usize>::None);
6079 };
6080 if let ::core::option::Option::Some(size) =
6081 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
6082 {
6083 max_size += size;
6084 } else {
6085 break 'msg (::core::option::Option::<usize>::None);
6086 };
6087 ::core::option::Option::Some(max_size)
6088 };
6089 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6090 &self,
6091 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6092 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6093 use ::micropb::{FieldEncode, PbMap};
6094 {
6095 let val_ref = &self.r#feature;
6096 if *val_ref != 0 {
6097 encoder.encode_varint32(8u32)?;
6098 encoder.encode_varint32(*val_ref as _)?;
6099 }
6100 }
6101 {
6102 let val_ref = &self.r#enable;
6103 if *val_ref {
6104 encoder.encode_varint32(16u32)?;
6105 encoder.encode_bool(*val_ref)?;
6106 }
6107 }
6108 Ok(())
6109 }
6110 fn compute_size(&self) -> usize {
6111 use ::micropb::{FieldEncode, PbMap};
6112 let mut size = 0;
6113 {
6114 let val_ref = &self.r#feature;
6115 if *val_ref != 0 {
6116 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6117 }
6118 }
6119 {
6120 let val_ref = &self.r#enable;
6121 if *val_ref {
6122 size += 1usize + 1;
6123 }
6124 }
6125 size
6126 }
6127}
6128#[derive(Debug, Default, PartialEq, Clone)]
538#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
539pub(crate) enum CtrlWifiPowerSave { 6130pub struct CtrlMsg_Resp_EnableDisable {
540 #[default] 6131 pub r#resp: i32,
541 PsInvalid = 0,
542 MinModem = 1,
543 MaxModem = 2,
544} 6132}
545 6133impl CtrlMsg_Resp_EnableDisable {
546/// Wifi Security Settings 6134 ///Return a reference to `resp`
547#[allow(missing_docs)] 6135 #[inline]
548#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 6136 pub fn r#resp(&self) -> &i32 {
549#[repr(u32)] 6137 &self.r#resp
550#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6138 }
551pub enum CtrlWifiSecProt { 6139 ///Return a mutable reference to `resp`
552 #[default] 6140 #[inline]
553 Open = 0, 6141 pub fn mut_resp(&mut self) -> &mut i32 {
554 Wep = 1, 6142 &mut self.r#resp
555 WpaPsk = 2, 6143 }
556 Wpa2Psk = 3, 6144 ///Set the value of `resp`
557 WpaWpa2Psk = 4, 6145 #[inline]
558 Wpa2Enterprise = 5, 6146 pub fn set_resp(&mut self, value: i32) -> &mut Self {
559 Wpa3Psk = 6, 6147 self.r#resp = value.into();
560 Wpa2Wpa3Psk = 7, 6148 self
6149 }
6150 ///Builder method that sets the value of `resp`. Useful for initializing the message.
6151 #[inline]
6152 pub fn init_resp(mut self, value: i32) -> Self {
6153 self.r#resp = value.into();
6154 self
6155 }
561} 6156}
562 6157impl ::micropb::MessageDecode for CtrlMsg_Resp_EnableDisable {
563/// enums for Control path 6158 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
564#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 6159 &mut self,
565#[repr(u32)] 6160 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
566#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6161 len: usize,
567pub(crate) enum CtrlStatus { 6162 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
568 #[default] 6163 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
569 Connected = 0, 6164 let before = decoder.bytes_read();
570 NotConnected = 1, 6165 while decoder.bytes_read() - before < len {
571 NoApFound = 2, 6166 let tag = decoder.decode_tag()?;
572 ConnectionFail = 3, 6167 match tag.field_num() {
573 InvalidArgument = 4, 6168 0 => return Err(::micropb::DecodeError::ZeroField),
574 OutOfRange = 5, 6169 1u32 => {
6170 let mut_ref = &mut self.r#resp;
6171 {
6172 let val = decoder.decode_int32()?;
6173 let val_ref = &val;
6174 if *val_ref != 0 {
6175 *mut_ref = val as _;
6176 }
6177 };
6178 }
6179 _ => {
6180 decoder.skip_wire_value(tag.wire_type())?;
6181 }
6182 }
6183 }
6184 Ok(())
6185 }
575} 6186}
576 6187impl ::micropb::MessageEncode for CtrlMsg_Resp_EnableDisable {
577#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 6188 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
578#[repr(u32)] 6189 let mut max_size = 0;
6190 if let ::core::option::Option::Some(size) =
6191 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
6192 {
6193 max_size += size;
6194 } else {
6195 break 'msg (::core::option::Option::<usize>::None);
6196 };
6197 ::core::option::Option::Some(max_size)
6198 };
6199 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6200 &self,
6201 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6202 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6203 use ::micropb::{FieldEncode, PbMap};
6204 {
6205 let val_ref = &self.r#resp;
6206 if *val_ref != 0 {
6207 encoder.encode_varint32(8u32)?;
6208 encoder.encode_int32(*val_ref as _)?;
6209 }
6210 }
6211 Ok(())
6212 }
6213 fn compute_size(&self) -> usize {
6214 use ::micropb::{FieldEncode, PbMap};
6215 let mut size = 0;
6216 {
6217 let val_ref = &self.r#resp;
6218 if *val_ref != 0 {
6219 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
6220 }
6221 }
6222 size
6223 }
6224}
6225#[derive(Debug, Default, PartialEq, Clone)]
579#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6226#[cfg_attr(feature = "defmt", derive(defmt::Format))]
580pub(crate) enum CtrlMsgType { 6227pub struct CtrlMsg_Req_GetFwVersion {}
581 #[default] 6228impl CtrlMsg_Req_GetFwVersion {}
582 MsgTypeInvalid = 0, 6229impl ::micropb::MessageDecode for CtrlMsg_Req_GetFwVersion {
583 Req = 1, 6230 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
584 Resp = 2, 6231 &mut self,
585 Event = 3, 6232 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
586 MsgTypeMax = 4, 6233 len: usize,
6234 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6235 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6236 let before = decoder.bytes_read();
6237 while decoder.bytes_read() - before < len {
6238 let tag = decoder.decode_tag()?;
6239 match tag.field_num() {
6240 0 => return Err(::micropb::DecodeError::ZeroField),
6241 _ => {
6242 decoder.skip_wire_value(tag.wire_type())?;
6243 }
6244 }
6245 }
6246 Ok(())
6247 }
587} 6248}
588 6249impl ::micropb::MessageEncode for CtrlMsg_Req_GetFwVersion {
589#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 6250 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
590#[repr(u32)] 6251 let mut max_size = 0;
591#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6252 ::core::option::Option::Some(max_size)
592pub(crate) enum CtrlMsgId { 6253 };
593 #[default] 6254 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
594 MsgIdInvalid = 0, 6255 &self,
595 /// * Request Msgs * 6256 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
596 ReqBase = 100, 6257 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
597 ReqGetMacAddress = 101, 6258 use ::micropb::{FieldEncode, PbMap};
598 ReqSetMacAddress = 102, 6259 Ok(())
599 ReqGetWifiMode = 103, 6260 }
600 ReqSetWifiMode = 104, 6261 fn compute_size(&self) -> usize {
601 ReqGetApScanList = 105, 6262 use ::micropb::{FieldEncode, PbMap};
602 ReqGetApConfig = 106, 6263 let mut size = 0;
603 ReqConnectAp = 107, 6264 size
604 ReqDisconnectAp = 108, 6265 }
605 ReqGetSoftApConfig = 109, 6266}
606 ReqSetSoftApVendorSpecificIe = 110, 6267#[derive(Debug, Default, PartialEq, Clone)]
607 ReqStartSoftAp = 111, 6268#[cfg_attr(feature = "defmt", derive(defmt::Format))]
608 ReqGetSoftApConnectedStaList = 112, 6269pub struct CtrlMsg_Resp_GetFwVersion {
609 ReqStopSoftAp = 113, 6270 pub r#resp: i32,
610 ReqSetPowerSaveMode = 114, 6271 pub r#name: ::micropb::heapless::String<32>,
611 ReqGetPowerSaveMode = 115, 6272 pub r#major1: u32,
612 ReqOtaBegin = 116, 6273 pub r#major2: u32,
613 ReqOtaWrite = 117, 6274 pub r#minor: u32,
614 ReqOtaEnd = 118, 6275 pub r#rev_patch1: u32,
615 ReqSetWifiMaxTxPower = 119, 6276 pub r#rev_patch2: u32,
616 ReqGetWifiCurrTxPower = 120, 6277}
617 ReqConfigHeartbeat = 121, 6278impl CtrlMsg_Resp_GetFwVersion {
618 /// Add new control path command response before Req_Max 6279 ///Return a reference to `resp`
619 /// and update Req_Max 6280 #[inline]
620 ReqMax = 122, 6281 pub fn r#resp(&self) -> &i32 {
621 /// * Response Msgs * 6282 &self.r#resp
622 RespBase = 200, 6283 }
623 RespGetMacAddress = 201, 6284 ///Return a mutable reference to `resp`
624 RespSetMacAddress = 202, 6285 #[inline]
625 RespGetWifiMode = 203, 6286 pub fn mut_resp(&mut self) -> &mut i32 {
626 RespSetWifiMode = 204, 6287 &mut self.r#resp
627 RespGetApScanList = 205, 6288 }
628 RespGetApConfig = 206, 6289 ///Set the value of `resp`
629 RespConnectAp = 207, 6290 #[inline]
630 RespDisconnectAp = 208, 6291 pub fn set_resp(&mut self, value: i32) -> &mut Self {
631 RespGetSoftApConfig = 209, 6292 self.r#resp = value.into();
632 RespSetSoftApVendorSpecificIe = 210, 6293 self
633 RespStartSoftAp = 211, 6294 }
634 RespGetSoftApConnectedStaList = 212, 6295 ///Builder method that sets the value of `resp`. Useful for initializing the message.
635 RespStopSoftAp = 213, 6296 #[inline]
636 RespSetPowerSaveMode = 214, 6297 pub fn init_resp(mut self, value: i32) -> Self {
637 RespGetPowerSaveMode = 215, 6298 self.r#resp = value.into();
638 RespOtaBegin = 216, 6299 self
639 RespOtaWrite = 217, 6300 }
640 RespOtaEnd = 218, 6301 ///Return a reference to `name`
641 RespSetWifiMaxTxPower = 219, 6302 #[inline]
642 RespGetWifiCurrTxPower = 220, 6303 pub fn r#name(&self) -> &::micropb::heapless::String<32> {
643 RespConfigHeartbeat = 221, 6304 &self.r#name
644 /// Add new control path command response before Resp_Max 6305 }
645 /// and update Resp_Max 6306 ///Return a mutable reference to `name`
646 RespMax = 222, 6307 #[inline]
647 /// * Event Msgs * 6308 pub fn mut_name(&mut self) -> &mut ::micropb::heapless::String<32> {
648 EventBase = 300, 6309 &mut self.r#name
649 EventEspInit = 301, 6310 }
650 EventHeartbeat = 302, 6311 ///Set the value of `name`
651 EventStationDisconnectFromAp = 303, 6312 #[inline]
652 EventStationDisconnectFromEspSoftAp = 304, 6313 pub fn set_name(&mut self, value: ::micropb::heapless::String<32>) -> &mut Self {
653 /// Add new control path command notification before Event_Max 6314 self.r#name = value.into();
654 /// and update Event_Max 6315 self
655 EventMax = 305, 6316 }
6317 ///Builder method that sets the value of `name`. Useful for initializing the message.
6318 #[inline]
6319 pub fn init_name(mut self, value: ::micropb::heapless::String<32>) -> Self {
6320 self.r#name = value.into();
6321 self
6322 }
6323 ///Return a reference to `major1`
6324 #[inline]
6325 pub fn r#major1(&self) -> &u32 {
6326 &self.r#major1
6327 }
6328 ///Return a mutable reference to `major1`
6329 #[inline]
6330 pub fn mut_major1(&mut self) -> &mut u32 {
6331 &mut self.r#major1
6332 }
6333 ///Set the value of `major1`
6334 #[inline]
6335 pub fn set_major1(&mut self, value: u32) -> &mut Self {
6336 self.r#major1 = value.into();
6337 self
6338 }
6339 ///Builder method that sets the value of `major1`. Useful for initializing the message.
6340 #[inline]
6341 pub fn init_major1(mut self, value: u32) -> Self {
6342 self.r#major1 = value.into();
6343 self
6344 }
6345 ///Return a reference to `major2`
6346 #[inline]
6347 pub fn r#major2(&self) -> &u32 {
6348 &self.r#major2
6349 }
6350 ///Return a mutable reference to `major2`
6351 #[inline]
6352 pub fn mut_major2(&mut self) -> &mut u32 {
6353 &mut self.r#major2
6354 }
6355 ///Set the value of `major2`
6356 #[inline]
6357 pub fn set_major2(&mut self, value: u32) -> &mut Self {
6358 self.r#major2 = value.into();
6359 self
6360 }
6361 ///Builder method that sets the value of `major2`. Useful for initializing the message.
6362 #[inline]
6363 pub fn init_major2(mut self, value: u32) -> Self {
6364 self.r#major2 = value.into();
6365 self
6366 }
6367 ///Return a reference to `minor`
6368 #[inline]
6369 pub fn r#minor(&self) -> &u32 {
6370 &self.r#minor
6371 }
6372 ///Return a mutable reference to `minor`
6373 #[inline]
6374 pub fn mut_minor(&mut self) -> &mut u32 {
6375 &mut self.r#minor
6376 }
6377 ///Set the value of `minor`
6378 #[inline]
6379 pub fn set_minor(&mut self, value: u32) -> &mut Self {
6380 self.r#minor = value.into();
6381 self
6382 }
6383 ///Builder method that sets the value of `minor`. Useful for initializing the message.
6384 #[inline]
6385 pub fn init_minor(mut self, value: u32) -> Self {
6386 self.r#minor = value.into();
6387 self
6388 }
6389 ///Return a reference to `rev_patch1`
6390 #[inline]
6391 pub fn r#rev_patch1(&self) -> &u32 {
6392 &self.r#rev_patch1
6393 }
6394 ///Return a mutable reference to `rev_patch1`
6395 #[inline]
6396 pub fn mut_rev_patch1(&mut self) -> &mut u32 {
6397 &mut self.r#rev_patch1
6398 }
6399 ///Set the value of `rev_patch1`
6400 #[inline]
6401 pub fn set_rev_patch1(&mut self, value: u32) -> &mut Self {
6402 self.r#rev_patch1 = value.into();
6403 self
6404 }
6405 ///Builder method that sets the value of `rev_patch1`. Useful for initializing the message.
6406 #[inline]
6407 pub fn init_rev_patch1(mut self, value: u32) -> Self {
6408 self.r#rev_patch1 = value.into();
6409 self
6410 }
6411 ///Return a reference to `rev_patch2`
6412 #[inline]
6413 pub fn r#rev_patch2(&self) -> &u32 {
6414 &self.r#rev_patch2
6415 }
6416 ///Return a mutable reference to `rev_patch2`
6417 #[inline]
6418 pub fn mut_rev_patch2(&mut self) -> &mut u32 {
6419 &mut self.r#rev_patch2
6420 }
6421 ///Set the value of `rev_patch2`
6422 #[inline]
6423 pub fn set_rev_patch2(&mut self, value: u32) -> &mut Self {
6424 self.r#rev_patch2 = value.into();
6425 self
6426 }
6427 ///Builder method that sets the value of `rev_patch2`. Useful for initializing the message.
6428 #[inline]
6429 pub fn init_rev_patch2(mut self, value: u32) -> Self {
6430 self.r#rev_patch2 = value.into();
6431 self
6432 }
6433}
6434impl ::micropb::MessageDecode for CtrlMsg_Resp_GetFwVersion {
6435 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
6436 &mut self,
6437 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
6438 len: usize,
6439 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6440 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6441 let before = decoder.bytes_read();
6442 while decoder.bytes_read() - before < len {
6443 let tag = decoder.decode_tag()?;
6444 match tag.field_num() {
6445 0 => return Err(::micropb::DecodeError::ZeroField),
6446 1u32 => {
6447 let mut_ref = &mut self.r#resp;
6448 {
6449 let val = decoder.decode_int32()?;
6450 let val_ref = &val;
6451 if *val_ref != 0 {
6452 *mut_ref = val as _;
6453 }
6454 };
6455 }
6456 2u32 => {
6457 let mut_ref = &mut self.r#name;
6458 {
6459 decoder.decode_string(mut_ref, ::micropb::Presence::Implicit)?;
6460 };
6461 }
6462 3u32 => {
6463 let mut_ref = &mut self.r#major1;
6464 {
6465 let val = decoder.decode_varint32()?;
6466 let val_ref = &val;
6467 if *val_ref != 0 {
6468 *mut_ref = val as _;
6469 }
6470 };
6471 }
6472 4u32 => {
6473 let mut_ref = &mut self.r#major2;
6474 {
6475 let val = decoder.decode_varint32()?;
6476 let val_ref = &val;
6477 if *val_ref != 0 {
6478 *mut_ref = val as _;
6479 }
6480 };
6481 }
6482 5u32 => {
6483 let mut_ref = &mut self.r#minor;
6484 {
6485 let val = decoder.decode_varint32()?;
6486 let val_ref = &val;
6487 if *val_ref != 0 {
6488 *mut_ref = val as _;
6489 }
6490 };
6491 }
6492 6u32 => {
6493 let mut_ref = &mut self.r#rev_patch1;
6494 {
6495 let val = decoder.decode_varint32()?;
6496 let val_ref = &val;
6497 if *val_ref != 0 {
6498 *mut_ref = val as _;
6499 }
6500 };
6501 }
6502 7u32 => {
6503 let mut_ref = &mut self.r#rev_patch2;
6504 {
6505 let val = decoder.decode_varint32()?;
6506 let val_ref = &val;
6507 if *val_ref != 0 {
6508 *mut_ref = val as _;
6509 }
6510 };
6511 }
6512 _ => {
6513 decoder.skip_wire_value(tag.wire_type())?;
6514 }
6515 }
6516 }
6517 Ok(())
6518 }
6519}
6520impl ::micropb::MessageEncode for CtrlMsg_Resp_GetFwVersion {
6521 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
6522 let mut max_size = 0;
6523 if let ::core::option::Option::Some(size) =
6524 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
6525 {
6526 max_size += size;
6527 } else {
6528 break 'msg (::core::option::Option::<usize>::None);
6529 };
6530 if let ::core::option::Option::Some(size) =
6531 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
6532 {
6533 max_size += size;
6534 } else {
6535 break 'msg (::core::option::Option::<usize>::None);
6536 };
6537 if let ::core::option::Option::Some(size) =
6538 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6539 {
6540 max_size += size;
6541 } else {
6542 break 'msg (::core::option::Option::<usize>::None);
6543 };
6544 if let ::core::option::Option::Some(size) =
6545 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6546 {
6547 max_size += size;
6548 } else {
6549 break 'msg (::core::option::Option::<usize>::None);
6550 };
6551 if let ::core::option::Option::Some(size) =
6552 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6553 {
6554 max_size += size;
6555 } else {
6556 break 'msg (::core::option::Option::<usize>::None);
6557 };
6558 if let ::core::option::Option::Some(size) =
6559 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6560 {
6561 max_size += size;
6562 } else {
6563 break 'msg (::core::option::Option::<usize>::None);
6564 };
6565 if let ::core::option::Option::Some(size) =
6566 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
6567 {
6568 max_size += size;
6569 } else {
6570 break 'msg (::core::option::Option::<usize>::None);
6571 };
6572 ::core::option::Option::Some(max_size)
6573 };
6574 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6575 &self,
6576 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6577 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6578 use ::micropb::{FieldEncode, PbMap};
6579 {
6580 let val_ref = &self.r#resp;
6581 if *val_ref != 0 {
6582 encoder.encode_varint32(8u32)?;
6583 encoder.encode_int32(*val_ref as _)?;
6584 }
6585 }
6586 {
6587 let val_ref = &self.r#name;
6588 if !val_ref.is_empty() {
6589 encoder.encode_varint32(18u32)?;
6590 encoder.encode_string(val_ref)?;
6591 }
6592 }
6593 {
6594 let val_ref = &self.r#major1;
6595 if *val_ref != 0 {
6596 encoder.encode_varint32(24u32)?;
6597 encoder.encode_varint32(*val_ref as _)?;
6598 }
6599 }
6600 {
6601 let val_ref = &self.r#major2;
6602 if *val_ref != 0 {
6603 encoder.encode_varint32(32u32)?;
6604 encoder.encode_varint32(*val_ref as _)?;
6605 }
6606 }
6607 {
6608 let val_ref = &self.r#minor;
6609 if *val_ref != 0 {
6610 encoder.encode_varint32(40u32)?;
6611 encoder.encode_varint32(*val_ref as _)?;
6612 }
6613 }
6614 {
6615 let val_ref = &self.r#rev_patch1;
6616 if *val_ref != 0 {
6617 encoder.encode_varint32(48u32)?;
6618 encoder.encode_varint32(*val_ref as _)?;
6619 }
6620 }
6621 {
6622 let val_ref = &self.r#rev_patch2;
6623 if *val_ref != 0 {
6624 encoder.encode_varint32(56u32)?;
6625 encoder.encode_varint32(*val_ref as _)?;
6626 }
6627 }
6628 Ok(())
6629 }
6630 fn compute_size(&self) -> usize {
6631 use ::micropb::{FieldEncode, PbMap};
6632 let mut size = 0;
6633 {
6634 let val_ref = &self.r#resp;
6635 if *val_ref != 0 {
6636 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
6637 }
6638 }
6639 {
6640 let val_ref = &self.r#name;
6641 if !val_ref.is_empty() {
6642 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
6643 }
6644 }
6645 {
6646 let val_ref = &self.r#major1;
6647 if *val_ref != 0 {
6648 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6649 }
6650 }
6651 {
6652 let val_ref = &self.r#major2;
6653 if *val_ref != 0 {
6654 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6655 }
6656 }
6657 {
6658 let val_ref = &self.r#minor;
6659 if *val_ref != 0 {
6660 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6661 }
6662 }
6663 {
6664 let val_ref = &self.r#rev_patch1;
6665 if *val_ref != 0 {
6666 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6667 }
6668 }
6669 {
6670 let val_ref = &self.r#rev_patch2;
6671 if *val_ref != 0 {
6672 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
6673 }
6674 }
6675 size
6676 }
6677}
6678#[derive(Debug, Default, PartialEq, Clone)]
6679#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6680pub struct CtrlMsg_Req_SetCountryCode {
6681 pub r#country: ::micropb::heapless::Vec<u8, 32>,
6682 pub r#ieee80211d_enabled: bool,
6683}
6684impl CtrlMsg_Req_SetCountryCode {
6685 ///Return a reference to `country`
6686 #[inline]
6687 pub fn r#country(&self) -> &::micropb::heapless::Vec<u8, 32> {
6688 &self.r#country
6689 }
6690 ///Return a mutable reference to `country`
6691 #[inline]
6692 pub fn mut_country(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
6693 &mut self.r#country
6694 }
6695 ///Set the value of `country`
6696 #[inline]
6697 pub fn set_country(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
6698 self.r#country = value.into();
6699 self
6700 }
6701 ///Builder method that sets the value of `country`. Useful for initializing the message.
6702 #[inline]
6703 pub fn init_country(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
6704 self.r#country = value.into();
6705 self
6706 }
6707 ///Return a reference to `ieee80211d_enabled`
6708 #[inline]
6709 pub fn r#ieee80211d_enabled(&self) -> &bool {
6710 &self.r#ieee80211d_enabled
6711 }
6712 ///Return a mutable reference to `ieee80211d_enabled`
6713 #[inline]
6714 pub fn mut_ieee80211d_enabled(&mut self) -> &mut bool {
6715 &mut self.r#ieee80211d_enabled
6716 }
6717 ///Set the value of `ieee80211d_enabled`
6718 #[inline]
6719 pub fn set_ieee80211d_enabled(&mut self, value: bool) -> &mut Self {
6720 self.r#ieee80211d_enabled = value.into();
6721 self
6722 }
6723 ///Builder method that sets the value of `ieee80211d_enabled`. Useful for initializing the message.
6724 #[inline]
6725 pub fn init_ieee80211d_enabled(mut self, value: bool) -> Self {
6726 self.r#ieee80211d_enabled = value.into();
6727 self
6728 }
6729}
6730impl ::micropb::MessageDecode for CtrlMsg_Req_SetCountryCode {
6731 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
6732 &mut self,
6733 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
6734 len: usize,
6735 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6736 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6737 let before = decoder.bytes_read();
6738 while decoder.bytes_read() - before < len {
6739 let tag = decoder.decode_tag()?;
6740 match tag.field_num() {
6741 0 => return Err(::micropb::DecodeError::ZeroField),
6742 1u32 => {
6743 let mut_ref = &mut self.r#country;
6744 {
6745 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
6746 };
6747 }
6748 2u32 => {
6749 let mut_ref = &mut self.r#ieee80211d_enabled;
6750 {
6751 let val = decoder.decode_bool()?;
6752 let val_ref = &val;
6753 if *val_ref {
6754 *mut_ref = val as _;
6755 }
6756 };
6757 }
6758 _ => {
6759 decoder.skip_wire_value(tag.wire_type())?;
6760 }
6761 }
6762 }
6763 Ok(())
6764 }
6765}
6766impl ::micropb::MessageEncode for CtrlMsg_Req_SetCountryCode {
6767 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
6768 let mut max_size = 0;
6769 if let ::core::option::Option::Some(size) =
6770 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
6771 {
6772 max_size += size;
6773 } else {
6774 break 'msg (::core::option::Option::<usize>::None);
6775 };
6776 if let ::core::option::Option::Some(size) =
6777 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
6778 {
6779 max_size += size;
6780 } else {
6781 break 'msg (::core::option::Option::<usize>::None);
6782 };
6783 ::core::option::Option::Some(max_size)
6784 };
6785 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6786 &self,
6787 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6788 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6789 use ::micropb::{FieldEncode, PbMap};
6790 {
6791 let val_ref = &self.r#country;
6792 if !val_ref.is_empty() {
6793 encoder.encode_varint32(10u32)?;
6794 encoder.encode_bytes(val_ref)?;
6795 }
6796 }
6797 {
6798 let val_ref = &self.r#ieee80211d_enabled;
6799 if *val_ref {
6800 encoder.encode_varint32(16u32)?;
6801 encoder.encode_bool(*val_ref)?;
6802 }
6803 }
6804 Ok(())
6805 }
6806 fn compute_size(&self) -> usize {
6807 use ::micropb::{FieldEncode, PbMap};
6808 let mut size = 0;
6809 {
6810 let val_ref = &self.r#country;
6811 if !val_ref.is_empty() {
6812 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
6813 }
6814 }
6815 {
6816 let val_ref = &self.r#ieee80211d_enabled;
6817 if *val_ref {
6818 size += 1usize + 1;
6819 }
6820 }
6821 size
6822 }
6823}
6824#[derive(Debug, Default, PartialEq, Clone)]
6825#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6826pub struct CtrlMsg_Resp_SetCountryCode {
6827 pub r#resp: i32,
6828}
6829impl CtrlMsg_Resp_SetCountryCode {
6830 ///Return a reference to `resp`
6831 #[inline]
6832 pub fn r#resp(&self) -> &i32 {
6833 &self.r#resp
6834 }
6835 ///Return a mutable reference to `resp`
6836 #[inline]
6837 pub fn mut_resp(&mut self) -> &mut i32 {
6838 &mut self.r#resp
6839 }
6840 ///Set the value of `resp`
6841 #[inline]
6842 pub fn set_resp(&mut self, value: i32) -> &mut Self {
6843 self.r#resp = value.into();
6844 self
6845 }
6846 ///Builder method that sets the value of `resp`. Useful for initializing the message.
6847 #[inline]
6848 pub fn init_resp(mut self, value: i32) -> Self {
6849 self.r#resp = value.into();
6850 self
6851 }
6852}
6853impl ::micropb::MessageDecode for CtrlMsg_Resp_SetCountryCode {
6854 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
6855 &mut self,
6856 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
6857 len: usize,
6858 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6859 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6860 let before = decoder.bytes_read();
6861 while decoder.bytes_read() - before < len {
6862 let tag = decoder.decode_tag()?;
6863 match tag.field_num() {
6864 0 => return Err(::micropb::DecodeError::ZeroField),
6865 1u32 => {
6866 let mut_ref = &mut self.r#resp;
6867 {
6868 let val = decoder.decode_int32()?;
6869 let val_ref = &val;
6870 if *val_ref != 0 {
6871 *mut_ref = val as _;
6872 }
6873 };
6874 }
6875 _ => {
6876 decoder.skip_wire_value(tag.wire_type())?;
6877 }
6878 }
6879 }
6880 Ok(())
6881 }
6882}
6883impl ::micropb::MessageEncode for CtrlMsg_Resp_SetCountryCode {
6884 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
6885 let mut max_size = 0;
6886 if let ::core::option::Option::Some(size) =
6887 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
6888 {
6889 max_size += size;
6890 } else {
6891 break 'msg (::core::option::Option::<usize>::None);
6892 };
6893 ::core::option::Option::Some(max_size)
6894 };
6895 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6896 &self,
6897 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6898 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6899 use ::micropb::{FieldEncode, PbMap};
6900 {
6901 let val_ref = &self.r#resp;
6902 if *val_ref != 0 {
6903 encoder.encode_varint32(8u32)?;
6904 encoder.encode_int32(*val_ref as _)?;
6905 }
6906 }
6907 Ok(())
6908 }
6909 fn compute_size(&self) -> usize {
6910 use ::micropb::{FieldEncode, PbMap};
6911 let mut size = 0;
6912 {
6913 let val_ref = &self.r#resp;
6914 if *val_ref != 0 {
6915 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
6916 }
6917 }
6918 size
6919 }
6920}
6921#[derive(Debug, Default, PartialEq, Clone)]
6922#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6923pub struct CtrlMsg_Req_GetCountryCode {}
6924impl CtrlMsg_Req_GetCountryCode {}
6925impl ::micropb::MessageDecode for CtrlMsg_Req_GetCountryCode {
6926 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
6927 &mut self,
6928 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
6929 len: usize,
6930 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
6931 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
6932 let before = decoder.bytes_read();
6933 while decoder.bytes_read() - before < len {
6934 let tag = decoder.decode_tag()?;
6935 match tag.field_num() {
6936 0 => return Err(::micropb::DecodeError::ZeroField),
6937 _ => {
6938 decoder.skip_wire_value(tag.wire_type())?;
6939 }
6940 }
6941 }
6942 Ok(())
6943 }
6944}
6945impl ::micropb::MessageEncode for CtrlMsg_Req_GetCountryCode {
6946 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
6947 let mut max_size = 0;
6948 ::core::option::Option::Some(max_size)
6949 };
6950 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
6951 &self,
6952 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
6953 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
6954 use ::micropb::{FieldEncode, PbMap};
6955 Ok(())
6956 }
6957 fn compute_size(&self) -> usize {
6958 use ::micropb::{FieldEncode, PbMap};
6959 let mut size = 0;
6960 size
6961 }
6962}
6963#[derive(Debug, Default, PartialEq, Clone)]
6964#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6965pub struct CtrlMsg_Resp_GetCountryCode {
6966 pub r#resp: i32,
6967 pub r#country: ::micropb::heapless::Vec<u8, 32>,
6968}
6969impl CtrlMsg_Resp_GetCountryCode {
6970 ///Return a reference to `resp`
6971 #[inline]
6972 pub fn r#resp(&self) -> &i32 {
6973 &self.r#resp
6974 }
6975 ///Return a mutable reference to `resp`
6976 #[inline]
6977 pub fn mut_resp(&mut self) -> &mut i32 {
6978 &mut self.r#resp
6979 }
6980 ///Set the value of `resp`
6981 #[inline]
6982 pub fn set_resp(&mut self, value: i32) -> &mut Self {
6983 self.r#resp = value.into();
6984 self
6985 }
6986 ///Builder method that sets the value of `resp`. Useful for initializing the message.
6987 #[inline]
6988 pub fn init_resp(mut self, value: i32) -> Self {
6989 self.r#resp = value.into();
6990 self
6991 }
6992 ///Return a reference to `country`
6993 #[inline]
6994 pub fn r#country(&self) -> &::micropb::heapless::Vec<u8, 32> {
6995 &self.r#country
6996 }
6997 ///Return a mutable reference to `country`
6998 #[inline]
6999 pub fn mut_country(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7000 &mut self.r#country
7001 }
7002 ///Set the value of `country`
7003 #[inline]
7004 pub fn set_country(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7005 self.r#country = value.into();
7006 self
7007 }
7008 ///Builder method that sets the value of `country`. Useful for initializing the message.
7009 #[inline]
7010 pub fn init_country(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7011 self.r#country = value.into();
7012 self
7013 }
7014}
7015impl ::micropb::MessageDecode for CtrlMsg_Resp_GetCountryCode {
7016 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
7017 &mut self,
7018 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
7019 len: usize,
7020 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
7021 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
7022 let before = decoder.bytes_read();
7023 while decoder.bytes_read() - before < len {
7024 let tag = decoder.decode_tag()?;
7025 match tag.field_num() {
7026 0 => return Err(::micropb::DecodeError::ZeroField),
7027 1u32 => {
7028 let mut_ref = &mut self.r#resp;
7029 {
7030 let val = decoder.decode_int32()?;
7031 let val_ref = &val;
7032 if *val_ref != 0 {
7033 *mut_ref = val as _;
7034 }
7035 };
7036 }
7037 2u32 => {
7038 let mut_ref = &mut self.r#country;
7039 {
7040 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
7041 };
7042 }
7043 _ => {
7044 decoder.skip_wire_value(tag.wire_type())?;
7045 }
7046 }
7047 }
7048 Ok(())
7049 }
7050}
7051impl ::micropb::MessageEncode for CtrlMsg_Resp_GetCountryCode {
7052 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
7053 let mut max_size = 0;
7054 if let ::core::option::Option::Some(size) =
7055 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7056 {
7057 max_size += size;
7058 } else {
7059 break 'msg (::core::option::Option::<usize>::None);
7060 };
7061 if let ::core::option::Option::Some(size) =
7062 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
7063 {
7064 max_size += size;
7065 } else {
7066 break 'msg (::core::option::Option::<usize>::None);
7067 };
7068 ::core::option::Option::Some(max_size)
7069 };
7070 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
7071 &self,
7072 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
7073 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
7074 use ::micropb::{FieldEncode, PbMap};
7075 {
7076 let val_ref = &self.r#resp;
7077 if *val_ref != 0 {
7078 encoder.encode_varint32(8u32)?;
7079 encoder.encode_int32(*val_ref as _)?;
7080 }
7081 }
7082 {
7083 let val_ref = &self.r#country;
7084 if !val_ref.is_empty() {
7085 encoder.encode_varint32(18u32)?;
7086 encoder.encode_bytes(val_ref)?;
7087 }
7088 }
7089 Ok(())
7090 }
7091 fn compute_size(&self) -> usize {
7092 use ::micropb::{FieldEncode, PbMap};
7093 let mut size = 0;
7094 {
7095 let val_ref = &self.r#resp;
7096 if *val_ref != 0 {
7097 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7098 }
7099 }
7100 {
7101 let val_ref = &self.r#country;
7102 if !val_ref.is_empty() {
7103 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
7104 }
7105 }
7106 size
7107 }
7108}
7109#[derive(Debug, Default, PartialEq, Clone)]
7110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7111pub struct CtrlMsg_Req_SetDhcpDnsStatus {
7112 pub r#iface: i32,
7113 pub r#net_link_up: i32,
7114 pub r#dhcp_up: i32,
7115 pub r#dhcp_ip: ::micropb::heapless::Vec<u8, 32>,
7116 pub r#dhcp_nm: ::micropb::heapless::Vec<u8, 32>,
7117 pub r#dhcp_gw: ::micropb::heapless::Vec<u8, 32>,
7118 pub r#dns_up: i32,
7119 pub r#dns_ip: ::micropb::heapless::Vec<u8, 32>,
7120 pub r#dns_type: i32,
7121}
7122impl CtrlMsg_Req_SetDhcpDnsStatus {
7123 ///Return a reference to `iface`
7124 #[inline]
7125 pub fn r#iface(&self) -> &i32 {
7126 &self.r#iface
7127 }
7128 ///Return a mutable reference to `iface`
7129 #[inline]
7130 pub fn mut_iface(&mut self) -> &mut i32 {
7131 &mut self.r#iface
7132 }
7133 ///Set the value of `iface`
7134 #[inline]
7135 pub fn set_iface(&mut self, value: i32) -> &mut Self {
7136 self.r#iface = value.into();
7137 self
7138 }
7139 ///Builder method that sets the value of `iface`. Useful for initializing the message.
7140 #[inline]
7141 pub fn init_iface(mut self, value: i32) -> Self {
7142 self.r#iface = value.into();
7143 self
7144 }
7145 ///Return a reference to `net_link_up`
7146 #[inline]
7147 pub fn r#net_link_up(&self) -> &i32 {
7148 &self.r#net_link_up
7149 }
7150 ///Return a mutable reference to `net_link_up`
7151 #[inline]
7152 pub fn mut_net_link_up(&mut self) -> &mut i32 {
7153 &mut self.r#net_link_up
7154 }
7155 ///Set the value of `net_link_up`
7156 #[inline]
7157 pub fn set_net_link_up(&mut self, value: i32) -> &mut Self {
7158 self.r#net_link_up = value.into();
7159 self
7160 }
7161 ///Builder method that sets the value of `net_link_up`. Useful for initializing the message.
7162 #[inline]
7163 pub fn init_net_link_up(mut self, value: i32) -> Self {
7164 self.r#net_link_up = value.into();
7165 self
7166 }
7167 ///Return a reference to `dhcp_up`
7168 #[inline]
7169 pub fn r#dhcp_up(&self) -> &i32 {
7170 &self.r#dhcp_up
7171 }
7172 ///Return a mutable reference to `dhcp_up`
7173 #[inline]
7174 pub fn mut_dhcp_up(&mut self) -> &mut i32 {
7175 &mut self.r#dhcp_up
7176 }
7177 ///Set the value of `dhcp_up`
7178 #[inline]
7179 pub fn set_dhcp_up(&mut self, value: i32) -> &mut Self {
7180 self.r#dhcp_up = value.into();
7181 self
7182 }
7183 ///Builder method that sets the value of `dhcp_up`. Useful for initializing the message.
7184 #[inline]
7185 pub fn init_dhcp_up(mut self, value: i32) -> Self {
7186 self.r#dhcp_up = value.into();
7187 self
7188 }
7189 ///Return a reference to `dhcp_ip`
7190 #[inline]
7191 pub fn r#dhcp_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
7192 &self.r#dhcp_ip
7193 }
7194 ///Return a mutable reference to `dhcp_ip`
7195 #[inline]
7196 pub fn mut_dhcp_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7197 &mut self.r#dhcp_ip
7198 }
7199 ///Set the value of `dhcp_ip`
7200 #[inline]
7201 pub fn set_dhcp_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7202 self.r#dhcp_ip = value.into();
7203 self
7204 }
7205 ///Builder method that sets the value of `dhcp_ip`. Useful for initializing the message.
7206 #[inline]
7207 pub fn init_dhcp_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7208 self.r#dhcp_ip = value.into();
7209 self
7210 }
7211 ///Return a reference to `dhcp_nm`
7212 #[inline]
7213 pub fn r#dhcp_nm(&self) -> &::micropb::heapless::Vec<u8, 32> {
7214 &self.r#dhcp_nm
7215 }
7216 ///Return a mutable reference to `dhcp_nm`
7217 #[inline]
7218 pub fn mut_dhcp_nm(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7219 &mut self.r#dhcp_nm
7220 }
7221 ///Set the value of `dhcp_nm`
7222 #[inline]
7223 pub fn set_dhcp_nm(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7224 self.r#dhcp_nm = value.into();
7225 self
7226 }
7227 ///Builder method that sets the value of `dhcp_nm`. Useful for initializing the message.
7228 #[inline]
7229 pub fn init_dhcp_nm(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7230 self.r#dhcp_nm = value.into();
7231 self
7232 }
7233 ///Return a reference to `dhcp_gw`
7234 #[inline]
7235 pub fn r#dhcp_gw(&self) -> &::micropb::heapless::Vec<u8, 32> {
7236 &self.r#dhcp_gw
7237 }
7238 ///Return a mutable reference to `dhcp_gw`
7239 #[inline]
7240 pub fn mut_dhcp_gw(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7241 &mut self.r#dhcp_gw
7242 }
7243 ///Set the value of `dhcp_gw`
7244 #[inline]
7245 pub fn set_dhcp_gw(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7246 self.r#dhcp_gw = value.into();
7247 self
7248 }
7249 ///Builder method that sets the value of `dhcp_gw`. Useful for initializing the message.
7250 #[inline]
7251 pub fn init_dhcp_gw(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7252 self.r#dhcp_gw = value.into();
7253 self
7254 }
7255 ///Return a reference to `dns_up`
7256 #[inline]
7257 pub fn r#dns_up(&self) -> &i32 {
7258 &self.r#dns_up
7259 }
7260 ///Return a mutable reference to `dns_up`
7261 #[inline]
7262 pub fn mut_dns_up(&mut self) -> &mut i32 {
7263 &mut self.r#dns_up
7264 }
7265 ///Set the value of `dns_up`
7266 #[inline]
7267 pub fn set_dns_up(&mut self, value: i32) -> &mut Self {
7268 self.r#dns_up = value.into();
7269 self
7270 }
7271 ///Builder method that sets the value of `dns_up`. Useful for initializing the message.
7272 #[inline]
7273 pub fn init_dns_up(mut self, value: i32) -> Self {
7274 self.r#dns_up = value.into();
7275 self
7276 }
7277 ///Return a reference to `dns_ip`
7278 #[inline]
7279 pub fn r#dns_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
7280 &self.r#dns_ip
7281 }
7282 ///Return a mutable reference to `dns_ip`
7283 #[inline]
7284 pub fn mut_dns_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7285 &mut self.r#dns_ip
7286 }
7287 ///Set the value of `dns_ip`
7288 #[inline]
7289 pub fn set_dns_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7290 self.r#dns_ip = value.into();
7291 self
7292 }
7293 ///Builder method that sets the value of `dns_ip`. Useful for initializing the message.
7294 #[inline]
7295 pub fn init_dns_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7296 self.r#dns_ip = value.into();
7297 self
7298 }
7299 ///Return a reference to `dns_type`
7300 #[inline]
7301 pub fn r#dns_type(&self) -> &i32 {
7302 &self.r#dns_type
7303 }
7304 ///Return a mutable reference to `dns_type`
7305 #[inline]
7306 pub fn mut_dns_type(&mut self) -> &mut i32 {
7307 &mut self.r#dns_type
7308 }
7309 ///Set the value of `dns_type`
7310 #[inline]
7311 pub fn set_dns_type(&mut self, value: i32) -> &mut Self {
7312 self.r#dns_type = value.into();
7313 self
7314 }
7315 ///Builder method that sets the value of `dns_type`. Useful for initializing the message.
7316 #[inline]
7317 pub fn init_dns_type(mut self, value: i32) -> Self {
7318 self.r#dns_type = value.into();
7319 self
7320 }
7321}
7322impl ::micropb::MessageDecode for CtrlMsg_Req_SetDhcpDnsStatus {
7323 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
7324 &mut self,
7325 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
7326 len: usize,
7327 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
7328 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
7329 let before = decoder.bytes_read();
7330 while decoder.bytes_read() - before < len {
7331 let tag = decoder.decode_tag()?;
7332 match tag.field_num() {
7333 0 => return Err(::micropb::DecodeError::ZeroField),
7334 1u32 => {
7335 let mut_ref = &mut self.r#iface;
7336 {
7337 let val = decoder.decode_int32()?;
7338 let val_ref = &val;
7339 if *val_ref != 0 {
7340 *mut_ref = val as _;
7341 }
7342 };
7343 }
7344 2u32 => {
7345 let mut_ref = &mut self.r#net_link_up;
7346 {
7347 let val = decoder.decode_int32()?;
7348 let val_ref = &val;
7349 if *val_ref != 0 {
7350 *mut_ref = val as _;
7351 }
7352 };
7353 }
7354 3u32 => {
7355 let mut_ref = &mut self.r#dhcp_up;
7356 {
7357 let val = decoder.decode_int32()?;
7358 let val_ref = &val;
7359 if *val_ref != 0 {
7360 *mut_ref = val as _;
7361 }
7362 };
7363 }
7364 4u32 => {
7365 let mut_ref = &mut self.r#dhcp_ip;
7366 {
7367 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
7368 };
7369 }
7370 5u32 => {
7371 let mut_ref = &mut self.r#dhcp_nm;
7372 {
7373 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
7374 };
7375 }
7376 6u32 => {
7377 let mut_ref = &mut self.r#dhcp_gw;
7378 {
7379 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
7380 };
7381 }
7382 7u32 => {
7383 let mut_ref = &mut self.r#dns_up;
7384 {
7385 let val = decoder.decode_int32()?;
7386 let val_ref = &val;
7387 if *val_ref != 0 {
7388 *mut_ref = val as _;
7389 }
7390 };
7391 }
7392 8u32 => {
7393 let mut_ref = &mut self.r#dns_ip;
7394 {
7395 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
7396 };
7397 }
7398 9u32 => {
7399 let mut_ref = &mut self.r#dns_type;
7400 {
7401 let val = decoder.decode_int32()?;
7402 let val_ref = &val;
7403 if *val_ref != 0 {
7404 *mut_ref = val as _;
7405 }
7406 };
7407 }
7408 _ => {
7409 decoder.skip_wire_value(tag.wire_type())?;
7410 }
7411 }
7412 }
7413 Ok(())
7414 }
7415}
7416impl ::micropb::MessageEncode for CtrlMsg_Req_SetDhcpDnsStatus {
7417 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
7418 let mut max_size = 0;
7419 if let ::core::option::Option::Some(size) =
7420 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7421 {
7422 max_size += size;
7423 } else {
7424 break 'msg (::core::option::Option::<usize>::None);
7425 };
7426 if let ::core::option::Option::Some(size) =
7427 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7428 {
7429 max_size += size;
7430 } else {
7431 break 'msg (::core::option::Option::<usize>::None);
7432 };
7433 if let ::core::option::Option::Some(size) =
7434 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7435 {
7436 max_size += size;
7437 } else {
7438 break 'msg (::core::option::Option::<usize>::None);
7439 };
7440 if let ::core::option::Option::Some(size) =
7441 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
7442 {
7443 max_size += size;
7444 } else {
7445 break 'msg (::core::option::Option::<usize>::None);
7446 };
7447 if let ::core::option::Option::Some(size) =
7448 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
7449 {
7450 max_size += size;
7451 } else {
7452 break 'msg (::core::option::Option::<usize>::None);
7453 };
7454 if let ::core::option::Option::Some(size) =
7455 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
7456 {
7457 max_size += size;
7458 } else {
7459 break 'msg (::core::option::Option::<usize>::None);
7460 };
7461 if let ::core::option::Option::Some(size) =
7462 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7463 {
7464 max_size += size;
7465 } else {
7466 break 'msg (::core::option::Option::<usize>::None);
7467 };
7468 if let ::core::option::Option::Some(size) =
7469 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
7470 {
7471 max_size += size;
7472 } else {
7473 break 'msg (::core::option::Option::<usize>::None);
7474 };
7475 if let ::core::option::Option::Some(size) =
7476 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7477 {
7478 max_size += size;
7479 } else {
7480 break 'msg (::core::option::Option::<usize>::None);
7481 };
7482 ::core::option::Option::Some(max_size)
7483 };
7484 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
7485 &self,
7486 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
7487 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
7488 use ::micropb::{FieldEncode, PbMap};
7489 {
7490 let val_ref = &self.r#iface;
7491 if *val_ref != 0 {
7492 encoder.encode_varint32(8u32)?;
7493 encoder.encode_int32(*val_ref as _)?;
7494 }
7495 }
7496 {
7497 let val_ref = &self.r#net_link_up;
7498 if *val_ref != 0 {
7499 encoder.encode_varint32(16u32)?;
7500 encoder.encode_int32(*val_ref as _)?;
7501 }
7502 }
7503 {
7504 let val_ref = &self.r#dhcp_up;
7505 if *val_ref != 0 {
7506 encoder.encode_varint32(24u32)?;
7507 encoder.encode_int32(*val_ref as _)?;
7508 }
7509 }
7510 {
7511 let val_ref = &self.r#dhcp_ip;
7512 if !val_ref.is_empty() {
7513 encoder.encode_varint32(34u32)?;
7514 encoder.encode_bytes(val_ref)?;
7515 }
7516 }
7517 {
7518 let val_ref = &self.r#dhcp_nm;
7519 if !val_ref.is_empty() {
7520 encoder.encode_varint32(42u32)?;
7521 encoder.encode_bytes(val_ref)?;
7522 }
7523 }
7524 {
7525 let val_ref = &self.r#dhcp_gw;
7526 if !val_ref.is_empty() {
7527 encoder.encode_varint32(50u32)?;
7528 encoder.encode_bytes(val_ref)?;
7529 }
7530 }
7531 {
7532 let val_ref = &self.r#dns_up;
7533 if *val_ref != 0 {
7534 encoder.encode_varint32(56u32)?;
7535 encoder.encode_int32(*val_ref as _)?;
7536 }
7537 }
7538 {
7539 let val_ref = &self.r#dns_ip;
7540 if !val_ref.is_empty() {
7541 encoder.encode_varint32(66u32)?;
7542 encoder.encode_bytes(val_ref)?;
7543 }
7544 }
7545 {
7546 let val_ref = &self.r#dns_type;
7547 if *val_ref != 0 {
7548 encoder.encode_varint32(72u32)?;
7549 encoder.encode_int32(*val_ref as _)?;
7550 }
7551 }
7552 Ok(())
7553 }
7554 fn compute_size(&self) -> usize {
7555 use ::micropb::{FieldEncode, PbMap};
7556 let mut size = 0;
7557 {
7558 let val_ref = &self.r#iface;
7559 if *val_ref != 0 {
7560 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7561 }
7562 }
7563 {
7564 let val_ref = &self.r#net_link_up;
7565 if *val_ref != 0 {
7566 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7567 }
7568 }
7569 {
7570 let val_ref = &self.r#dhcp_up;
7571 if *val_ref != 0 {
7572 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7573 }
7574 }
7575 {
7576 let val_ref = &self.r#dhcp_ip;
7577 if !val_ref.is_empty() {
7578 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
7579 }
7580 }
7581 {
7582 let val_ref = &self.r#dhcp_nm;
7583 if !val_ref.is_empty() {
7584 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
7585 }
7586 }
7587 {
7588 let val_ref = &self.r#dhcp_gw;
7589 if !val_ref.is_empty() {
7590 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
7591 }
7592 }
7593 {
7594 let val_ref = &self.r#dns_up;
7595 if *val_ref != 0 {
7596 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7597 }
7598 }
7599 {
7600 let val_ref = &self.r#dns_ip;
7601 if !val_ref.is_empty() {
7602 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
7603 }
7604 }
7605 {
7606 let val_ref = &self.r#dns_type;
7607 if *val_ref != 0 {
7608 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7609 }
7610 }
7611 size
7612 }
7613}
7614#[derive(Debug, Default, PartialEq, Clone)]
7615#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7616pub struct CtrlMsg_Resp_SetDhcpDnsStatus {
7617 pub r#resp: i32,
7618}
7619impl CtrlMsg_Resp_SetDhcpDnsStatus {
7620 ///Return a reference to `resp`
7621 #[inline]
7622 pub fn r#resp(&self) -> &i32 {
7623 &self.r#resp
7624 }
7625 ///Return a mutable reference to `resp`
7626 #[inline]
7627 pub fn mut_resp(&mut self) -> &mut i32 {
7628 &mut self.r#resp
7629 }
7630 ///Set the value of `resp`
7631 #[inline]
7632 pub fn set_resp(&mut self, value: i32) -> &mut Self {
7633 self.r#resp = value.into();
7634 self
7635 }
7636 ///Builder method that sets the value of `resp`. Useful for initializing the message.
7637 #[inline]
7638 pub fn init_resp(mut self, value: i32) -> Self {
7639 self.r#resp = value.into();
7640 self
7641 }
7642}
7643impl ::micropb::MessageDecode for CtrlMsg_Resp_SetDhcpDnsStatus {
7644 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
7645 &mut self,
7646 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
7647 len: usize,
7648 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
7649 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
7650 let before = decoder.bytes_read();
7651 while decoder.bytes_read() - before < len {
7652 let tag = decoder.decode_tag()?;
7653 match tag.field_num() {
7654 0 => return Err(::micropb::DecodeError::ZeroField),
7655 1u32 => {
7656 let mut_ref = &mut self.r#resp;
7657 {
7658 let val = decoder.decode_int32()?;
7659 let val_ref = &val;
7660 if *val_ref != 0 {
7661 *mut_ref = val as _;
7662 }
7663 };
7664 }
7665 _ => {
7666 decoder.skip_wire_value(tag.wire_type())?;
7667 }
7668 }
7669 }
7670 Ok(())
7671 }
7672}
7673impl ::micropb::MessageEncode for CtrlMsg_Resp_SetDhcpDnsStatus {
7674 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
7675 let mut max_size = 0;
7676 if let ::core::option::Option::Some(size) =
7677 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
7678 {
7679 max_size += size;
7680 } else {
7681 break 'msg (::core::option::Option::<usize>::None);
7682 };
7683 ::core::option::Option::Some(max_size)
7684 };
7685 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
7686 &self,
7687 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
7688 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
7689 use ::micropb::{FieldEncode, PbMap};
7690 {
7691 let val_ref = &self.r#resp;
7692 if *val_ref != 0 {
7693 encoder.encode_varint32(8u32)?;
7694 encoder.encode_int32(*val_ref as _)?;
7695 }
7696 }
7697 Ok(())
7698 }
7699 fn compute_size(&self) -> usize {
7700 use ::micropb::{FieldEncode, PbMap};
7701 let mut size = 0;
7702 {
7703 let val_ref = &self.r#resp;
7704 if *val_ref != 0 {
7705 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
7706 }
7707 }
7708 size
7709 }
7710}
7711#[derive(Debug, Default, PartialEq, Clone)]
7712#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7713pub struct CtrlMsg_Req_GetDhcpDnsStatus {}
7714impl CtrlMsg_Req_GetDhcpDnsStatus {}
7715impl ::micropb::MessageDecode for CtrlMsg_Req_GetDhcpDnsStatus {
7716 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
7717 &mut self,
7718 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
7719 len: usize,
7720 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
7721 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
7722 let before = decoder.bytes_read();
7723 while decoder.bytes_read() - before < len {
7724 let tag = decoder.decode_tag()?;
7725 match tag.field_num() {
7726 0 => return Err(::micropb::DecodeError::ZeroField),
7727 _ => {
7728 decoder.skip_wire_value(tag.wire_type())?;
7729 }
7730 }
7731 }
7732 Ok(())
7733 }
7734}
7735impl ::micropb::MessageEncode for CtrlMsg_Req_GetDhcpDnsStatus {
7736 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
7737 let mut max_size = 0;
7738 ::core::option::Option::Some(max_size)
7739 };
7740 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
7741 &self,
7742 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
7743 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
7744 use ::micropb::{FieldEncode, PbMap};
7745 Ok(())
7746 }
7747 fn compute_size(&self) -> usize {
7748 use ::micropb::{FieldEncode, PbMap};
7749 let mut size = 0;
7750 size
7751 }
7752}
7753#[derive(Debug, Default, PartialEq, Clone)]
7754#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7755pub struct CtrlMsg_Resp_GetDhcpDnsStatus {
7756 pub r#resp: i32,
7757 pub r#iface: i32,
7758 pub r#net_link_up: i32,
7759 pub r#dhcp_up: i32,
7760 pub r#dhcp_ip: ::micropb::heapless::Vec<u8, 32>,
7761 pub r#dhcp_nm: ::micropb::heapless::Vec<u8, 32>,
7762 pub r#dhcp_gw: ::micropb::heapless::Vec<u8, 32>,
7763 pub r#dns_up: i32,
7764 pub r#dns_ip: ::micropb::heapless::Vec<u8, 32>,
7765 pub r#dns_type: i32,
7766}
7767impl CtrlMsg_Resp_GetDhcpDnsStatus {
7768 ///Return a reference to `resp`
7769 #[inline]
7770 pub fn r#resp(&self) -> &i32 {
7771 &self.r#resp
7772 }
7773 ///Return a mutable reference to `resp`
7774 #[inline]
7775 pub fn mut_resp(&mut self) -> &mut i32 {
7776 &mut self.r#resp
7777 }
7778 ///Set the value of `resp`
7779 #[inline]
7780 pub fn set_resp(&mut self, value: i32) -> &mut Self {
7781 self.r#resp = value.into();
7782 self
7783 }
7784 ///Builder method that sets the value of `resp`. Useful for initializing the message.
7785 #[inline]
7786 pub fn init_resp(mut self, value: i32) -> Self {
7787 self.r#resp = value.into();
7788 self
7789 }
7790 ///Return a reference to `iface`
7791 #[inline]
7792 pub fn r#iface(&self) -> &i32 {
7793 &self.r#iface
7794 }
7795 ///Return a mutable reference to `iface`
7796 #[inline]
7797 pub fn mut_iface(&mut self) -> &mut i32 {
7798 &mut self.r#iface
7799 }
7800 ///Set the value of `iface`
7801 #[inline]
7802 pub fn set_iface(&mut self, value: i32) -> &mut Self {
7803 self.r#iface = value.into();
7804 self
7805 }
7806 ///Builder method that sets the value of `iface`. Useful for initializing the message.
7807 #[inline]
7808 pub fn init_iface(mut self, value: i32) -> Self {
7809 self.r#iface = value.into();
7810 self
7811 }
7812 ///Return a reference to `net_link_up`
7813 #[inline]
7814 pub fn r#net_link_up(&self) -> &i32 {
7815 &self.r#net_link_up
7816 }
7817 ///Return a mutable reference to `net_link_up`
7818 #[inline]
7819 pub fn mut_net_link_up(&mut self) -> &mut i32 {
7820 &mut self.r#net_link_up
7821 }
7822 ///Set the value of `net_link_up`
7823 #[inline]
7824 pub fn set_net_link_up(&mut self, value: i32) -> &mut Self {
7825 self.r#net_link_up = value.into();
7826 self
7827 }
7828 ///Builder method that sets the value of `net_link_up`. Useful for initializing the message.
7829 #[inline]
7830 pub fn init_net_link_up(mut self, value: i32) -> Self {
7831 self.r#net_link_up = value.into();
7832 self
7833 }
7834 ///Return a reference to `dhcp_up`
7835 #[inline]
7836 pub fn r#dhcp_up(&self) -> &i32 {
7837 &self.r#dhcp_up
7838 }
7839 ///Return a mutable reference to `dhcp_up`
7840 #[inline]
7841 pub fn mut_dhcp_up(&mut self) -> &mut i32 {
7842 &mut self.r#dhcp_up
7843 }
7844 ///Set the value of `dhcp_up`
7845 #[inline]
7846 pub fn set_dhcp_up(&mut self, value: i32) -> &mut Self {
7847 self.r#dhcp_up = value.into();
7848 self
7849 }
7850 ///Builder method that sets the value of `dhcp_up`. Useful for initializing the message.
7851 #[inline]
7852 pub fn init_dhcp_up(mut self, value: i32) -> Self {
7853 self.r#dhcp_up = value.into();
7854 self
7855 }
7856 ///Return a reference to `dhcp_ip`
7857 #[inline]
7858 pub fn r#dhcp_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
7859 &self.r#dhcp_ip
7860 }
7861 ///Return a mutable reference to `dhcp_ip`
7862 #[inline]
7863 pub fn mut_dhcp_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7864 &mut self.r#dhcp_ip
7865 }
7866 ///Set the value of `dhcp_ip`
7867 #[inline]
7868 pub fn set_dhcp_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7869 self.r#dhcp_ip = value.into();
7870 self
7871 }
7872 ///Builder method that sets the value of `dhcp_ip`. Useful for initializing the message.
7873 #[inline]
7874 pub fn init_dhcp_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7875 self.r#dhcp_ip = value.into();
7876 self
7877 }
7878 ///Return a reference to `dhcp_nm`
7879 #[inline]
7880 pub fn r#dhcp_nm(&self) -> &::micropb::heapless::Vec<u8, 32> {
7881 &self.r#dhcp_nm
7882 }
7883 ///Return a mutable reference to `dhcp_nm`
7884 #[inline]
7885 pub fn mut_dhcp_nm(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7886 &mut self.r#dhcp_nm
7887 }
7888 ///Set the value of `dhcp_nm`
7889 #[inline]
7890 pub fn set_dhcp_nm(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7891 self.r#dhcp_nm = value.into();
7892 self
7893 }
7894 ///Builder method that sets the value of `dhcp_nm`. Useful for initializing the message.
7895 #[inline]
7896 pub fn init_dhcp_nm(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7897 self.r#dhcp_nm = value.into();
7898 self
7899 }
7900 ///Return a reference to `dhcp_gw`
7901 #[inline]
7902 pub fn r#dhcp_gw(&self) -> &::micropb::heapless::Vec<u8, 32> {
7903 &self.r#dhcp_gw
7904 }
7905 ///Return a mutable reference to `dhcp_gw`
7906 #[inline]
7907 pub fn mut_dhcp_gw(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7908 &mut self.r#dhcp_gw
7909 }
7910 ///Set the value of `dhcp_gw`
7911 #[inline]
7912 pub fn set_dhcp_gw(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7913 self.r#dhcp_gw = value.into();
7914 self
7915 }
7916 ///Builder method that sets the value of `dhcp_gw`. Useful for initializing the message.
7917 #[inline]
7918 pub fn init_dhcp_gw(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7919 self.r#dhcp_gw = value.into();
7920 self
7921 }
7922 ///Return a reference to `dns_up`
7923 #[inline]
7924 pub fn r#dns_up(&self) -> &i32 {
7925 &self.r#dns_up
7926 }
7927 ///Return a mutable reference to `dns_up`
7928 #[inline]
7929 pub fn mut_dns_up(&mut self) -> &mut i32 {
7930 &mut self.r#dns_up
7931 }
7932 ///Set the value of `dns_up`
7933 #[inline]
7934 pub fn set_dns_up(&mut self, value: i32) -> &mut Self {
7935 self.r#dns_up = value.into();
7936 self
7937 }
7938 ///Builder method that sets the value of `dns_up`. Useful for initializing the message.
7939 #[inline]
7940 pub fn init_dns_up(mut self, value: i32) -> Self {
7941 self.r#dns_up = value.into();
7942 self
7943 }
7944 ///Return a reference to `dns_ip`
7945 #[inline]
7946 pub fn r#dns_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
7947 &self.r#dns_ip
7948 }
7949 ///Return a mutable reference to `dns_ip`
7950 #[inline]
7951 pub fn mut_dns_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
7952 &mut self.r#dns_ip
7953 }
7954 ///Set the value of `dns_ip`
7955 #[inline]
7956 pub fn set_dns_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
7957 self.r#dns_ip = value.into();
7958 self
7959 }
7960 ///Builder method that sets the value of `dns_ip`. Useful for initializing the message.
7961 #[inline]
7962 pub fn init_dns_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
7963 self.r#dns_ip = value.into();
7964 self
7965 }
7966 ///Return a reference to `dns_type`
7967 #[inline]
7968 pub fn r#dns_type(&self) -> &i32 {
7969 &self.r#dns_type
7970 }
7971 ///Return a mutable reference to `dns_type`
7972 #[inline]
7973 pub fn mut_dns_type(&mut self) -> &mut i32 {
7974 &mut self.r#dns_type
7975 }
7976 ///Set the value of `dns_type`
7977 #[inline]
7978 pub fn set_dns_type(&mut self, value: i32) -> &mut Self {
7979 self.r#dns_type = value.into();
7980 self
7981 }
7982 ///Builder method that sets the value of `dns_type`. Useful for initializing the message.
7983 #[inline]
7984 pub fn init_dns_type(mut self, value: i32) -> Self {
7985 self.r#dns_type = value.into();
7986 self
7987 }
7988}
7989impl ::micropb::MessageDecode for CtrlMsg_Resp_GetDhcpDnsStatus {
7990 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
7991 &mut self,
7992 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
7993 len: usize,
7994 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
7995 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
7996 let before = decoder.bytes_read();
7997 while decoder.bytes_read() - before < len {
7998 let tag = decoder.decode_tag()?;
7999 match tag.field_num() {
8000 0 => return Err(::micropb::DecodeError::ZeroField),
8001 1u32 => {
8002 let mut_ref = &mut self.r#resp;
8003 {
8004 let val = decoder.decode_int32()?;
8005 let val_ref = &val;
8006 if *val_ref != 0 {
8007 *mut_ref = val as _;
8008 }
8009 };
8010 }
8011 2u32 => {
8012 let mut_ref = &mut self.r#iface;
8013 {
8014 let val = decoder.decode_int32()?;
8015 let val_ref = &val;
8016 if *val_ref != 0 {
8017 *mut_ref = val as _;
8018 }
8019 };
8020 }
8021 3u32 => {
8022 let mut_ref = &mut self.r#net_link_up;
8023 {
8024 let val = decoder.decode_int32()?;
8025 let val_ref = &val;
8026 if *val_ref != 0 {
8027 *mut_ref = val as _;
8028 }
8029 };
8030 }
8031 4u32 => {
8032 let mut_ref = &mut self.r#dhcp_up;
8033 {
8034 let val = decoder.decode_int32()?;
8035 let val_ref = &val;
8036 if *val_ref != 0 {
8037 *mut_ref = val as _;
8038 }
8039 };
8040 }
8041 5u32 => {
8042 let mut_ref = &mut self.r#dhcp_ip;
8043 {
8044 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8045 };
8046 }
8047 6u32 => {
8048 let mut_ref = &mut self.r#dhcp_nm;
8049 {
8050 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8051 };
8052 }
8053 7u32 => {
8054 let mut_ref = &mut self.r#dhcp_gw;
8055 {
8056 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8057 };
8058 }
8059 8u32 => {
8060 let mut_ref = &mut self.r#dns_up;
8061 {
8062 let val = decoder.decode_int32()?;
8063 let val_ref = &val;
8064 if *val_ref != 0 {
8065 *mut_ref = val as _;
8066 }
8067 };
8068 }
8069 9u32 => {
8070 let mut_ref = &mut self.r#dns_ip;
8071 {
8072 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8073 };
8074 }
8075 10u32 => {
8076 let mut_ref = &mut self.r#dns_type;
8077 {
8078 let val = decoder.decode_int32()?;
8079 let val_ref = &val;
8080 if *val_ref != 0 {
8081 *mut_ref = val as _;
8082 }
8083 };
8084 }
8085 _ => {
8086 decoder.skip_wire_value(tag.wire_type())?;
8087 }
8088 }
8089 }
8090 Ok(())
8091 }
8092}
8093impl ::micropb::MessageEncode for CtrlMsg_Resp_GetDhcpDnsStatus {
8094 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
8095 let mut max_size = 0;
8096 if let ::core::option::Option::Some(size) =
8097 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8098 {
8099 max_size += size;
8100 } else {
8101 break 'msg (::core::option::Option::<usize>::None);
8102 };
8103 if let ::core::option::Option::Some(size) =
8104 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8105 {
8106 max_size += size;
8107 } else {
8108 break 'msg (::core::option::Option::<usize>::None);
8109 };
8110 if let ::core::option::Option::Some(size) =
8111 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8112 {
8113 max_size += size;
8114 } else {
8115 break 'msg (::core::option::Option::<usize>::None);
8116 };
8117 if let ::core::option::Option::Some(size) =
8118 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8119 {
8120 max_size += size;
8121 } else {
8122 break 'msg (::core::option::Option::<usize>::None);
8123 };
8124 if let ::core::option::Option::Some(size) =
8125 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8126 {
8127 max_size += size;
8128 } else {
8129 break 'msg (::core::option::Option::<usize>::None);
8130 };
8131 if let ::core::option::Option::Some(size) =
8132 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8133 {
8134 max_size += size;
8135 } else {
8136 break 'msg (::core::option::Option::<usize>::None);
8137 };
8138 if let ::core::option::Option::Some(size) =
8139 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8140 {
8141 max_size += size;
8142 } else {
8143 break 'msg (::core::option::Option::<usize>::None);
8144 };
8145 if let ::core::option::Option::Some(size) =
8146 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8147 {
8148 max_size += size;
8149 } else {
8150 break 'msg (::core::option::Option::<usize>::None);
8151 };
8152 if let ::core::option::Option::Some(size) =
8153 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8154 {
8155 max_size += size;
8156 } else {
8157 break 'msg (::core::option::Option::<usize>::None);
8158 };
8159 if let ::core::option::Option::Some(size) =
8160 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8161 {
8162 max_size += size;
8163 } else {
8164 break 'msg (::core::option::Option::<usize>::None);
8165 };
8166 ::core::option::Option::Some(max_size)
8167 };
8168 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
8169 &self,
8170 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
8171 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
8172 use ::micropb::{FieldEncode, PbMap};
8173 {
8174 let val_ref = &self.r#resp;
8175 if *val_ref != 0 {
8176 encoder.encode_varint32(8u32)?;
8177 encoder.encode_int32(*val_ref as _)?;
8178 }
8179 }
8180 {
8181 let val_ref = &self.r#iface;
8182 if *val_ref != 0 {
8183 encoder.encode_varint32(16u32)?;
8184 encoder.encode_int32(*val_ref as _)?;
8185 }
8186 }
8187 {
8188 let val_ref = &self.r#net_link_up;
8189 if *val_ref != 0 {
8190 encoder.encode_varint32(24u32)?;
8191 encoder.encode_int32(*val_ref as _)?;
8192 }
8193 }
8194 {
8195 let val_ref = &self.r#dhcp_up;
8196 if *val_ref != 0 {
8197 encoder.encode_varint32(32u32)?;
8198 encoder.encode_int32(*val_ref as _)?;
8199 }
8200 }
8201 {
8202 let val_ref = &self.r#dhcp_ip;
8203 if !val_ref.is_empty() {
8204 encoder.encode_varint32(42u32)?;
8205 encoder.encode_bytes(val_ref)?;
8206 }
8207 }
8208 {
8209 let val_ref = &self.r#dhcp_nm;
8210 if !val_ref.is_empty() {
8211 encoder.encode_varint32(50u32)?;
8212 encoder.encode_bytes(val_ref)?;
8213 }
8214 }
8215 {
8216 let val_ref = &self.r#dhcp_gw;
8217 if !val_ref.is_empty() {
8218 encoder.encode_varint32(58u32)?;
8219 encoder.encode_bytes(val_ref)?;
8220 }
8221 }
8222 {
8223 let val_ref = &self.r#dns_up;
8224 if *val_ref != 0 {
8225 encoder.encode_varint32(64u32)?;
8226 encoder.encode_int32(*val_ref as _)?;
8227 }
8228 }
8229 {
8230 let val_ref = &self.r#dns_ip;
8231 if !val_ref.is_empty() {
8232 encoder.encode_varint32(74u32)?;
8233 encoder.encode_bytes(val_ref)?;
8234 }
8235 }
8236 {
8237 let val_ref = &self.r#dns_type;
8238 if *val_ref != 0 {
8239 encoder.encode_varint32(80u32)?;
8240 encoder.encode_int32(*val_ref as _)?;
8241 }
8242 }
8243 Ok(())
8244 }
8245 fn compute_size(&self) -> usize {
8246 use ::micropb::{FieldEncode, PbMap};
8247 let mut size = 0;
8248 {
8249 let val_ref = &self.r#resp;
8250 if *val_ref != 0 {
8251 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8252 }
8253 }
8254 {
8255 let val_ref = &self.r#iface;
8256 if *val_ref != 0 {
8257 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8258 }
8259 }
8260 {
8261 let val_ref = &self.r#net_link_up;
8262 if *val_ref != 0 {
8263 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8264 }
8265 }
8266 {
8267 let val_ref = &self.r#dhcp_up;
8268 if *val_ref != 0 {
8269 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8270 }
8271 }
8272 {
8273 let val_ref = &self.r#dhcp_ip;
8274 if !val_ref.is_empty() {
8275 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8276 }
8277 }
8278 {
8279 let val_ref = &self.r#dhcp_nm;
8280 if !val_ref.is_empty() {
8281 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8282 }
8283 }
8284 {
8285 let val_ref = &self.r#dhcp_gw;
8286 if !val_ref.is_empty() {
8287 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8288 }
8289 }
8290 {
8291 let val_ref = &self.r#dns_up;
8292 if *val_ref != 0 {
8293 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8294 }
8295 }
8296 {
8297 let val_ref = &self.r#dns_ip;
8298 if !val_ref.is_empty() {
8299 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8300 }
8301 }
8302 {
8303 let val_ref = &self.r#dns_type;
8304 if *val_ref != 0 {
8305 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8306 }
8307 }
8308 size
8309 }
8310}
8311#[derive(Debug, Default, PartialEq, Clone)]
8312#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8313pub struct CtrlMsg_Event_ESPInit {
8314 pub r#init_data: ::micropb::heapless::Vec<u8, 64>,
8315}
8316impl CtrlMsg_Event_ESPInit {
8317 ///Return a reference to `init_data`
8318 #[inline]
8319 pub fn r#init_data(&self) -> &::micropb::heapless::Vec<u8, 64> {
8320 &self.r#init_data
8321 }
8322 ///Return a mutable reference to `init_data`
8323 #[inline]
8324 pub fn mut_init_data(&mut self) -> &mut ::micropb::heapless::Vec<u8, 64> {
8325 &mut self.r#init_data
8326 }
8327 ///Set the value of `init_data`
8328 #[inline]
8329 pub fn set_init_data(&mut self, value: ::micropb::heapless::Vec<u8, 64>) -> &mut Self {
8330 self.r#init_data = value.into();
8331 self
8332 }
8333 ///Builder method that sets the value of `init_data`. Useful for initializing the message.
8334 #[inline]
8335 pub fn init_init_data(mut self, value: ::micropb::heapless::Vec<u8, 64>) -> Self {
8336 self.r#init_data = value.into();
8337 self
8338 }
8339}
8340impl ::micropb::MessageDecode for CtrlMsg_Event_ESPInit {
8341 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
8342 &mut self,
8343 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
8344 len: usize,
8345 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
8346 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
8347 let before = decoder.bytes_read();
8348 while decoder.bytes_read() - before < len {
8349 let tag = decoder.decode_tag()?;
8350 match tag.field_num() {
8351 0 => return Err(::micropb::DecodeError::ZeroField),
8352 1u32 => {
8353 let mut_ref = &mut self.r#init_data;
8354 {
8355 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8356 };
8357 }
8358 _ => {
8359 decoder.skip_wire_value(tag.wire_type())?;
8360 }
8361 }
8362 }
8363 Ok(())
8364 }
8365}
8366impl ::micropb::MessageEncode for CtrlMsg_Event_ESPInit {
8367 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
8368 let mut max_size = 0;
8369 if let ::core::option::Option::Some(size) =
8370 ::micropb::const_map!(::core::option::Option::Some(65usize), |size| size + 1usize)
8371 {
8372 max_size += size;
8373 } else {
8374 break 'msg (::core::option::Option::<usize>::None);
8375 };
8376 ::core::option::Option::Some(max_size)
8377 };
8378 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
8379 &self,
8380 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
8381 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
8382 use ::micropb::{FieldEncode, PbMap};
8383 {
8384 let val_ref = &self.r#init_data;
8385 if !val_ref.is_empty() {
8386 encoder.encode_varint32(10u32)?;
8387 encoder.encode_bytes(val_ref)?;
8388 }
8389 }
8390 Ok(())
8391 }
8392 fn compute_size(&self) -> usize {
8393 use ::micropb::{FieldEncode, PbMap};
8394 let mut size = 0;
8395 {
8396 let val_ref = &self.r#init_data;
8397 if !val_ref.is_empty() {
8398 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8399 }
8400 }
8401 size
8402 }
8403}
8404#[derive(Debug, Default, PartialEq, Clone)]
8405#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8406pub struct CtrlMsg_Event_Heartbeat {
8407 pub r#hb_num: i32,
8408}
8409impl CtrlMsg_Event_Heartbeat {
8410 ///Return a reference to `hb_num`
8411 #[inline]
8412 pub fn r#hb_num(&self) -> &i32 {
8413 &self.r#hb_num
8414 }
8415 ///Return a mutable reference to `hb_num`
8416 #[inline]
8417 pub fn mut_hb_num(&mut self) -> &mut i32 {
8418 &mut self.r#hb_num
8419 }
8420 ///Set the value of `hb_num`
8421 #[inline]
8422 pub fn set_hb_num(&mut self, value: i32) -> &mut Self {
8423 self.r#hb_num = value.into();
8424 self
8425 }
8426 ///Builder method that sets the value of `hb_num`. Useful for initializing the message.
8427 #[inline]
8428 pub fn init_hb_num(mut self, value: i32) -> Self {
8429 self.r#hb_num = value.into();
8430 self
8431 }
8432}
8433impl ::micropb::MessageDecode for CtrlMsg_Event_Heartbeat {
8434 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
8435 &mut self,
8436 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
8437 len: usize,
8438 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
8439 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
8440 let before = decoder.bytes_read();
8441 while decoder.bytes_read() - before < len {
8442 let tag = decoder.decode_tag()?;
8443 match tag.field_num() {
8444 0 => return Err(::micropb::DecodeError::ZeroField),
8445 1u32 => {
8446 let mut_ref = &mut self.r#hb_num;
8447 {
8448 let val = decoder.decode_int32()?;
8449 let val_ref = &val;
8450 if *val_ref != 0 {
8451 *mut_ref = val as _;
8452 }
8453 };
8454 }
8455 _ => {
8456 decoder.skip_wire_value(tag.wire_type())?;
8457 }
8458 }
8459 }
8460 Ok(())
8461 }
8462}
8463impl ::micropb::MessageEncode for CtrlMsg_Event_Heartbeat {
8464 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
8465 let mut max_size = 0;
8466 if let ::core::option::Option::Some(size) =
8467 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8468 {
8469 max_size += size;
8470 } else {
8471 break 'msg (::core::option::Option::<usize>::None);
8472 };
8473 ::core::option::Option::Some(max_size)
8474 };
8475 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
8476 &self,
8477 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
8478 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
8479 use ::micropb::{FieldEncode, PbMap};
8480 {
8481 let val_ref = &self.r#hb_num;
8482 if *val_ref != 0 {
8483 encoder.encode_varint32(8u32)?;
8484 encoder.encode_int32(*val_ref as _)?;
8485 }
8486 }
8487 Ok(())
8488 }
8489 fn compute_size(&self) -> usize {
8490 use ::micropb::{FieldEncode, PbMap};
8491 let mut size = 0;
8492 {
8493 let val_ref = &self.r#hb_num;
8494 if *val_ref != 0 {
8495 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8496 }
8497 }
8498 size
8499 }
8500}
8501#[derive(Debug, Default, PartialEq, Clone)]
8502#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8503pub struct CtrlMsg_Event_StationDisconnectFromAP {
8504 pub r#resp: i32,
8505 pub r#ssid: ::micropb::heapless::Vec<u8, 32>,
8506 pub r#ssid_len: u32,
8507 pub r#bssid: ::micropb::heapless::Vec<u8, 32>,
8508 pub r#reason: u32,
8509 pub r#rssi: i32,
8510}
8511impl CtrlMsg_Event_StationDisconnectFromAP {
8512 ///Return a reference to `resp`
8513 #[inline]
8514 pub fn r#resp(&self) -> &i32 {
8515 &self.r#resp
8516 }
8517 ///Return a mutable reference to `resp`
8518 #[inline]
8519 pub fn mut_resp(&mut self) -> &mut i32 {
8520 &mut self.r#resp
8521 }
8522 ///Set the value of `resp`
8523 #[inline]
8524 pub fn set_resp(&mut self, value: i32) -> &mut Self {
8525 self.r#resp = value.into();
8526 self
8527 }
8528 ///Builder method that sets the value of `resp`. Useful for initializing the message.
8529 #[inline]
8530 pub fn init_resp(mut self, value: i32) -> Self {
8531 self.r#resp = value.into();
8532 self
8533 }
8534 ///Return a reference to `ssid`
8535 #[inline]
8536 pub fn r#ssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
8537 &self.r#ssid
8538 }
8539 ///Return a mutable reference to `ssid`
8540 #[inline]
8541 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
8542 &mut self.r#ssid
8543 }
8544 ///Set the value of `ssid`
8545 #[inline]
8546 pub fn set_ssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
8547 self.r#ssid = value.into();
8548 self
8549 }
8550 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
8551 #[inline]
8552 pub fn init_ssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
8553 self.r#ssid = value.into();
8554 self
8555 }
8556 ///Return a reference to `ssid_len`
8557 #[inline]
8558 pub fn r#ssid_len(&self) -> &u32 {
8559 &self.r#ssid_len
8560 }
8561 ///Return a mutable reference to `ssid_len`
8562 #[inline]
8563 pub fn mut_ssid_len(&mut self) -> &mut u32 {
8564 &mut self.r#ssid_len
8565 }
8566 ///Set the value of `ssid_len`
8567 #[inline]
8568 pub fn set_ssid_len(&mut self, value: u32) -> &mut Self {
8569 self.r#ssid_len = value.into();
8570 self
8571 }
8572 ///Builder method that sets the value of `ssid_len`. Useful for initializing the message.
8573 #[inline]
8574 pub fn init_ssid_len(mut self, value: u32) -> Self {
8575 self.r#ssid_len = value.into();
8576 self
8577 }
8578 ///Return a reference to `bssid`
8579 #[inline]
8580 pub fn r#bssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
8581 &self.r#bssid
8582 }
8583 ///Return a mutable reference to `bssid`
8584 #[inline]
8585 pub fn mut_bssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
8586 &mut self.r#bssid
8587 }
8588 ///Set the value of `bssid`
8589 #[inline]
8590 pub fn set_bssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
8591 self.r#bssid = value.into();
8592 self
8593 }
8594 ///Builder method that sets the value of `bssid`. Useful for initializing the message.
8595 #[inline]
8596 pub fn init_bssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
8597 self.r#bssid = value.into();
8598 self
8599 }
8600 ///Return a reference to `reason`
8601 #[inline]
8602 pub fn r#reason(&self) -> &u32 {
8603 &self.r#reason
8604 }
8605 ///Return a mutable reference to `reason`
8606 #[inline]
8607 pub fn mut_reason(&mut self) -> &mut u32 {
8608 &mut self.r#reason
8609 }
8610 ///Set the value of `reason`
8611 #[inline]
8612 pub fn set_reason(&mut self, value: u32) -> &mut Self {
8613 self.r#reason = value.into();
8614 self
8615 }
8616 ///Builder method that sets the value of `reason`. Useful for initializing the message.
8617 #[inline]
8618 pub fn init_reason(mut self, value: u32) -> Self {
8619 self.r#reason = value.into();
8620 self
8621 }
8622 ///Return a reference to `rssi`
8623 #[inline]
8624 pub fn r#rssi(&self) -> &i32 {
8625 &self.r#rssi
8626 }
8627 ///Return a mutable reference to `rssi`
8628 #[inline]
8629 pub fn mut_rssi(&mut self) -> &mut i32 {
8630 &mut self.r#rssi
8631 }
8632 ///Set the value of `rssi`
8633 #[inline]
8634 pub fn set_rssi(&mut self, value: i32) -> &mut Self {
8635 self.r#rssi = value.into();
8636 self
8637 }
8638 ///Builder method that sets the value of `rssi`. Useful for initializing the message.
8639 #[inline]
8640 pub fn init_rssi(mut self, value: i32) -> Self {
8641 self.r#rssi = value.into();
8642 self
8643 }
8644}
8645impl ::micropb::MessageDecode for CtrlMsg_Event_StationDisconnectFromAP {
8646 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
8647 &mut self,
8648 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
8649 len: usize,
8650 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
8651 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
8652 let before = decoder.bytes_read();
8653 while decoder.bytes_read() - before < len {
8654 let tag = decoder.decode_tag()?;
8655 match tag.field_num() {
8656 0 => return Err(::micropb::DecodeError::ZeroField),
8657 1u32 => {
8658 let mut_ref = &mut self.r#resp;
8659 {
8660 let val = decoder.decode_int32()?;
8661 let val_ref = &val;
8662 if *val_ref != 0 {
8663 *mut_ref = val as _;
8664 }
8665 };
8666 }
8667 2u32 => {
8668 let mut_ref = &mut self.r#ssid;
8669 {
8670 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8671 };
8672 }
8673 3u32 => {
8674 let mut_ref = &mut self.r#ssid_len;
8675 {
8676 let val = decoder.decode_varint32()?;
8677 let val_ref = &val;
8678 if *val_ref != 0 {
8679 *mut_ref = val as _;
8680 }
8681 };
8682 }
8683 4u32 => {
8684 let mut_ref = &mut self.r#bssid;
8685 {
8686 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
8687 };
8688 }
8689 5u32 => {
8690 let mut_ref = &mut self.r#reason;
8691 {
8692 let val = decoder.decode_varint32()?;
8693 let val_ref = &val;
8694 if *val_ref != 0 {
8695 *mut_ref = val as _;
8696 }
8697 };
8698 }
8699 6u32 => {
8700 let mut_ref = &mut self.r#rssi;
8701 {
8702 let val = decoder.decode_int32()?;
8703 let val_ref = &val;
8704 if *val_ref != 0 {
8705 *mut_ref = val as _;
8706 }
8707 };
8708 }
8709 _ => {
8710 decoder.skip_wire_value(tag.wire_type())?;
8711 }
8712 }
8713 }
8714 Ok(())
8715 }
8716}
8717impl ::micropb::MessageEncode for CtrlMsg_Event_StationDisconnectFromAP {
8718 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
8719 let mut max_size = 0;
8720 if let ::core::option::Option::Some(size) =
8721 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8722 {
8723 max_size += size;
8724 } else {
8725 break 'msg (::core::option::Option::<usize>::None);
8726 };
8727 if let ::core::option::Option::Some(size) =
8728 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8729 {
8730 max_size += size;
8731 } else {
8732 break 'msg (::core::option::Option::<usize>::None);
8733 };
8734 if let ::core::option::Option::Some(size) =
8735 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
8736 {
8737 max_size += size;
8738 } else {
8739 break 'msg (::core::option::Option::<usize>::None);
8740 };
8741 if let ::core::option::Option::Some(size) =
8742 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
8743 {
8744 max_size += size;
8745 } else {
8746 break 'msg (::core::option::Option::<usize>::None);
8747 };
8748 if let ::core::option::Option::Some(size) =
8749 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
8750 {
8751 max_size += size;
8752 } else {
8753 break 'msg (::core::option::Option::<usize>::None);
8754 };
8755 if let ::core::option::Option::Some(size) =
8756 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
8757 {
8758 max_size += size;
8759 } else {
8760 break 'msg (::core::option::Option::<usize>::None);
8761 };
8762 ::core::option::Option::Some(max_size)
8763 };
8764 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
8765 &self,
8766 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
8767 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
8768 use ::micropb::{FieldEncode, PbMap};
8769 {
8770 let val_ref = &self.r#resp;
8771 if *val_ref != 0 {
8772 encoder.encode_varint32(8u32)?;
8773 encoder.encode_int32(*val_ref as _)?;
8774 }
8775 }
8776 {
8777 let val_ref = &self.r#ssid;
8778 if !val_ref.is_empty() {
8779 encoder.encode_varint32(18u32)?;
8780 encoder.encode_bytes(val_ref)?;
8781 }
8782 }
8783 {
8784 let val_ref = &self.r#ssid_len;
8785 if *val_ref != 0 {
8786 encoder.encode_varint32(24u32)?;
8787 encoder.encode_varint32(*val_ref as _)?;
8788 }
8789 }
8790 {
8791 let val_ref = &self.r#bssid;
8792 if !val_ref.is_empty() {
8793 encoder.encode_varint32(34u32)?;
8794 encoder.encode_bytes(val_ref)?;
8795 }
8796 }
8797 {
8798 let val_ref = &self.r#reason;
8799 if *val_ref != 0 {
8800 encoder.encode_varint32(40u32)?;
8801 encoder.encode_varint32(*val_ref as _)?;
8802 }
8803 }
8804 {
8805 let val_ref = &self.r#rssi;
8806 if *val_ref != 0 {
8807 encoder.encode_varint32(48u32)?;
8808 encoder.encode_int32(*val_ref as _)?;
8809 }
8810 }
8811 Ok(())
8812 }
8813 fn compute_size(&self) -> usize {
8814 use ::micropb::{FieldEncode, PbMap};
8815 let mut size = 0;
8816 {
8817 let val_ref = &self.r#resp;
8818 if *val_ref != 0 {
8819 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8820 }
8821 }
8822 {
8823 let val_ref = &self.r#ssid;
8824 if !val_ref.is_empty() {
8825 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8826 }
8827 }
8828 {
8829 let val_ref = &self.r#ssid_len;
8830 if *val_ref != 0 {
8831 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
8832 }
8833 }
8834 {
8835 let val_ref = &self.r#bssid;
8836 if !val_ref.is_empty() {
8837 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
8838 }
8839 }
8840 {
8841 let val_ref = &self.r#reason;
8842 if *val_ref != 0 {
8843 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
8844 }
8845 }
8846 {
8847 let val_ref = &self.r#rssi;
8848 if *val_ref != 0 {
8849 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
8850 }
8851 }
8852 size
8853 }
8854}
8855#[derive(Debug, Default, PartialEq, Clone)]
8856#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8857pub struct CtrlMsg_Event_StationConnectedToAP {
8858 pub r#resp: i32,
8859 pub r#ssid: ::micropb::heapless::Vec<u8, 32>,
8860 pub r#ssid_len: u32,
8861 pub r#bssid: ::micropb::heapless::Vec<u8, 32>,
8862 pub r#channel: u32,
8863 pub r#authmode: i32,
8864 pub r#aid: i32,
8865}
8866impl CtrlMsg_Event_StationConnectedToAP {
8867 ///Return a reference to `resp`
8868 #[inline]
8869 pub fn r#resp(&self) -> &i32 {
8870 &self.r#resp
8871 }
8872 ///Return a mutable reference to `resp`
8873 #[inline]
8874 pub fn mut_resp(&mut self) -> &mut i32 {
8875 &mut self.r#resp
8876 }
8877 ///Set the value of `resp`
8878 #[inline]
8879 pub fn set_resp(&mut self, value: i32) -> &mut Self {
8880 self.r#resp = value.into();
8881 self
8882 }
8883 ///Builder method that sets the value of `resp`. Useful for initializing the message.
8884 #[inline]
8885 pub fn init_resp(mut self, value: i32) -> Self {
8886 self.r#resp = value.into();
8887 self
8888 }
8889 ///Return a reference to `ssid`
8890 #[inline]
8891 pub fn r#ssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
8892 &self.r#ssid
8893 }
8894 ///Return a mutable reference to `ssid`
8895 #[inline]
8896 pub fn mut_ssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
8897 &mut self.r#ssid
8898 }
8899 ///Set the value of `ssid`
8900 #[inline]
8901 pub fn set_ssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
8902 self.r#ssid = value.into();
8903 self
8904 }
8905 ///Builder method that sets the value of `ssid`. Useful for initializing the message.
8906 #[inline]
8907 pub fn init_ssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
8908 self.r#ssid = value.into();
8909 self
8910 }
8911 ///Return a reference to `ssid_len`
8912 #[inline]
8913 pub fn r#ssid_len(&self) -> &u32 {
8914 &self.r#ssid_len
8915 }
8916 ///Return a mutable reference to `ssid_len`
8917 #[inline]
8918 pub fn mut_ssid_len(&mut self) -> &mut u32 {
8919 &mut self.r#ssid_len
8920 }
8921 ///Set the value of `ssid_len`
8922 #[inline]
8923 pub fn set_ssid_len(&mut self, value: u32) -> &mut Self {
8924 self.r#ssid_len = value.into();
8925 self
8926 }
8927 ///Builder method that sets the value of `ssid_len`. Useful for initializing the message.
8928 #[inline]
8929 pub fn init_ssid_len(mut self, value: u32) -> Self {
8930 self.r#ssid_len = value.into();
8931 self
8932 }
8933 ///Return a reference to `bssid`
8934 #[inline]
8935 pub fn r#bssid(&self) -> &::micropb::heapless::Vec<u8, 32> {
8936 &self.r#bssid
8937 }
8938 ///Return a mutable reference to `bssid`
8939 #[inline]
8940 pub fn mut_bssid(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
8941 &mut self.r#bssid
8942 }
8943 ///Set the value of `bssid`
8944 #[inline]
8945 pub fn set_bssid(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
8946 self.r#bssid = value.into();
8947 self
8948 }
8949 ///Builder method that sets the value of `bssid`. Useful for initializing the message.
8950 #[inline]
8951 pub fn init_bssid(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
8952 self.r#bssid = value.into();
8953 self
8954 }
8955 ///Return a reference to `channel`
8956 #[inline]
8957 pub fn r#channel(&self) -> &u32 {
8958 &self.r#channel
8959 }
8960 ///Return a mutable reference to `channel`
8961 #[inline]
8962 pub fn mut_channel(&mut self) -> &mut u32 {
8963 &mut self.r#channel
8964 }
8965 ///Set the value of `channel`
8966 #[inline]
8967 pub fn set_channel(&mut self, value: u32) -> &mut Self {
8968 self.r#channel = value.into();
8969 self
8970 }
8971 ///Builder method that sets the value of `channel`. Useful for initializing the message.
8972 #[inline]
8973 pub fn init_channel(mut self, value: u32) -> Self {
8974 self.r#channel = value.into();
8975 self
8976 }
8977 ///Return a reference to `authmode`
8978 #[inline]
8979 pub fn r#authmode(&self) -> &i32 {
8980 &self.r#authmode
8981 }
8982 ///Return a mutable reference to `authmode`
8983 #[inline]
8984 pub fn mut_authmode(&mut self) -> &mut i32 {
8985 &mut self.r#authmode
8986 }
8987 ///Set the value of `authmode`
8988 #[inline]
8989 pub fn set_authmode(&mut self, value: i32) -> &mut Self {
8990 self.r#authmode = value.into();
8991 self
8992 }
8993 ///Builder method that sets the value of `authmode`. Useful for initializing the message.
8994 #[inline]
8995 pub fn init_authmode(mut self, value: i32) -> Self {
8996 self.r#authmode = value.into();
8997 self
8998 }
8999 ///Return a reference to `aid`
9000 #[inline]
9001 pub fn r#aid(&self) -> &i32 {
9002 &self.r#aid
9003 }
9004 ///Return a mutable reference to `aid`
9005 #[inline]
9006 pub fn mut_aid(&mut self) -> &mut i32 {
9007 &mut self.r#aid
9008 }
9009 ///Set the value of `aid`
9010 #[inline]
9011 pub fn set_aid(&mut self, value: i32) -> &mut Self {
9012 self.r#aid = value.into();
9013 self
9014 }
9015 ///Builder method that sets the value of `aid`. Useful for initializing the message.
9016 #[inline]
9017 pub fn init_aid(mut self, value: i32) -> Self {
9018 self.r#aid = value.into();
9019 self
9020 }
9021}
9022impl ::micropb::MessageDecode for CtrlMsg_Event_StationConnectedToAP {
9023 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
9024 &mut self,
9025 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
9026 len: usize,
9027 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
9028 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
9029 let before = decoder.bytes_read();
9030 while decoder.bytes_read() - before < len {
9031 let tag = decoder.decode_tag()?;
9032 match tag.field_num() {
9033 0 => return Err(::micropb::DecodeError::ZeroField),
9034 1u32 => {
9035 let mut_ref = &mut self.r#resp;
9036 {
9037 let val = decoder.decode_int32()?;
9038 let val_ref = &val;
9039 if *val_ref != 0 {
9040 *mut_ref = val as _;
9041 }
9042 };
9043 }
9044 2u32 => {
9045 let mut_ref = &mut self.r#ssid;
9046 {
9047 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
9048 };
9049 }
9050 3u32 => {
9051 let mut_ref = &mut self.r#ssid_len;
9052 {
9053 let val = decoder.decode_varint32()?;
9054 let val_ref = &val;
9055 if *val_ref != 0 {
9056 *mut_ref = val as _;
9057 }
9058 };
9059 }
9060 4u32 => {
9061 let mut_ref = &mut self.r#bssid;
9062 {
9063 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
9064 };
9065 }
9066 5u32 => {
9067 let mut_ref = &mut self.r#channel;
9068 {
9069 let val = decoder.decode_varint32()?;
9070 let val_ref = &val;
9071 if *val_ref != 0 {
9072 *mut_ref = val as _;
9073 }
9074 };
9075 }
9076 6u32 => {
9077 let mut_ref = &mut self.r#authmode;
9078 {
9079 let val = decoder.decode_int32()?;
9080 let val_ref = &val;
9081 if *val_ref != 0 {
9082 *mut_ref = val as _;
9083 }
9084 };
9085 }
9086 7u32 => {
9087 let mut_ref = &mut self.r#aid;
9088 {
9089 let val = decoder.decode_int32()?;
9090 let val_ref = &val;
9091 if *val_ref != 0 {
9092 *mut_ref = val as _;
9093 }
9094 };
9095 }
9096 _ => {
9097 decoder.skip_wire_value(tag.wire_type())?;
9098 }
9099 }
9100 }
9101 Ok(())
9102 }
9103}
9104impl ::micropb::MessageEncode for CtrlMsg_Event_StationConnectedToAP {
9105 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
9106 let mut max_size = 0;
9107 if let ::core::option::Option::Some(size) =
9108 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
9109 {
9110 max_size += size;
9111 } else {
9112 break 'msg (::core::option::Option::<usize>::None);
9113 };
9114 if let ::core::option::Option::Some(size) =
9115 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
9116 {
9117 max_size += size;
9118 } else {
9119 break 'msg (::core::option::Option::<usize>::None);
9120 };
9121 if let ::core::option::Option::Some(size) =
9122 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
9123 {
9124 max_size += size;
9125 } else {
9126 break 'msg (::core::option::Option::<usize>::None);
9127 };
9128 if let ::core::option::Option::Some(size) =
9129 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
9130 {
9131 max_size += size;
9132 } else {
9133 break 'msg (::core::option::Option::<usize>::None);
9134 };
9135 if let ::core::option::Option::Some(size) =
9136 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
9137 {
9138 max_size += size;
9139 } else {
9140 break 'msg (::core::option::Option::<usize>::None);
9141 };
9142 if let ::core::option::Option::Some(size) =
9143 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
9144 {
9145 max_size += size;
9146 } else {
9147 break 'msg (::core::option::Option::<usize>::None);
9148 };
9149 if let ::core::option::Option::Some(size) =
9150 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
9151 {
9152 max_size += size;
9153 } else {
9154 break 'msg (::core::option::Option::<usize>::None);
9155 };
9156 ::core::option::Option::Some(max_size)
9157 };
9158 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
9159 &self,
9160 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
9161 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
9162 use ::micropb::{FieldEncode, PbMap};
9163 {
9164 let val_ref = &self.r#resp;
9165 if *val_ref != 0 {
9166 encoder.encode_varint32(8u32)?;
9167 encoder.encode_int32(*val_ref as _)?;
9168 }
9169 }
9170 {
9171 let val_ref = &self.r#ssid;
9172 if !val_ref.is_empty() {
9173 encoder.encode_varint32(18u32)?;
9174 encoder.encode_bytes(val_ref)?;
9175 }
9176 }
9177 {
9178 let val_ref = &self.r#ssid_len;
9179 if *val_ref != 0 {
9180 encoder.encode_varint32(24u32)?;
9181 encoder.encode_varint32(*val_ref as _)?;
9182 }
9183 }
9184 {
9185 let val_ref = &self.r#bssid;
9186 if !val_ref.is_empty() {
9187 encoder.encode_varint32(34u32)?;
9188 encoder.encode_bytes(val_ref)?;
9189 }
9190 }
9191 {
9192 let val_ref = &self.r#channel;
9193 if *val_ref != 0 {
9194 encoder.encode_varint32(40u32)?;
9195 encoder.encode_varint32(*val_ref as _)?;
9196 }
9197 }
9198 {
9199 let val_ref = &self.r#authmode;
9200 if *val_ref != 0 {
9201 encoder.encode_varint32(48u32)?;
9202 encoder.encode_int32(*val_ref as _)?;
9203 }
9204 }
9205 {
9206 let val_ref = &self.r#aid;
9207 if *val_ref != 0 {
9208 encoder.encode_varint32(56u32)?;
9209 encoder.encode_int32(*val_ref as _)?;
9210 }
9211 }
9212 Ok(())
9213 }
9214 fn compute_size(&self) -> usize {
9215 use ::micropb::{FieldEncode, PbMap};
9216 let mut size = 0;
9217 {
9218 let val_ref = &self.r#resp;
9219 if *val_ref != 0 {
9220 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
9221 }
9222 }
9223 {
9224 let val_ref = &self.r#ssid;
9225 if !val_ref.is_empty() {
9226 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
9227 }
9228 }
9229 {
9230 let val_ref = &self.r#ssid_len;
9231 if *val_ref != 0 {
9232 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
9233 }
9234 }
9235 {
9236 let val_ref = &self.r#bssid;
9237 if !val_ref.is_empty() {
9238 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
9239 }
9240 }
9241 {
9242 let val_ref = &self.r#channel;
9243 if *val_ref != 0 {
9244 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
9245 }
9246 }
9247 {
9248 let val_ref = &self.r#authmode;
9249 if *val_ref != 0 {
9250 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
9251 }
9252 }
9253 {
9254 let val_ref = &self.r#aid;
9255 if *val_ref != 0 {
9256 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
9257 }
9258 }
9259 size
9260 }
9261}
9262#[derive(Debug, Default, PartialEq, Clone)]
9263#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9264pub struct CtrlMsg_Event_StationDisconnectFromESPSoftAP {
9265 pub r#resp: i32,
9266 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
9267 pub r#aid: u32,
9268 pub r#is_mesh_child: bool,
9269 pub r#reason: u32,
9270}
9271impl CtrlMsg_Event_StationDisconnectFromESPSoftAP {
9272 ///Return a reference to `resp`
9273 #[inline]
9274 pub fn r#resp(&self) -> &i32 {
9275 &self.r#resp
9276 }
9277 ///Return a mutable reference to `resp`
9278 #[inline]
9279 pub fn mut_resp(&mut self) -> &mut i32 {
9280 &mut self.r#resp
9281 }
9282 ///Set the value of `resp`
9283 #[inline]
9284 pub fn set_resp(&mut self, value: i32) -> &mut Self {
9285 self.r#resp = value.into();
9286 self
9287 }
9288 ///Builder method that sets the value of `resp`. Useful for initializing the message.
9289 #[inline]
9290 pub fn init_resp(mut self, value: i32) -> Self {
9291 self.r#resp = value.into();
9292 self
9293 }
9294 ///Return a reference to `mac`
9295 #[inline]
9296 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
9297 &self.r#mac
9298 }
9299 ///Return a mutable reference to `mac`
9300 #[inline]
9301 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9302 &mut self.r#mac
9303 }
9304 ///Set the value of `mac`
9305 #[inline]
9306 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
9307 self.r#mac = value.into();
9308 self
9309 }
9310 ///Builder method that sets the value of `mac`. Useful for initializing the message.
9311 #[inline]
9312 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
9313 self.r#mac = value.into();
9314 self
9315 }
9316 ///Return a reference to `aid`
9317 #[inline]
9318 pub fn r#aid(&self) -> &u32 {
9319 &self.r#aid
9320 }
9321 ///Return a mutable reference to `aid`
9322 #[inline]
9323 pub fn mut_aid(&mut self) -> &mut u32 {
9324 &mut self.r#aid
9325 }
9326 ///Set the value of `aid`
9327 #[inline]
9328 pub fn set_aid(&mut self, value: u32) -> &mut Self {
9329 self.r#aid = value.into();
9330 self
9331 }
9332 ///Builder method that sets the value of `aid`. Useful for initializing the message.
9333 #[inline]
9334 pub fn init_aid(mut self, value: u32) -> Self {
9335 self.r#aid = value.into();
9336 self
9337 }
9338 ///Return a reference to `is_mesh_child`
9339 #[inline]
9340 pub fn r#is_mesh_child(&self) -> &bool {
9341 &self.r#is_mesh_child
9342 }
9343 ///Return a mutable reference to `is_mesh_child`
9344 #[inline]
9345 pub fn mut_is_mesh_child(&mut self) -> &mut bool {
9346 &mut self.r#is_mesh_child
9347 }
9348 ///Set the value of `is_mesh_child`
9349 #[inline]
9350 pub fn set_is_mesh_child(&mut self, value: bool) -> &mut Self {
9351 self.r#is_mesh_child = value.into();
9352 self
9353 }
9354 ///Builder method that sets the value of `is_mesh_child`. Useful for initializing the message.
9355 #[inline]
9356 pub fn init_is_mesh_child(mut self, value: bool) -> Self {
9357 self.r#is_mesh_child = value.into();
9358 self
9359 }
9360 ///Return a reference to `reason`
9361 #[inline]
9362 pub fn r#reason(&self) -> &u32 {
9363 &self.r#reason
9364 }
9365 ///Return a mutable reference to `reason`
9366 #[inline]
9367 pub fn mut_reason(&mut self) -> &mut u32 {
9368 &mut self.r#reason
9369 }
9370 ///Set the value of `reason`
9371 #[inline]
9372 pub fn set_reason(&mut self, value: u32) -> &mut Self {
9373 self.r#reason = value.into();
9374 self
9375 }
9376 ///Builder method that sets the value of `reason`. Useful for initializing the message.
9377 #[inline]
9378 pub fn init_reason(mut self, value: u32) -> Self {
9379 self.r#reason = value.into();
9380 self
9381 }
9382}
9383impl ::micropb::MessageDecode for CtrlMsg_Event_StationDisconnectFromESPSoftAP {
9384 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
9385 &mut self,
9386 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
9387 len: usize,
9388 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
9389 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
9390 let before = decoder.bytes_read();
9391 while decoder.bytes_read() - before < len {
9392 let tag = decoder.decode_tag()?;
9393 match tag.field_num() {
9394 0 => return Err(::micropb::DecodeError::ZeroField),
9395 1u32 => {
9396 let mut_ref = &mut self.r#resp;
9397 {
9398 let val = decoder.decode_int32()?;
9399 let val_ref = &val;
9400 if *val_ref != 0 {
9401 *mut_ref = val as _;
9402 }
9403 };
9404 }
9405 2u32 => {
9406 let mut_ref = &mut self.r#mac;
9407 {
9408 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
9409 };
9410 }
9411 3u32 => {
9412 let mut_ref = &mut self.r#aid;
9413 {
9414 let val = decoder.decode_varint32()?;
9415 let val_ref = &val;
9416 if *val_ref != 0 {
9417 *mut_ref = val as _;
9418 }
9419 };
9420 }
9421 4u32 => {
9422 let mut_ref = &mut self.r#is_mesh_child;
9423 {
9424 let val = decoder.decode_bool()?;
9425 let val_ref = &val;
9426 if *val_ref {
9427 *mut_ref = val as _;
9428 }
9429 };
9430 }
9431 5u32 => {
9432 let mut_ref = &mut self.r#reason;
9433 {
9434 let val = decoder.decode_varint32()?;
9435 let val_ref = &val;
9436 if *val_ref != 0 {
9437 *mut_ref = val as _;
9438 }
9439 };
9440 }
9441 _ => {
9442 decoder.skip_wire_value(tag.wire_type())?;
9443 }
9444 }
9445 }
9446 Ok(())
9447 }
9448}
9449impl ::micropb::MessageEncode for CtrlMsg_Event_StationDisconnectFromESPSoftAP {
9450 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
9451 let mut max_size = 0;
9452 if let ::core::option::Option::Some(size) =
9453 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
9454 {
9455 max_size += size;
9456 } else {
9457 break 'msg (::core::option::Option::<usize>::None);
9458 };
9459 if let ::core::option::Option::Some(size) =
9460 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
9461 {
9462 max_size += size;
9463 } else {
9464 break 'msg (::core::option::Option::<usize>::None);
9465 };
9466 if let ::core::option::Option::Some(size) =
9467 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
9468 {
9469 max_size += size;
9470 } else {
9471 break 'msg (::core::option::Option::<usize>::None);
9472 };
9473 if let ::core::option::Option::Some(size) =
9474 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
9475 {
9476 max_size += size;
9477 } else {
9478 break 'msg (::core::option::Option::<usize>::None);
9479 };
9480 if let ::core::option::Option::Some(size) =
9481 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
9482 {
9483 max_size += size;
9484 } else {
9485 break 'msg (::core::option::Option::<usize>::None);
9486 };
9487 ::core::option::Option::Some(max_size)
9488 };
9489 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
9490 &self,
9491 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
9492 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
9493 use ::micropb::{FieldEncode, PbMap};
9494 {
9495 let val_ref = &self.r#resp;
9496 if *val_ref != 0 {
9497 encoder.encode_varint32(8u32)?;
9498 encoder.encode_int32(*val_ref as _)?;
9499 }
9500 }
9501 {
9502 let val_ref = &self.r#mac;
9503 if !val_ref.is_empty() {
9504 encoder.encode_varint32(18u32)?;
9505 encoder.encode_bytes(val_ref)?;
9506 }
9507 }
9508 {
9509 let val_ref = &self.r#aid;
9510 if *val_ref != 0 {
9511 encoder.encode_varint32(24u32)?;
9512 encoder.encode_varint32(*val_ref as _)?;
9513 }
9514 }
9515 {
9516 let val_ref = &self.r#is_mesh_child;
9517 if *val_ref {
9518 encoder.encode_varint32(32u32)?;
9519 encoder.encode_bool(*val_ref)?;
9520 }
9521 }
9522 {
9523 let val_ref = &self.r#reason;
9524 if *val_ref != 0 {
9525 encoder.encode_varint32(40u32)?;
9526 encoder.encode_varint32(*val_ref as _)?;
9527 }
9528 }
9529 Ok(())
9530 }
9531 fn compute_size(&self) -> usize {
9532 use ::micropb::{FieldEncode, PbMap};
9533 let mut size = 0;
9534 {
9535 let val_ref = &self.r#resp;
9536 if *val_ref != 0 {
9537 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
9538 }
9539 }
9540 {
9541 let val_ref = &self.r#mac;
9542 if !val_ref.is_empty() {
9543 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
9544 }
9545 }
9546 {
9547 let val_ref = &self.r#aid;
9548 if *val_ref != 0 {
9549 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
9550 }
9551 }
9552 {
9553 let val_ref = &self.r#is_mesh_child;
9554 if *val_ref {
9555 size += 1usize + 1;
9556 }
9557 }
9558 {
9559 let val_ref = &self.r#reason;
9560 if *val_ref != 0 {
9561 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
9562 }
9563 }
9564 size
9565 }
9566}
9567#[derive(Debug, Default, PartialEq, Clone)]
9568#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9569pub struct CtrlMsg_Event_StationConnectedToESPSoftAP {
9570 pub r#resp: i32,
9571 pub r#mac: ::micropb::heapless::Vec<u8, 32>,
9572 pub r#aid: u32,
9573 pub r#is_mesh_child: bool,
9574}
9575impl CtrlMsg_Event_StationConnectedToESPSoftAP {
9576 ///Return a reference to `resp`
9577 #[inline]
9578 pub fn r#resp(&self) -> &i32 {
9579 &self.r#resp
9580 }
9581 ///Return a mutable reference to `resp`
9582 #[inline]
9583 pub fn mut_resp(&mut self) -> &mut i32 {
9584 &mut self.r#resp
9585 }
9586 ///Set the value of `resp`
9587 #[inline]
9588 pub fn set_resp(&mut self, value: i32) -> &mut Self {
9589 self.r#resp = value.into();
9590 self
9591 }
9592 ///Builder method that sets the value of `resp`. Useful for initializing the message.
9593 #[inline]
9594 pub fn init_resp(mut self, value: i32) -> Self {
9595 self.r#resp = value.into();
9596 self
9597 }
9598 ///Return a reference to `mac`
9599 #[inline]
9600 pub fn r#mac(&self) -> &::micropb::heapless::Vec<u8, 32> {
9601 &self.r#mac
9602 }
9603 ///Return a mutable reference to `mac`
9604 #[inline]
9605 pub fn mut_mac(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9606 &mut self.r#mac
9607 }
9608 ///Set the value of `mac`
9609 #[inline]
9610 pub fn set_mac(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
9611 self.r#mac = value.into();
9612 self
9613 }
9614 ///Builder method that sets the value of `mac`. Useful for initializing the message.
9615 #[inline]
9616 pub fn init_mac(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
9617 self.r#mac = value.into();
9618 self
9619 }
9620 ///Return a reference to `aid`
9621 #[inline]
9622 pub fn r#aid(&self) -> &u32 {
9623 &self.r#aid
9624 }
9625 ///Return a mutable reference to `aid`
9626 #[inline]
9627 pub fn mut_aid(&mut self) -> &mut u32 {
9628 &mut self.r#aid
9629 }
9630 ///Set the value of `aid`
9631 #[inline]
9632 pub fn set_aid(&mut self, value: u32) -> &mut Self {
9633 self.r#aid = value.into();
9634 self
9635 }
9636 ///Builder method that sets the value of `aid`. Useful for initializing the message.
9637 #[inline]
9638 pub fn init_aid(mut self, value: u32) -> Self {
9639 self.r#aid = value.into();
9640 self
9641 }
9642 ///Return a reference to `is_mesh_child`
9643 #[inline]
9644 pub fn r#is_mesh_child(&self) -> &bool {
9645 &self.r#is_mesh_child
9646 }
9647 ///Return a mutable reference to `is_mesh_child`
9648 #[inline]
9649 pub fn mut_is_mesh_child(&mut self) -> &mut bool {
9650 &mut self.r#is_mesh_child
9651 }
9652 ///Set the value of `is_mesh_child`
9653 #[inline]
9654 pub fn set_is_mesh_child(&mut self, value: bool) -> &mut Self {
9655 self.r#is_mesh_child = value.into();
9656 self
9657 }
9658 ///Builder method that sets the value of `is_mesh_child`. Useful for initializing the message.
9659 #[inline]
9660 pub fn init_is_mesh_child(mut self, value: bool) -> Self {
9661 self.r#is_mesh_child = value.into();
9662 self
9663 }
9664}
9665impl ::micropb::MessageDecode for CtrlMsg_Event_StationConnectedToESPSoftAP {
9666 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
9667 &mut self,
9668 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
9669 len: usize,
9670 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
9671 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
9672 let before = decoder.bytes_read();
9673 while decoder.bytes_read() - before < len {
9674 let tag = decoder.decode_tag()?;
9675 match tag.field_num() {
9676 0 => return Err(::micropb::DecodeError::ZeroField),
9677 1u32 => {
9678 let mut_ref = &mut self.r#resp;
9679 {
9680 let val = decoder.decode_int32()?;
9681 let val_ref = &val;
9682 if *val_ref != 0 {
9683 *mut_ref = val as _;
9684 }
9685 };
9686 }
9687 2u32 => {
9688 let mut_ref = &mut self.r#mac;
9689 {
9690 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
9691 };
9692 }
9693 3u32 => {
9694 let mut_ref = &mut self.r#aid;
9695 {
9696 let val = decoder.decode_varint32()?;
9697 let val_ref = &val;
9698 if *val_ref != 0 {
9699 *mut_ref = val as _;
9700 }
9701 };
9702 }
9703 4u32 => {
9704 let mut_ref = &mut self.r#is_mesh_child;
9705 {
9706 let val = decoder.decode_bool()?;
9707 let val_ref = &val;
9708 if *val_ref {
9709 *mut_ref = val as _;
9710 }
9711 };
9712 }
9713 _ => {
9714 decoder.skip_wire_value(tag.wire_type())?;
9715 }
9716 }
9717 }
9718 Ok(())
9719 }
9720}
9721impl ::micropb::MessageEncode for CtrlMsg_Event_StationConnectedToESPSoftAP {
9722 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
9723 let mut max_size = 0;
9724 if let ::core::option::Option::Some(size) =
9725 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
9726 {
9727 max_size += size;
9728 } else {
9729 break 'msg (::core::option::Option::<usize>::None);
9730 };
9731 if let ::core::option::Option::Some(size) =
9732 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
9733 {
9734 max_size += size;
9735 } else {
9736 break 'msg (::core::option::Option::<usize>::None);
9737 };
9738 if let ::core::option::Option::Some(size) =
9739 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
9740 {
9741 max_size += size;
9742 } else {
9743 break 'msg (::core::option::Option::<usize>::None);
9744 };
9745 if let ::core::option::Option::Some(size) =
9746 ::micropb::const_map!(::core::option::Option::Some(1usize), |size| size + 1usize)
9747 {
9748 max_size += size;
9749 } else {
9750 break 'msg (::core::option::Option::<usize>::None);
9751 };
9752 ::core::option::Option::Some(max_size)
9753 };
9754 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
9755 &self,
9756 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
9757 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
9758 use ::micropb::{FieldEncode, PbMap};
9759 {
9760 let val_ref = &self.r#resp;
9761 if *val_ref != 0 {
9762 encoder.encode_varint32(8u32)?;
9763 encoder.encode_int32(*val_ref as _)?;
9764 }
9765 }
9766 {
9767 let val_ref = &self.r#mac;
9768 if !val_ref.is_empty() {
9769 encoder.encode_varint32(18u32)?;
9770 encoder.encode_bytes(val_ref)?;
9771 }
9772 }
9773 {
9774 let val_ref = &self.r#aid;
9775 if *val_ref != 0 {
9776 encoder.encode_varint32(24u32)?;
9777 encoder.encode_varint32(*val_ref as _)?;
9778 }
9779 }
9780 {
9781 let val_ref = &self.r#is_mesh_child;
9782 if *val_ref {
9783 encoder.encode_varint32(32u32)?;
9784 encoder.encode_bool(*val_ref)?;
9785 }
9786 }
9787 Ok(())
9788 }
9789 fn compute_size(&self) -> usize {
9790 use ::micropb::{FieldEncode, PbMap};
9791 let mut size = 0;
9792 {
9793 let val_ref = &self.r#resp;
9794 if *val_ref != 0 {
9795 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
9796 }
9797 }
9798 {
9799 let val_ref = &self.r#mac;
9800 if !val_ref.is_empty() {
9801 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
9802 }
9803 }
9804 {
9805 let val_ref = &self.r#aid;
9806 if *val_ref != 0 {
9807 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
9808 }
9809 }
9810 {
9811 let val_ref = &self.r#is_mesh_child;
9812 if *val_ref {
9813 size += 1usize + 1;
9814 }
9815 }
9816 size
9817 }
9818}
9819#[derive(Debug, Default, PartialEq, Clone)]
9820#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9821pub struct CtrlMsg_Event_SetDhcpDnsStatus {
9822 pub r#iface: i32,
9823 pub r#net_link_up: i32,
9824 pub r#dhcp_up: i32,
9825 pub r#dhcp_ip: ::micropb::heapless::Vec<u8, 32>,
9826 pub r#dhcp_nm: ::micropb::heapless::Vec<u8, 32>,
9827 pub r#dhcp_gw: ::micropb::heapless::Vec<u8, 32>,
9828 pub r#dns_up: i32,
9829 pub r#dns_ip: ::micropb::heapless::Vec<u8, 32>,
9830 pub r#dns_type: i32,
9831 pub r#resp: i32,
9832}
9833impl CtrlMsg_Event_SetDhcpDnsStatus {
9834 ///Return a reference to `iface`
9835 #[inline]
9836 pub fn r#iface(&self) -> &i32 {
9837 &self.r#iface
9838 }
9839 ///Return a mutable reference to `iface`
9840 #[inline]
9841 pub fn mut_iface(&mut self) -> &mut i32 {
9842 &mut self.r#iface
9843 }
9844 ///Set the value of `iface`
9845 #[inline]
9846 pub fn set_iface(&mut self, value: i32) -> &mut Self {
9847 self.r#iface = value.into();
9848 self
9849 }
9850 ///Builder method that sets the value of `iface`. Useful for initializing the message.
9851 #[inline]
9852 pub fn init_iface(mut self, value: i32) -> Self {
9853 self.r#iface = value.into();
9854 self
9855 }
9856 ///Return a reference to `net_link_up`
9857 #[inline]
9858 pub fn r#net_link_up(&self) -> &i32 {
9859 &self.r#net_link_up
9860 }
9861 ///Return a mutable reference to `net_link_up`
9862 #[inline]
9863 pub fn mut_net_link_up(&mut self) -> &mut i32 {
9864 &mut self.r#net_link_up
9865 }
9866 ///Set the value of `net_link_up`
9867 #[inline]
9868 pub fn set_net_link_up(&mut self, value: i32) -> &mut Self {
9869 self.r#net_link_up = value.into();
9870 self
9871 }
9872 ///Builder method that sets the value of `net_link_up`. Useful for initializing the message.
9873 #[inline]
9874 pub fn init_net_link_up(mut self, value: i32) -> Self {
9875 self.r#net_link_up = value.into();
9876 self
9877 }
9878 ///Return a reference to `dhcp_up`
9879 #[inline]
9880 pub fn r#dhcp_up(&self) -> &i32 {
9881 &self.r#dhcp_up
9882 }
9883 ///Return a mutable reference to `dhcp_up`
9884 #[inline]
9885 pub fn mut_dhcp_up(&mut self) -> &mut i32 {
9886 &mut self.r#dhcp_up
9887 }
9888 ///Set the value of `dhcp_up`
9889 #[inline]
9890 pub fn set_dhcp_up(&mut self, value: i32) -> &mut Self {
9891 self.r#dhcp_up = value.into();
9892 self
9893 }
9894 ///Builder method that sets the value of `dhcp_up`. Useful for initializing the message.
9895 #[inline]
9896 pub fn init_dhcp_up(mut self, value: i32) -> Self {
9897 self.r#dhcp_up = value.into();
9898 self
9899 }
9900 ///Return a reference to `dhcp_ip`
9901 #[inline]
9902 pub fn r#dhcp_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
9903 &self.r#dhcp_ip
9904 }
9905 ///Return a mutable reference to `dhcp_ip`
9906 #[inline]
9907 pub fn mut_dhcp_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9908 &mut self.r#dhcp_ip
9909 }
9910 ///Set the value of `dhcp_ip`
9911 #[inline]
9912 pub fn set_dhcp_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
9913 self.r#dhcp_ip = value.into();
9914 self
9915 }
9916 ///Builder method that sets the value of `dhcp_ip`. Useful for initializing the message.
9917 #[inline]
9918 pub fn init_dhcp_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
9919 self.r#dhcp_ip = value.into();
9920 self
9921 }
9922 ///Return a reference to `dhcp_nm`
9923 #[inline]
9924 pub fn r#dhcp_nm(&self) -> &::micropb::heapless::Vec<u8, 32> {
9925 &self.r#dhcp_nm
9926 }
9927 ///Return a mutable reference to `dhcp_nm`
9928 #[inline]
9929 pub fn mut_dhcp_nm(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9930 &mut self.r#dhcp_nm
9931 }
9932 ///Set the value of `dhcp_nm`
9933 #[inline]
9934 pub fn set_dhcp_nm(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
9935 self.r#dhcp_nm = value.into();
9936 self
9937 }
9938 ///Builder method that sets the value of `dhcp_nm`. Useful for initializing the message.
9939 #[inline]
9940 pub fn init_dhcp_nm(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
9941 self.r#dhcp_nm = value.into();
9942 self
9943 }
9944 ///Return a reference to `dhcp_gw`
9945 #[inline]
9946 pub fn r#dhcp_gw(&self) -> &::micropb::heapless::Vec<u8, 32> {
9947 &self.r#dhcp_gw
9948 }
9949 ///Return a mutable reference to `dhcp_gw`
9950 #[inline]
9951 pub fn mut_dhcp_gw(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9952 &mut self.r#dhcp_gw
9953 }
9954 ///Set the value of `dhcp_gw`
9955 #[inline]
9956 pub fn set_dhcp_gw(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
9957 self.r#dhcp_gw = value.into();
9958 self
9959 }
9960 ///Builder method that sets the value of `dhcp_gw`. Useful for initializing the message.
9961 #[inline]
9962 pub fn init_dhcp_gw(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
9963 self.r#dhcp_gw = value.into();
9964 self
9965 }
9966 ///Return a reference to `dns_up`
9967 #[inline]
9968 pub fn r#dns_up(&self) -> &i32 {
9969 &self.r#dns_up
9970 }
9971 ///Return a mutable reference to `dns_up`
9972 #[inline]
9973 pub fn mut_dns_up(&mut self) -> &mut i32 {
9974 &mut self.r#dns_up
9975 }
9976 ///Set the value of `dns_up`
9977 #[inline]
9978 pub fn set_dns_up(&mut self, value: i32) -> &mut Self {
9979 self.r#dns_up = value.into();
9980 self
9981 }
9982 ///Builder method that sets the value of `dns_up`. Useful for initializing the message.
9983 #[inline]
9984 pub fn init_dns_up(mut self, value: i32) -> Self {
9985 self.r#dns_up = value.into();
9986 self
9987 }
9988 ///Return a reference to `dns_ip`
9989 #[inline]
9990 pub fn r#dns_ip(&self) -> &::micropb::heapless::Vec<u8, 32> {
9991 &self.r#dns_ip
9992 }
9993 ///Return a mutable reference to `dns_ip`
9994 #[inline]
9995 pub fn mut_dns_ip(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
9996 &mut self.r#dns_ip
9997 }
9998 ///Set the value of `dns_ip`
9999 #[inline]
10000 pub fn set_dns_ip(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
10001 self.r#dns_ip = value.into();
10002 self
10003 }
10004 ///Builder method that sets the value of `dns_ip`. Useful for initializing the message.
10005 #[inline]
10006 pub fn init_dns_ip(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
10007 self.r#dns_ip = value.into();
10008 self
10009 }
10010 ///Return a reference to `dns_type`
10011 #[inline]
10012 pub fn r#dns_type(&self) -> &i32 {
10013 &self.r#dns_type
10014 }
10015 ///Return a mutable reference to `dns_type`
10016 #[inline]
10017 pub fn mut_dns_type(&mut self) -> &mut i32 {
10018 &mut self.r#dns_type
10019 }
10020 ///Set the value of `dns_type`
10021 #[inline]
10022 pub fn set_dns_type(&mut self, value: i32) -> &mut Self {
10023 self.r#dns_type = value.into();
10024 self
10025 }
10026 ///Builder method that sets the value of `dns_type`. Useful for initializing the message.
10027 #[inline]
10028 pub fn init_dns_type(mut self, value: i32) -> Self {
10029 self.r#dns_type = value.into();
10030 self
10031 }
10032 ///Return a reference to `resp`
10033 #[inline]
10034 pub fn r#resp(&self) -> &i32 {
10035 &self.r#resp
10036 }
10037 ///Return a mutable reference to `resp`
10038 #[inline]
10039 pub fn mut_resp(&mut self) -> &mut i32 {
10040 &mut self.r#resp
10041 }
10042 ///Set the value of `resp`
10043 #[inline]
10044 pub fn set_resp(&mut self, value: i32) -> &mut Self {
10045 self.r#resp = value.into();
10046 self
10047 }
10048 ///Builder method that sets the value of `resp`. Useful for initializing the message.
10049 #[inline]
10050 pub fn init_resp(mut self, value: i32) -> Self {
10051 self.r#resp = value.into();
10052 self
10053 }
10054}
10055impl ::micropb::MessageDecode for CtrlMsg_Event_SetDhcpDnsStatus {
10056 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
10057 &mut self,
10058 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
10059 len: usize,
10060 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
10061 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
10062 let before = decoder.bytes_read();
10063 while decoder.bytes_read() - before < len {
10064 let tag = decoder.decode_tag()?;
10065 match tag.field_num() {
10066 0 => return Err(::micropb::DecodeError::ZeroField),
10067 1u32 => {
10068 let mut_ref = &mut self.r#iface;
10069 {
10070 let val = decoder.decode_int32()?;
10071 let val_ref = &val;
10072 if *val_ref != 0 {
10073 *mut_ref = val as _;
10074 }
10075 };
10076 }
10077 2u32 => {
10078 let mut_ref = &mut self.r#net_link_up;
10079 {
10080 let val = decoder.decode_int32()?;
10081 let val_ref = &val;
10082 if *val_ref != 0 {
10083 *mut_ref = val as _;
10084 }
10085 };
10086 }
10087 3u32 => {
10088 let mut_ref = &mut self.r#dhcp_up;
10089 {
10090 let val = decoder.decode_int32()?;
10091 let val_ref = &val;
10092 if *val_ref != 0 {
10093 *mut_ref = val as _;
10094 }
10095 };
10096 }
10097 4u32 => {
10098 let mut_ref = &mut self.r#dhcp_ip;
10099 {
10100 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10101 };
10102 }
10103 5u32 => {
10104 let mut_ref = &mut self.r#dhcp_nm;
10105 {
10106 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10107 };
10108 }
10109 6u32 => {
10110 let mut_ref = &mut self.r#dhcp_gw;
10111 {
10112 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10113 };
10114 }
10115 7u32 => {
10116 let mut_ref = &mut self.r#dns_up;
10117 {
10118 let val = decoder.decode_int32()?;
10119 let val_ref = &val;
10120 if *val_ref != 0 {
10121 *mut_ref = val as _;
10122 }
10123 };
10124 }
10125 8u32 => {
10126 let mut_ref = &mut self.r#dns_ip;
10127 {
10128 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10129 };
10130 }
10131 9u32 => {
10132 let mut_ref = &mut self.r#dns_type;
10133 {
10134 let val = decoder.decode_int32()?;
10135 let val_ref = &val;
10136 if *val_ref != 0 {
10137 *mut_ref = val as _;
10138 }
10139 };
10140 }
10141 10u32 => {
10142 let mut_ref = &mut self.r#resp;
10143 {
10144 let val = decoder.decode_int32()?;
10145 let val_ref = &val;
10146 if *val_ref != 0 {
10147 *mut_ref = val as _;
10148 }
10149 };
10150 }
10151 _ => {
10152 decoder.skip_wire_value(tag.wire_type())?;
10153 }
10154 }
10155 }
10156 Ok(())
10157 }
10158}
10159impl ::micropb::MessageEncode for CtrlMsg_Event_SetDhcpDnsStatus {
10160 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
10161 let mut max_size = 0;
10162 if let ::core::option::Option::Some(size) =
10163 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10164 {
10165 max_size += size;
10166 } else {
10167 break 'msg (::core::option::Option::<usize>::None);
10168 };
10169 if let ::core::option::Option::Some(size) =
10170 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10171 {
10172 max_size += size;
10173 } else {
10174 break 'msg (::core::option::Option::<usize>::None);
10175 };
10176 if let ::core::option::Option::Some(size) =
10177 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10178 {
10179 max_size += size;
10180 } else {
10181 break 'msg (::core::option::Option::<usize>::None);
10182 };
10183 if let ::core::option::Option::Some(size) =
10184 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10185 {
10186 max_size += size;
10187 } else {
10188 break 'msg (::core::option::Option::<usize>::None);
10189 };
10190 if let ::core::option::Option::Some(size) =
10191 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10192 {
10193 max_size += size;
10194 } else {
10195 break 'msg (::core::option::Option::<usize>::None);
10196 };
10197 if let ::core::option::Option::Some(size) =
10198 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10199 {
10200 max_size += size;
10201 } else {
10202 break 'msg (::core::option::Option::<usize>::None);
10203 };
10204 if let ::core::option::Option::Some(size) =
10205 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10206 {
10207 max_size += size;
10208 } else {
10209 break 'msg (::core::option::Option::<usize>::None);
10210 };
10211 if let ::core::option::Option::Some(size) =
10212 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10213 {
10214 max_size += size;
10215 } else {
10216 break 'msg (::core::option::Option::<usize>::None);
10217 };
10218 if let ::core::option::Option::Some(size) =
10219 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10220 {
10221 max_size += size;
10222 } else {
10223 break 'msg (::core::option::Option::<usize>::None);
10224 };
10225 if let ::core::option::Option::Some(size) =
10226 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10227 {
10228 max_size += size;
10229 } else {
10230 break 'msg (::core::option::Option::<usize>::None);
10231 };
10232 ::core::option::Option::Some(max_size)
10233 };
10234 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
10235 &self,
10236 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
10237 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
10238 use ::micropb::{FieldEncode, PbMap};
10239 {
10240 let val_ref = &self.r#iface;
10241 if *val_ref != 0 {
10242 encoder.encode_varint32(8u32)?;
10243 encoder.encode_int32(*val_ref as _)?;
10244 }
10245 }
10246 {
10247 let val_ref = &self.r#net_link_up;
10248 if *val_ref != 0 {
10249 encoder.encode_varint32(16u32)?;
10250 encoder.encode_int32(*val_ref as _)?;
10251 }
10252 }
10253 {
10254 let val_ref = &self.r#dhcp_up;
10255 if *val_ref != 0 {
10256 encoder.encode_varint32(24u32)?;
10257 encoder.encode_int32(*val_ref as _)?;
10258 }
10259 }
10260 {
10261 let val_ref = &self.r#dhcp_ip;
10262 if !val_ref.is_empty() {
10263 encoder.encode_varint32(34u32)?;
10264 encoder.encode_bytes(val_ref)?;
10265 }
10266 }
10267 {
10268 let val_ref = &self.r#dhcp_nm;
10269 if !val_ref.is_empty() {
10270 encoder.encode_varint32(42u32)?;
10271 encoder.encode_bytes(val_ref)?;
10272 }
10273 }
10274 {
10275 let val_ref = &self.r#dhcp_gw;
10276 if !val_ref.is_empty() {
10277 encoder.encode_varint32(50u32)?;
10278 encoder.encode_bytes(val_ref)?;
10279 }
10280 }
10281 {
10282 let val_ref = &self.r#dns_up;
10283 if *val_ref != 0 {
10284 encoder.encode_varint32(56u32)?;
10285 encoder.encode_int32(*val_ref as _)?;
10286 }
10287 }
10288 {
10289 let val_ref = &self.r#dns_ip;
10290 if !val_ref.is_empty() {
10291 encoder.encode_varint32(66u32)?;
10292 encoder.encode_bytes(val_ref)?;
10293 }
10294 }
10295 {
10296 let val_ref = &self.r#dns_type;
10297 if *val_ref != 0 {
10298 encoder.encode_varint32(72u32)?;
10299 encoder.encode_int32(*val_ref as _)?;
10300 }
10301 }
10302 {
10303 let val_ref = &self.r#resp;
10304 if *val_ref != 0 {
10305 encoder.encode_varint32(80u32)?;
10306 encoder.encode_int32(*val_ref as _)?;
10307 }
10308 }
10309 Ok(())
10310 }
10311 fn compute_size(&self) -> usize {
10312 use ::micropb::{FieldEncode, PbMap};
10313 let mut size = 0;
10314 {
10315 let val_ref = &self.r#iface;
10316 if *val_ref != 0 {
10317 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10318 }
10319 }
10320 {
10321 let val_ref = &self.r#net_link_up;
10322 if *val_ref != 0 {
10323 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10324 }
10325 }
10326 {
10327 let val_ref = &self.r#dhcp_up;
10328 if *val_ref != 0 {
10329 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10330 }
10331 }
10332 {
10333 let val_ref = &self.r#dhcp_ip;
10334 if !val_ref.is_empty() {
10335 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10336 }
10337 }
10338 {
10339 let val_ref = &self.r#dhcp_nm;
10340 if !val_ref.is_empty() {
10341 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10342 }
10343 }
10344 {
10345 let val_ref = &self.r#dhcp_gw;
10346 if !val_ref.is_empty() {
10347 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10348 }
10349 }
10350 {
10351 let val_ref = &self.r#dns_up;
10352 if *val_ref != 0 {
10353 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10354 }
10355 }
10356 {
10357 let val_ref = &self.r#dns_ip;
10358 if !val_ref.is_empty() {
10359 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10360 }
10361 }
10362 {
10363 let val_ref = &self.r#dns_type;
10364 if *val_ref != 0 {
10365 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10366 }
10367 }
10368 {
10369 let val_ref = &self.r#resp;
10370 if *val_ref != 0 {
10371 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10372 }
10373 }
10374 size
10375 }
10376}
10377#[derive(Debug, Default, PartialEq, Clone)]
10378#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10379pub struct CtrlMsg_Req_CustomRpcUnserialisedMsg {
10380 pub r#custom_msg_id: u32,
10381 pub r#data: ::micropb::heapless::Vec<u8, 32>,
10382}
10383impl CtrlMsg_Req_CustomRpcUnserialisedMsg {
10384 ///Return a reference to `custom_msg_id`
10385 #[inline]
10386 pub fn r#custom_msg_id(&self) -> &u32 {
10387 &self.r#custom_msg_id
10388 }
10389 ///Return a mutable reference to `custom_msg_id`
10390 #[inline]
10391 pub fn mut_custom_msg_id(&mut self) -> &mut u32 {
10392 &mut self.r#custom_msg_id
10393 }
10394 ///Set the value of `custom_msg_id`
10395 #[inline]
10396 pub fn set_custom_msg_id(&mut self, value: u32) -> &mut Self {
10397 self.r#custom_msg_id = value.into();
10398 self
10399 }
10400 ///Builder method that sets the value of `custom_msg_id`. Useful for initializing the message.
10401 #[inline]
10402 pub fn init_custom_msg_id(mut self, value: u32) -> Self {
10403 self.r#custom_msg_id = value.into();
10404 self
10405 }
10406 ///Return a reference to `data`
10407 #[inline]
10408 pub fn r#data(&self) -> &::micropb::heapless::Vec<u8, 32> {
10409 &self.r#data
10410 }
10411 ///Return a mutable reference to `data`
10412 #[inline]
10413 pub fn mut_data(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
10414 &mut self.r#data
10415 }
10416 ///Set the value of `data`
10417 #[inline]
10418 pub fn set_data(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
10419 self.r#data = value.into();
10420 self
10421 }
10422 ///Builder method that sets the value of `data`. Useful for initializing the message.
10423 #[inline]
10424 pub fn init_data(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
10425 self.r#data = value.into();
10426 self
10427 }
10428}
10429impl ::micropb::MessageDecode for CtrlMsg_Req_CustomRpcUnserialisedMsg {
10430 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
10431 &mut self,
10432 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
10433 len: usize,
10434 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
10435 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
10436 let before = decoder.bytes_read();
10437 while decoder.bytes_read() - before < len {
10438 let tag = decoder.decode_tag()?;
10439 match tag.field_num() {
10440 0 => return Err(::micropb::DecodeError::ZeroField),
10441 1u32 => {
10442 let mut_ref = &mut self.r#custom_msg_id;
10443 {
10444 let val = decoder.decode_varint32()?;
10445 let val_ref = &val;
10446 if *val_ref != 0 {
10447 *mut_ref = val as _;
10448 }
10449 };
10450 }
10451 2u32 => {
10452 let mut_ref = &mut self.r#data;
10453 {
10454 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10455 };
10456 }
10457 _ => {
10458 decoder.skip_wire_value(tag.wire_type())?;
10459 }
10460 }
10461 }
10462 Ok(())
10463 }
10464}
10465impl ::micropb::MessageEncode for CtrlMsg_Req_CustomRpcUnserialisedMsg {
10466 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
10467 let mut max_size = 0;
10468 if let ::core::option::Option::Some(size) =
10469 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
10470 {
10471 max_size += size;
10472 } else {
10473 break 'msg (::core::option::Option::<usize>::None);
10474 };
10475 if let ::core::option::Option::Some(size) =
10476 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10477 {
10478 max_size += size;
10479 } else {
10480 break 'msg (::core::option::Option::<usize>::None);
10481 };
10482 ::core::option::Option::Some(max_size)
10483 };
10484 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
10485 &self,
10486 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
10487 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
10488 use ::micropb::{FieldEncode, PbMap};
10489 {
10490 let val_ref = &self.r#custom_msg_id;
10491 if *val_ref != 0 {
10492 encoder.encode_varint32(8u32)?;
10493 encoder.encode_varint32(*val_ref as _)?;
10494 }
10495 }
10496 {
10497 let val_ref = &self.r#data;
10498 if !val_ref.is_empty() {
10499 encoder.encode_varint32(18u32)?;
10500 encoder.encode_bytes(val_ref)?;
10501 }
10502 }
10503 Ok(())
10504 }
10505 fn compute_size(&self) -> usize {
10506 use ::micropb::{FieldEncode, PbMap};
10507 let mut size = 0;
10508 {
10509 let val_ref = &self.r#custom_msg_id;
10510 if *val_ref != 0 {
10511 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
10512 }
10513 }
10514 {
10515 let val_ref = &self.r#data;
10516 if !val_ref.is_empty() {
10517 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10518 }
10519 }
10520 size
10521 }
10522}
10523#[derive(Debug, Default, PartialEq, Clone)]
10524#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10525pub struct CtrlMsg_Resp_CustomRpcUnserialisedMsg {
10526 pub r#resp: i32,
10527 pub r#custom_msg_id: u32,
10528 pub r#data: ::micropb::heapless::Vec<u8, 32>,
10529}
10530impl CtrlMsg_Resp_CustomRpcUnserialisedMsg {
10531 ///Return a reference to `resp`
10532 #[inline]
10533 pub fn r#resp(&self) -> &i32 {
10534 &self.r#resp
10535 }
10536 ///Return a mutable reference to `resp`
10537 #[inline]
10538 pub fn mut_resp(&mut self) -> &mut i32 {
10539 &mut self.r#resp
10540 }
10541 ///Set the value of `resp`
10542 #[inline]
10543 pub fn set_resp(&mut self, value: i32) -> &mut Self {
10544 self.r#resp = value.into();
10545 self
10546 }
10547 ///Builder method that sets the value of `resp`. Useful for initializing the message.
10548 #[inline]
10549 pub fn init_resp(mut self, value: i32) -> Self {
10550 self.r#resp = value.into();
10551 self
10552 }
10553 ///Return a reference to `custom_msg_id`
10554 #[inline]
10555 pub fn r#custom_msg_id(&self) -> &u32 {
10556 &self.r#custom_msg_id
10557 }
10558 ///Return a mutable reference to `custom_msg_id`
10559 #[inline]
10560 pub fn mut_custom_msg_id(&mut self) -> &mut u32 {
10561 &mut self.r#custom_msg_id
10562 }
10563 ///Set the value of `custom_msg_id`
10564 #[inline]
10565 pub fn set_custom_msg_id(&mut self, value: u32) -> &mut Self {
10566 self.r#custom_msg_id = value.into();
10567 self
10568 }
10569 ///Builder method that sets the value of `custom_msg_id`. Useful for initializing the message.
10570 #[inline]
10571 pub fn init_custom_msg_id(mut self, value: u32) -> Self {
10572 self.r#custom_msg_id = value.into();
10573 self
10574 }
10575 ///Return a reference to `data`
10576 #[inline]
10577 pub fn r#data(&self) -> &::micropb::heapless::Vec<u8, 32> {
10578 &self.r#data
10579 }
10580 ///Return a mutable reference to `data`
10581 #[inline]
10582 pub fn mut_data(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
10583 &mut self.r#data
10584 }
10585 ///Set the value of `data`
10586 #[inline]
10587 pub fn set_data(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
10588 self.r#data = value.into();
10589 self
10590 }
10591 ///Builder method that sets the value of `data`. Useful for initializing the message.
10592 #[inline]
10593 pub fn init_data(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
10594 self.r#data = value.into();
10595 self
10596 }
10597}
10598impl ::micropb::MessageDecode for CtrlMsg_Resp_CustomRpcUnserialisedMsg {
10599 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
10600 &mut self,
10601 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
10602 len: usize,
10603 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
10604 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
10605 let before = decoder.bytes_read();
10606 while decoder.bytes_read() - before < len {
10607 let tag = decoder.decode_tag()?;
10608 match tag.field_num() {
10609 0 => return Err(::micropb::DecodeError::ZeroField),
10610 1u32 => {
10611 let mut_ref = &mut self.r#resp;
10612 {
10613 let val = decoder.decode_int32()?;
10614 let val_ref = &val;
10615 if *val_ref != 0 {
10616 *mut_ref = val as _;
10617 }
10618 };
10619 }
10620 2u32 => {
10621 let mut_ref = &mut self.r#custom_msg_id;
10622 {
10623 let val = decoder.decode_varint32()?;
10624 let val_ref = &val;
10625 if *val_ref != 0 {
10626 *mut_ref = val as _;
10627 }
10628 };
10629 }
10630 3u32 => {
10631 let mut_ref = &mut self.r#data;
10632 {
10633 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10634 };
10635 }
10636 _ => {
10637 decoder.skip_wire_value(tag.wire_type())?;
10638 }
10639 }
10640 }
10641 Ok(())
10642 }
10643}
10644impl ::micropb::MessageEncode for CtrlMsg_Resp_CustomRpcUnserialisedMsg {
10645 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
10646 let mut max_size = 0;
10647 if let ::core::option::Option::Some(size) =
10648 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10649 {
10650 max_size += size;
10651 } else {
10652 break 'msg (::core::option::Option::<usize>::None);
10653 };
10654 if let ::core::option::Option::Some(size) =
10655 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
10656 {
10657 max_size += size;
10658 } else {
10659 break 'msg (::core::option::Option::<usize>::None);
10660 };
10661 if let ::core::option::Option::Some(size) =
10662 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10663 {
10664 max_size += size;
10665 } else {
10666 break 'msg (::core::option::Option::<usize>::None);
10667 };
10668 ::core::option::Option::Some(max_size)
10669 };
10670 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
10671 &self,
10672 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
10673 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
10674 use ::micropb::{FieldEncode, PbMap};
10675 {
10676 let val_ref = &self.r#resp;
10677 if *val_ref != 0 {
10678 encoder.encode_varint32(8u32)?;
10679 encoder.encode_int32(*val_ref as _)?;
10680 }
10681 }
10682 {
10683 let val_ref = &self.r#custom_msg_id;
10684 if *val_ref != 0 {
10685 encoder.encode_varint32(16u32)?;
10686 encoder.encode_varint32(*val_ref as _)?;
10687 }
10688 }
10689 {
10690 let val_ref = &self.r#data;
10691 if !val_ref.is_empty() {
10692 encoder.encode_varint32(26u32)?;
10693 encoder.encode_bytes(val_ref)?;
10694 }
10695 }
10696 Ok(())
10697 }
10698 fn compute_size(&self) -> usize {
10699 use ::micropb::{FieldEncode, PbMap};
10700 let mut size = 0;
10701 {
10702 let val_ref = &self.r#resp;
10703 if *val_ref != 0 {
10704 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10705 }
10706 }
10707 {
10708 let val_ref = &self.r#custom_msg_id;
10709 if *val_ref != 0 {
10710 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
10711 }
10712 }
10713 {
10714 let val_ref = &self.r#data;
10715 if !val_ref.is_empty() {
10716 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10717 }
10718 }
10719 size
10720 }
10721}
10722#[derive(Debug, Default, PartialEq, Clone)]
10723#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10724pub struct CtrlMsg_Event_CustomRpcUnserialisedMsg {
10725 pub r#resp: i32,
10726 pub r#custom_evt_id: u32,
10727 pub r#data: ::micropb::heapless::Vec<u8, 32>,
10728}
10729impl CtrlMsg_Event_CustomRpcUnserialisedMsg {
10730 ///Return a reference to `resp`
10731 #[inline]
10732 pub fn r#resp(&self) -> &i32 {
10733 &self.r#resp
10734 }
10735 ///Return a mutable reference to `resp`
10736 #[inline]
10737 pub fn mut_resp(&mut self) -> &mut i32 {
10738 &mut self.r#resp
10739 }
10740 ///Set the value of `resp`
10741 #[inline]
10742 pub fn set_resp(&mut self, value: i32) -> &mut Self {
10743 self.r#resp = value.into();
10744 self
10745 }
10746 ///Builder method that sets the value of `resp`. Useful for initializing the message.
10747 #[inline]
10748 pub fn init_resp(mut self, value: i32) -> Self {
10749 self.r#resp = value.into();
10750 self
10751 }
10752 ///Return a reference to `custom_evt_id`
10753 #[inline]
10754 pub fn r#custom_evt_id(&self) -> &u32 {
10755 &self.r#custom_evt_id
10756 }
10757 ///Return a mutable reference to `custom_evt_id`
10758 #[inline]
10759 pub fn mut_custom_evt_id(&mut self) -> &mut u32 {
10760 &mut self.r#custom_evt_id
10761 }
10762 ///Set the value of `custom_evt_id`
10763 #[inline]
10764 pub fn set_custom_evt_id(&mut self, value: u32) -> &mut Self {
10765 self.r#custom_evt_id = value.into();
10766 self
10767 }
10768 ///Builder method that sets the value of `custom_evt_id`. Useful for initializing the message.
10769 #[inline]
10770 pub fn init_custom_evt_id(mut self, value: u32) -> Self {
10771 self.r#custom_evt_id = value.into();
10772 self
10773 }
10774 ///Return a reference to `data`
10775 #[inline]
10776 pub fn r#data(&self) -> &::micropb::heapless::Vec<u8, 32> {
10777 &self.r#data
10778 }
10779 ///Return a mutable reference to `data`
10780 #[inline]
10781 pub fn mut_data(&mut self) -> &mut ::micropb::heapless::Vec<u8, 32> {
10782 &mut self.r#data
10783 }
10784 ///Set the value of `data`
10785 #[inline]
10786 pub fn set_data(&mut self, value: ::micropb::heapless::Vec<u8, 32>) -> &mut Self {
10787 self.r#data = value.into();
10788 self
10789 }
10790 ///Builder method that sets the value of `data`. Useful for initializing the message.
10791 #[inline]
10792 pub fn init_data(mut self, value: ::micropb::heapless::Vec<u8, 32>) -> Self {
10793 self.r#data = value.into();
10794 self
10795 }
10796}
10797impl ::micropb::MessageDecode for CtrlMsg_Event_CustomRpcUnserialisedMsg {
10798 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
10799 &mut self,
10800 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
10801 len: usize,
10802 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
10803 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
10804 let before = decoder.bytes_read();
10805 while decoder.bytes_read() - before < len {
10806 let tag = decoder.decode_tag()?;
10807 match tag.field_num() {
10808 0 => return Err(::micropb::DecodeError::ZeroField),
10809 1u32 => {
10810 let mut_ref = &mut self.r#resp;
10811 {
10812 let val = decoder.decode_int32()?;
10813 let val_ref = &val;
10814 if *val_ref != 0 {
10815 *mut_ref = val as _;
10816 }
10817 };
10818 }
10819 2u32 => {
10820 let mut_ref = &mut self.r#custom_evt_id;
10821 {
10822 let val = decoder.decode_varint32()?;
10823 let val_ref = &val;
10824 if *val_ref != 0 {
10825 *mut_ref = val as _;
10826 }
10827 };
10828 }
10829 3u32 => {
10830 let mut_ref = &mut self.r#data;
10831 {
10832 decoder.decode_bytes(mut_ref, ::micropb::Presence::Implicit)?;
10833 };
10834 }
10835 _ => {
10836 decoder.skip_wire_value(tag.wire_type())?;
10837 }
10838 }
10839 }
10840 Ok(())
10841 }
10842}
10843impl ::micropb::MessageEncode for CtrlMsg_Event_CustomRpcUnserialisedMsg {
10844 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
10845 let mut max_size = 0;
10846 if let ::core::option::Option::Some(size) =
10847 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
10848 {
10849 max_size += size;
10850 } else {
10851 break 'msg (::core::option::Option::<usize>::None);
10852 };
10853 if let ::core::option::Option::Some(size) =
10854 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
10855 {
10856 max_size += size;
10857 } else {
10858 break 'msg (::core::option::Option::<usize>::None);
10859 };
10860 if let ::core::option::Option::Some(size) =
10861 ::micropb::const_map!(::core::option::Option::Some(33usize), |size| size + 1usize)
10862 {
10863 max_size += size;
10864 } else {
10865 break 'msg (::core::option::Option::<usize>::None);
10866 };
10867 ::core::option::Option::Some(max_size)
10868 };
10869 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
10870 &self,
10871 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
10872 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
10873 use ::micropb::{FieldEncode, PbMap};
10874 {
10875 let val_ref = &self.r#resp;
10876 if *val_ref != 0 {
10877 encoder.encode_varint32(8u32)?;
10878 encoder.encode_int32(*val_ref as _)?;
10879 }
10880 }
10881 {
10882 let val_ref = &self.r#custom_evt_id;
10883 if *val_ref != 0 {
10884 encoder.encode_varint32(16u32)?;
10885 encoder.encode_varint32(*val_ref as _)?;
10886 }
10887 }
10888 {
10889 let val_ref = &self.r#data;
10890 if !val_ref.is_empty() {
10891 encoder.encode_varint32(26u32)?;
10892 encoder.encode_bytes(val_ref)?;
10893 }
10894 }
10895 Ok(())
10896 }
10897 fn compute_size(&self) -> usize {
10898 use ::micropb::{FieldEncode, PbMap};
10899 let mut size = 0;
10900 {
10901 let val_ref = &self.r#resp;
10902 if *val_ref != 0 {
10903 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
10904 }
10905 }
10906 {
10907 let val_ref = &self.r#custom_evt_id;
10908 if *val_ref != 0 {
10909 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
10910 }
10911 }
10912 {
10913 let val_ref = &self.r#data;
10914 if !val_ref.is_empty() {
10915 size += 1usize + ::micropb::size::sizeof_len_record(val_ref.len());
10916 }
10917 }
10918 size
10919 }
10920}
10921pub mod CtrlMsg_ {
10922 #[derive(Debug, PartialEq, Clone)]
10923 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
10924 pub enum Payload {
10925 ReqGetMacAddress(super::CtrlMsg_Req_GetMacAddress),
10926 ReqSetMacAddress(super::CtrlMsg_Req_SetMacAddress),
10927 ReqGetWifiMode(super::CtrlMsg_Req_GetMode),
10928 ReqSetWifiMode(super::CtrlMsg_Req_SetMode),
10929 ReqScanApList(super::CtrlMsg_Req_ScanResult),
10930 ReqGetApConfig(super::CtrlMsg_Req_GetAPConfig),
10931 ReqConnectAp(super::CtrlMsg_Req_ConnectAP),
10932 ReqDisconnectAp(super::CtrlMsg_Req_GetStatus),
10933 ReqGetSoftapConfig(super::CtrlMsg_Req_GetSoftAPConfig),
10934 ReqSetSoftapVendorSpecificIe(super::CtrlMsg_Req_SetSoftAPVendorSpecificIE),
10935 ReqStartSoftap(super::CtrlMsg_Req_StartSoftAP),
10936 ReqSoftapConnectedStasList(super::CtrlMsg_Req_SoftAPConnectedSTA),
10937 ReqStopSoftap(super::CtrlMsg_Req_GetStatus),
10938 ReqSetPowerSaveMode(super::CtrlMsg_Req_SetMode),
10939 ReqGetPowerSaveMode(super::CtrlMsg_Req_GetMode),
10940 ReqOtaBegin(super::CtrlMsg_Req_OTABegin),
10941 ReqOtaWrite(super::CtrlMsg_Req_OTAWrite),
10942 ReqOtaEnd(super::CtrlMsg_Req_OTAEnd),
10943 ReqSetWifiMaxTxPower(super::CtrlMsg_Req_SetWifiMaxTxPower),
10944 ReqGetWifiCurrTxPower(super::CtrlMsg_Req_GetWifiCurrTxPower),
10945 ReqConfigHeartbeat(super::CtrlMsg_Req_ConfigHeartbeat),
10946 ReqEnableDisableFeat(super::CtrlMsg_Req_EnableDisable),
10947 ReqGetFwVersion(super::CtrlMsg_Req_GetFwVersion),
10948 ReqSetCountryCode(super::CtrlMsg_Req_SetCountryCode),
10949 ReqGetCountryCode(super::CtrlMsg_Req_GetCountryCode),
10950 ReqSetDhcpDnsStatus(super::CtrlMsg_Req_SetDhcpDnsStatus),
10951 ReqGetDhcpDnsStatus(super::CtrlMsg_Req_GetDhcpDnsStatus),
10952 ReqCustomRpcUnserialisedMsg(super::CtrlMsg_Req_CustomRpcUnserialisedMsg),
10953 RespGetMacAddress(super::CtrlMsg_Resp_GetMacAddress),
10954 RespSetMacAddress(super::CtrlMsg_Resp_SetMacAddress),
10955 RespGetWifiMode(super::CtrlMsg_Resp_GetMode),
10956 RespSetWifiMode(super::CtrlMsg_Resp_SetMode),
10957 RespScanApList(super::CtrlMsg_Resp_ScanResult),
10958 RespGetApConfig(super::CtrlMsg_Resp_GetAPConfig),
10959 RespConnectAp(super::CtrlMsg_Resp_ConnectAP),
10960 RespDisconnectAp(super::CtrlMsg_Resp_GetStatus),
10961 RespGetSoftapConfig(super::CtrlMsg_Resp_GetSoftAPConfig),
10962 RespSetSoftapVendorSpecificIe(super::CtrlMsg_Resp_SetSoftAPVendorSpecificIE),
10963 RespStartSoftap(super::CtrlMsg_Resp_StartSoftAP),
10964 RespSoftapConnectedStasList(super::CtrlMsg_Resp_SoftAPConnectedSTA),
10965 RespStopSoftap(super::CtrlMsg_Resp_GetStatus),
10966 RespSetPowerSaveMode(super::CtrlMsg_Resp_SetMode),
10967 RespGetPowerSaveMode(super::CtrlMsg_Resp_GetMode),
10968 RespOtaBegin(super::CtrlMsg_Resp_OTABegin),
10969 RespOtaWrite(super::CtrlMsg_Resp_OTAWrite),
10970 RespOtaEnd(super::CtrlMsg_Resp_OTAEnd),
10971 RespSetWifiMaxTxPower(super::CtrlMsg_Resp_SetWifiMaxTxPower),
10972 RespGetWifiCurrTxPower(super::CtrlMsg_Resp_GetWifiCurrTxPower),
10973 RespConfigHeartbeat(super::CtrlMsg_Resp_ConfigHeartbeat),
10974 RespEnableDisableFeat(super::CtrlMsg_Resp_EnableDisable),
10975 RespGetFwVersion(super::CtrlMsg_Resp_GetFwVersion),
10976 RespSetCountryCode(super::CtrlMsg_Resp_SetCountryCode),
10977 RespGetCountryCode(super::CtrlMsg_Resp_GetCountryCode),
10978 RespSetDhcpDnsStatus(super::CtrlMsg_Resp_SetDhcpDnsStatus),
10979 RespGetDhcpDnsStatus(super::CtrlMsg_Resp_GetDhcpDnsStatus),
10980 RespCustomRpcUnserialisedMsg(super::CtrlMsg_Resp_CustomRpcUnserialisedMsg),
10981 EventEspInit(super::CtrlMsg_Event_ESPInit),
10982 EventHeartbeat(super::CtrlMsg_Event_Heartbeat),
10983 EventStationDisconnectFromAp(super::CtrlMsg_Event_StationDisconnectFromAP),
10984 EventStationDisconnectFromEspSoftAp(super::CtrlMsg_Event_StationDisconnectFromESPSoftAP),
10985 EventStationConnectedToAp(super::CtrlMsg_Event_StationConnectedToAP),
10986 EventStationConnectedToEspSoftAp(super::CtrlMsg_Event_StationConnectedToESPSoftAP),
10987 EventSetDhcpDnsStatus(super::CtrlMsg_Event_SetDhcpDnsStatus),
10988 EventCustomRpcUnserialisedMsg(super::CtrlMsg_Event_CustomRpcUnserialisedMsg),
10989 }
10990}
10991#[derive(Debug, Default, PartialEq, Clone)]
10992#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10993pub struct CtrlMsg {
10994 pub r#msg_type: CtrlMsgType,
10995 pub r#msg_id: CtrlMsgId,
10996 pub r#uid: i32,
10997 pub r#req_resp_type: u32,
10998 pub r#payload: ::core::option::Option<CtrlMsg_::Payload>,
10999}
11000impl CtrlMsg {
11001 ///Return a reference to `msg_type`
11002 #[inline]
11003 pub fn r#msg_type(&self) -> &CtrlMsgType {
11004 &self.r#msg_type
11005 }
11006 ///Return a mutable reference to `msg_type`
11007 #[inline]
11008 pub fn mut_msg_type(&mut self) -> &mut CtrlMsgType {
11009 &mut self.r#msg_type
11010 }
11011 ///Set the value of `msg_type`
11012 #[inline]
11013 pub fn set_msg_type(&mut self, value: CtrlMsgType) -> &mut Self {
11014 self.r#msg_type = value.into();
11015 self
11016 }
11017 ///Builder method that sets the value of `msg_type`. Useful for initializing the message.
11018 #[inline]
11019 pub fn init_msg_type(mut self, value: CtrlMsgType) -> Self {
11020 self.r#msg_type = value.into();
11021 self
11022 }
11023 ///Return a reference to `msg_id`
11024 #[inline]
11025 pub fn r#msg_id(&self) -> &CtrlMsgId {
11026 &self.r#msg_id
11027 }
11028 ///Return a mutable reference to `msg_id`
11029 #[inline]
11030 pub fn mut_msg_id(&mut self) -> &mut CtrlMsgId {
11031 &mut self.r#msg_id
11032 }
11033 ///Set the value of `msg_id`
11034 #[inline]
11035 pub fn set_msg_id(&mut self, value: CtrlMsgId) -> &mut Self {
11036 self.r#msg_id = value.into();
11037 self
11038 }
11039 ///Builder method that sets the value of `msg_id`. Useful for initializing the message.
11040 #[inline]
11041 pub fn init_msg_id(mut self, value: CtrlMsgId) -> Self {
11042 self.r#msg_id = value.into();
11043 self
11044 }
11045 ///Return a reference to `uid`
11046 #[inline]
11047 pub fn r#uid(&self) -> &i32 {
11048 &self.r#uid
11049 }
11050 ///Return a mutable reference to `uid`
11051 #[inline]
11052 pub fn mut_uid(&mut self) -> &mut i32 {
11053 &mut self.r#uid
11054 }
11055 ///Set the value of `uid`
11056 #[inline]
11057 pub fn set_uid(&mut self, value: i32) -> &mut Self {
11058 self.r#uid = value.into();
11059 self
11060 }
11061 ///Builder method that sets the value of `uid`. Useful for initializing the message.
11062 #[inline]
11063 pub fn init_uid(mut self, value: i32) -> Self {
11064 self.r#uid = value.into();
11065 self
11066 }
11067 ///Return a reference to `req_resp_type`
11068 #[inline]
11069 pub fn r#req_resp_type(&self) -> &u32 {
11070 &self.r#req_resp_type
11071 }
11072 ///Return a mutable reference to `req_resp_type`
11073 #[inline]
11074 pub fn mut_req_resp_type(&mut self) -> &mut u32 {
11075 &mut self.r#req_resp_type
11076 }
11077 ///Set the value of `req_resp_type`
11078 #[inline]
11079 pub fn set_req_resp_type(&mut self, value: u32) -> &mut Self {
11080 self.r#req_resp_type = value.into();
11081 self
11082 }
11083 ///Builder method that sets the value of `req_resp_type`. Useful for initializing the message.
11084 #[inline]
11085 pub fn init_req_resp_type(mut self, value: u32) -> Self {
11086 self.r#req_resp_type = value.into();
11087 self
11088 }
11089}
11090impl ::micropb::MessageDecode for CtrlMsg {
11091 fn decode<IMPL_MICROPB_READ: ::micropb::PbRead>(
11092 &mut self,
11093 decoder: &mut ::micropb::PbDecoder<IMPL_MICROPB_READ>,
11094 len: usize,
11095 ) -> Result<(), ::micropb::DecodeError<IMPL_MICROPB_READ::Error>> {
11096 use ::micropb::{FieldDecode, PbBytes, PbMap, PbString, PbVec};
11097 let before = decoder.bytes_read();
11098 while decoder.bytes_read() - before < len {
11099 let tag = decoder.decode_tag()?;
11100 match tag.field_num() {
11101 0 => return Err(::micropb::DecodeError::ZeroField),
11102 1u32 => {
11103 let mut_ref = &mut self.r#msg_type;
11104 {
11105 let val = decoder.decode_int32().map(|n| CtrlMsgType(n as _))?;
11106 let val_ref = &val;
11107 if val_ref.0 != 0 {
11108 *mut_ref = val as _;
11109 }
11110 };
11111 }
11112 2u32 => {
11113 let mut_ref = &mut self.r#msg_id;
11114 {
11115 let val = decoder.decode_int32().map(|n| CtrlMsgId(n as _))?;
11116 let val_ref = &val;
11117 if val_ref.0 != 0 {
11118 *mut_ref = val as _;
11119 }
11120 };
11121 }
11122 3u32 => {
11123 let mut_ref = &mut self.r#uid;
11124 {
11125 let val = decoder.decode_int32()?;
11126 let val_ref = &val;
11127 if *val_ref != 0 {
11128 *mut_ref = val as _;
11129 }
11130 };
11131 }
11132 4u32 => {
11133 let mut_ref = &mut self.r#req_resp_type;
11134 {
11135 let val = decoder.decode_varint32()?;
11136 let val_ref = &val;
11137 if *val_ref != 0 {
11138 *mut_ref = val as _;
11139 }
11140 };
11141 }
11142 101u32 => {
11143 let mut_ref = loop {
11144 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11145 if let CtrlMsg_::Payload::ReqGetMacAddress(variant) = &mut *variant {
11146 break &mut *variant;
11147 }
11148 }
11149 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetMacAddress(
11150 ::core::default::Default::default(),
11151 ));
11152 };
11153 mut_ref.decode_len_delimited(decoder)?;
11154 }
11155 102u32 => {
11156 let mut_ref = loop {
11157 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11158 if let CtrlMsg_::Payload::ReqSetMacAddress(variant) = &mut *variant {
11159 break &mut *variant;
11160 }
11161 }
11162 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetMacAddress(
11163 ::core::default::Default::default(),
11164 ));
11165 };
11166 mut_ref.decode_len_delimited(decoder)?;
11167 }
11168 103u32 => {
11169 let mut_ref = loop {
11170 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11171 if let CtrlMsg_::Payload::ReqGetWifiMode(variant) = &mut *variant {
11172 break &mut *variant;
11173 }
11174 }
11175 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetWifiMode(
11176 ::core::default::Default::default(),
11177 ));
11178 };
11179 mut_ref.decode_len_delimited(decoder)?;
11180 }
11181 104u32 => {
11182 let mut_ref = loop {
11183 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11184 if let CtrlMsg_::Payload::ReqSetWifiMode(variant) = &mut *variant {
11185 break &mut *variant;
11186 }
11187 }
11188 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetWifiMode(
11189 ::core::default::Default::default(),
11190 ));
11191 };
11192 mut_ref.decode_len_delimited(decoder)?;
11193 }
11194 105u32 => {
11195 let mut_ref = loop {
11196 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11197 if let CtrlMsg_::Payload::ReqScanApList(variant) = &mut *variant {
11198 break &mut *variant;
11199 }
11200 }
11201 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqScanApList(
11202 ::core::default::Default::default(),
11203 ));
11204 };
11205 mut_ref.decode_len_delimited(decoder)?;
11206 }
11207 106u32 => {
11208 let mut_ref = loop {
11209 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11210 if let CtrlMsg_::Payload::ReqGetApConfig(variant) = &mut *variant {
11211 break &mut *variant;
11212 }
11213 }
11214 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetApConfig(
11215 ::core::default::Default::default(),
11216 ));
11217 };
11218 mut_ref.decode_len_delimited(decoder)?;
11219 }
11220 107u32 => {
11221 let mut_ref = loop {
11222 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11223 if let CtrlMsg_::Payload::ReqConnectAp(variant) = &mut *variant {
11224 break &mut *variant;
11225 }
11226 }
11227 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqConnectAp(
11228 ::core::default::Default::default(),
11229 ));
11230 };
11231 mut_ref.decode_len_delimited(decoder)?;
11232 }
11233 108u32 => {
11234 let mut_ref = loop {
11235 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11236 if let CtrlMsg_::Payload::ReqDisconnectAp(variant) = &mut *variant {
11237 break &mut *variant;
11238 }
11239 }
11240 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqDisconnectAp(
11241 ::core::default::Default::default(),
11242 ));
11243 };
11244 mut_ref.decode_len_delimited(decoder)?;
11245 }
11246 109u32 => {
11247 let mut_ref = loop {
11248 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11249 if let CtrlMsg_::Payload::ReqGetSoftapConfig(variant) = &mut *variant {
11250 break &mut *variant;
11251 }
11252 }
11253 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetSoftapConfig(
11254 ::core::default::Default::default(),
11255 ));
11256 };
11257 mut_ref.decode_len_delimited(decoder)?;
11258 }
11259 110u32 => {
11260 let mut_ref = loop {
11261 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11262 if let CtrlMsg_::Payload::ReqSetSoftapVendorSpecificIe(variant) = &mut *variant {
11263 break &mut *variant;
11264 }
11265 }
11266 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetSoftapVendorSpecificIe(
11267 ::core::default::Default::default(),
11268 ));
11269 };
11270 mut_ref.decode_len_delimited(decoder)?;
11271 }
11272 111u32 => {
11273 let mut_ref = loop {
11274 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11275 if let CtrlMsg_::Payload::ReqStartSoftap(variant) = &mut *variant {
11276 break &mut *variant;
11277 }
11278 }
11279 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqStartSoftap(
11280 ::core::default::Default::default(),
11281 ));
11282 };
11283 mut_ref.decode_len_delimited(decoder)?;
11284 }
11285 112u32 => {
11286 let mut_ref = loop {
11287 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11288 if let CtrlMsg_::Payload::ReqSoftapConnectedStasList(variant) = &mut *variant {
11289 break &mut *variant;
11290 }
11291 }
11292 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSoftapConnectedStasList(
11293 ::core::default::Default::default(),
11294 ));
11295 };
11296 mut_ref.decode_len_delimited(decoder)?;
11297 }
11298 113u32 => {
11299 let mut_ref = loop {
11300 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11301 if let CtrlMsg_::Payload::ReqStopSoftap(variant) = &mut *variant {
11302 break &mut *variant;
11303 }
11304 }
11305 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqStopSoftap(
11306 ::core::default::Default::default(),
11307 ));
11308 };
11309 mut_ref.decode_len_delimited(decoder)?;
11310 }
11311 114u32 => {
11312 let mut_ref = loop {
11313 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11314 if let CtrlMsg_::Payload::ReqSetPowerSaveMode(variant) = &mut *variant {
11315 break &mut *variant;
11316 }
11317 }
11318 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetPowerSaveMode(
11319 ::core::default::Default::default(),
11320 ));
11321 };
11322 mut_ref.decode_len_delimited(decoder)?;
11323 }
11324 115u32 => {
11325 let mut_ref = loop {
11326 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11327 if let CtrlMsg_::Payload::ReqGetPowerSaveMode(variant) = &mut *variant {
11328 break &mut *variant;
11329 }
11330 }
11331 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetPowerSaveMode(
11332 ::core::default::Default::default(),
11333 ));
11334 };
11335 mut_ref.decode_len_delimited(decoder)?;
11336 }
11337 116u32 => {
11338 let mut_ref = loop {
11339 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11340 if let CtrlMsg_::Payload::ReqOtaBegin(variant) = &mut *variant {
11341 break &mut *variant;
11342 }
11343 }
11344 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqOtaBegin(
11345 ::core::default::Default::default(),
11346 ));
11347 };
11348 mut_ref.decode_len_delimited(decoder)?;
11349 }
11350 117u32 => {
11351 let mut_ref = loop {
11352 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11353 if let CtrlMsg_::Payload::ReqOtaWrite(variant) = &mut *variant {
11354 break &mut *variant;
11355 }
11356 }
11357 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqOtaWrite(
11358 ::core::default::Default::default(),
11359 ));
11360 };
11361 mut_ref.decode_len_delimited(decoder)?;
11362 }
11363 118u32 => {
11364 let mut_ref = loop {
11365 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11366 if let CtrlMsg_::Payload::ReqOtaEnd(variant) = &mut *variant {
11367 break &mut *variant;
11368 }
11369 }
11370 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqOtaEnd(
11371 ::core::default::Default::default(),
11372 ));
11373 };
11374 mut_ref.decode_len_delimited(decoder)?;
11375 }
11376 119u32 => {
11377 let mut_ref = loop {
11378 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11379 if let CtrlMsg_::Payload::ReqSetWifiMaxTxPower(variant) = &mut *variant {
11380 break &mut *variant;
11381 }
11382 }
11383 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetWifiMaxTxPower(
11384 ::core::default::Default::default(),
11385 ));
11386 };
11387 mut_ref.decode_len_delimited(decoder)?;
11388 }
11389 120u32 => {
11390 let mut_ref = loop {
11391 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11392 if let CtrlMsg_::Payload::ReqGetWifiCurrTxPower(variant) = &mut *variant {
11393 break &mut *variant;
11394 }
11395 }
11396 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetWifiCurrTxPower(
11397 ::core::default::Default::default(),
11398 ));
11399 };
11400 mut_ref.decode_len_delimited(decoder)?;
11401 }
11402 121u32 => {
11403 let mut_ref = loop {
11404 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11405 if let CtrlMsg_::Payload::ReqConfigHeartbeat(variant) = &mut *variant {
11406 break &mut *variant;
11407 }
11408 }
11409 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqConfigHeartbeat(
11410 ::core::default::Default::default(),
11411 ));
11412 };
11413 mut_ref.decode_len_delimited(decoder)?;
11414 }
11415 122u32 => {
11416 let mut_ref = loop {
11417 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11418 if let CtrlMsg_::Payload::ReqEnableDisableFeat(variant) = &mut *variant {
11419 break &mut *variant;
11420 }
11421 }
11422 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqEnableDisableFeat(
11423 ::core::default::Default::default(),
11424 ));
11425 };
11426 mut_ref.decode_len_delimited(decoder)?;
11427 }
11428 123u32 => {
11429 let mut_ref = loop {
11430 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11431 if let CtrlMsg_::Payload::ReqGetFwVersion(variant) = &mut *variant {
11432 break &mut *variant;
11433 }
11434 }
11435 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetFwVersion(
11436 ::core::default::Default::default(),
11437 ));
11438 };
11439 mut_ref.decode_len_delimited(decoder)?;
11440 }
11441 124u32 => {
11442 let mut_ref = loop {
11443 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11444 if let CtrlMsg_::Payload::ReqSetCountryCode(variant) = &mut *variant {
11445 break &mut *variant;
11446 }
11447 }
11448 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetCountryCode(
11449 ::core::default::Default::default(),
11450 ));
11451 };
11452 mut_ref.decode_len_delimited(decoder)?;
11453 }
11454 125u32 => {
11455 let mut_ref = loop {
11456 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11457 if let CtrlMsg_::Payload::ReqGetCountryCode(variant) = &mut *variant {
11458 break &mut *variant;
11459 }
11460 }
11461 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetCountryCode(
11462 ::core::default::Default::default(),
11463 ));
11464 };
11465 mut_ref.decode_len_delimited(decoder)?;
11466 }
11467 126u32 => {
11468 let mut_ref = loop {
11469 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11470 if let CtrlMsg_::Payload::ReqSetDhcpDnsStatus(variant) = &mut *variant {
11471 break &mut *variant;
11472 }
11473 }
11474 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqSetDhcpDnsStatus(
11475 ::core::default::Default::default(),
11476 ));
11477 };
11478 mut_ref.decode_len_delimited(decoder)?;
11479 }
11480 127u32 => {
11481 let mut_ref = loop {
11482 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11483 if let CtrlMsg_::Payload::ReqGetDhcpDnsStatus(variant) = &mut *variant {
11484 break &mut *variant;
11485 }
11486 }
11487 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqGetDhcpDnsStatus(
11488 ::core::default::Default::default(),
11489 ));
11490 };
11491 mut_ref.decode_len_delimited(decoder)?;
11492 }
11493 128u32 => {
11494 let mut_ref = loop {
11495 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11496 if let CtrlMsg_::Payload::ReqCustomRpcUnserialisedMsg(variant) = &mut *variant {
11497 break &mut *variant;
11498 }
11499 }
11500 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::ReqCustomRpcUnserialisedMsg(
11501 ::core::default::Default::default(),
11502 ));
11503 };
11504 mut_ref.decode_len_delimited(decoder)?;
11505 }
11506 201u32 => {
11507 let mut_ref = loop {
11508 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11509 if let CtrlMsg_::Payload::RespGetMacAddress(variant) = &mut *variant {
11510 break &mut *variant;
11511 }
11512 }
11513 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetMacAddress(
11514 ::core::default::Default::default(),
11515 ));
11516 };
11517 mut_ref.decode_len_delimited(decoder)?;
11518 }
11519 202u32 => {
11520 let mut_ref = loop {
11521 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11522 if let CtrlMsg_::Payload::RespSetMacAddress(variant) = &mut *variant {
11523 break &mut *variant;
11524 }
11525 }
11526 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetMacAddress(
11527 ::core::default::Default::default(),
11528 ));
11529 };
11530 mut_ref.decode_len_delimited(decoder)?;
11531 }
11532 203u32 => {
11533 let mut_ref = loop {
11534 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11535 if let CtrlMsg_::Payload::RespGetWifiMode(variant) = &mut *variant {
11536 break &mut *variant;
11537 }
11538 }
11539 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetWifiMode(
11540 ::core::default::Default::default(),
11541 ));
11542 };
11543 mut_ref.decode_len_delimited(decoder)?;
11544 }
11545 204u32 => {
11546 let mut_ref = loop {
11547 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11548 if let CtrlMsg_::Payload::RespSetWifiMode(variant) = &mut *variant {
11549 break &mut *variant;
11550 }
11551 }
11552 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetWifiMode(
11553 ::core::default::Default::default(),
11554 ));
11555 };
11556 mut_ref.decode_len_delimited(decoder)?;
11557 }
11558 205u32 => {
11559 let mut_ref = loop {
11560 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11561 if let CtrlMsg_::Payload::RespScanApList(variant) = &mut *variant {
11562 break &mut *variant;
11563 }
11564 }
11565 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespScanApList(
11566 ::core::default::Default::default(),
11567 ));
11568 };
11569 mut_ref.decode_len_delimited(decoder)?;
11570 }
11571 206u32 => {
11572 let mut_ref = loop {
11573 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11574 if let CtrlMsg_::Payload::RespGetApConfig(variant) = &mut *variant {
11575 break &mut *variant;
11576 }
11577 }
11578 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetApConfig(
11579 ::core::default::Default::default(),
11580 ));
11581 };
11582 mut_ref.decode_len_delimited(decoder)?;
11583 }
11584 207u32 => {
11585 let mut_ref = loop {
11586 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11587 if let CtrlMsg_::Payload::RespConnectAp(variant) = &mut *variant {
11588 break &mut *variant;
11589 }
11590 }
11591 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespConnectAp(
11592 ::core::default::Default::default(),
11593 ));
11594 };
11595 mut_ref.decode_len_delimited(decoder)?;
11596 }
11597 208u32 => {
11598 let mut_ref = loop {
11599 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11600 if let CtrlMsg_::Payload::RespDisconnectAp(variant) = &mut *variant {
11601 break &mut *variant;
11602 }
11603 }
11604 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespDisconnectAp(
11605 ::core::default::Default::default(),
11606 ));
11607 };
11608 mut_ref.decode_len_delimited(decoder)?;
11609 }
11610 209u32 => {
11611 let mut_ref = loop {
11612 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11613 if let CtrlMsg_::Payload::RespGetSoftapConfig(variant) = &mut *variant {
11614 break &mut *variant;
11615 }
11616 }
11617 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetSoftapConfig(
11618 ::core::default::Default::default(),
11619 ));
11620 };
11621 mut_ref.decode_len_delimited(decoder)?;
11622 }
11623 210u32 => {
11624 let mut_ref = loop {
11625 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11626 if let CtrlMsg_::Payload::RespSetSoftapVendorSpecificIe(variant) = &mut *variant {
11627 break &mut *variant;
11628 }
11629 }
11630 self.r#payload = ::core::option::Option::Some(
11631 CtrlMsg_::Payload::RespSetSoftapVendorSpecificIe(::core::default::Default::default()),
11632 );
11633 };
11634 mut_ref.decode_len_delimited(decoder)?;
11635 }
11636 211u32 => {
11637 let mut_ref = loop {
11638 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11639 if let CtrlMsg_::Payload::RespStartSoftap(variant) = &mut *variant {
11640 break &mut *variant;
11641 }
11642 }
11643 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespStartSoftap(
11644 ::core::default::Default::default(),
11645 ));
11646 };
11647 mut_ref.decode_len_delimited(decoder)?;
11648 }
11649 212u32 => {
11650 let mut_ref = loop {
11651 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11652 if let CtrlMsg_::Payload::RespSoftapConnectedStasList(variant) = &mut *variant {
11653 break &mut *variant;
11654 }
11655 }
11656 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSoftapConnectedStasList(
11657 ::core::default::Default::default(),
11658 ));
11659 };
11660 mut_ref.decode_len_delimited(decoder)?;
11661 }
11662 213u32 => {
11663 let mut_ref = loop {
11664 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11665 if let CtrlMsg_::Payload::RespStopSoftap(variant) = &mut *variant {
11666 break &mut *variant;
11667 }
11668 }
11669 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespStopSoftap(
11670 ::core::default::Default::default(),
11671 ));
11672 };
11673 mut_ref.decode_len_delimited(decoder)?;
11674 }
11675 214u32 => {
11676 let mut_ref = loop {
11677 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11678 if let CtrlMsg_::Payload::RespSetPowerSaveMode(variant) = &mut *variant {
11679 break &mut *variant;
11680 }
11681 }
11682 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetPowerSaveMode(
11683 ::core::default::Default::default(),
11684 ));
11685 };
11686 mut_ref.decode_len_delimited(decoder)?;
11687 }
11688 215u32 => {
11689 let mut_ref = loop {
11690 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11691 if let CtrlMsg_::Payload::RespGetPowerSaveMode(variant) = &mut *variant {
11692 break &mut *variant;
11693 }
11694 }
11695 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetPowerSaveMode(
11696 ::core::default::Default::default(),
11697 ));
11698 };
11699 mut_ref.decode_len_delimited(decoder)?;
11700 }
11701 216u32 => {
11702 let mut_ref = loop {
11703 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11704 if let CtrlMsg_::Payload::RespOtaBegin(variant) = &mut *variant {
11705 break &mut *variant;
11706 }
11707 }
11708 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespOtaBegin(
11709 ::core::default::Default::default(),
11710 ));
11711 };
11712 mut_ref.decode_len_delimited(decoder)?;
11713 }
11714 217u32 => {
11715 let mut_ref = loop {
11716 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11717 if let CtrlMsg_::Payload::RespOtaWrite(variant) = &mut *variant {
11718 break &mut *variant;
11719 }
11720 }
11721 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespOtaWrite(
11722 ::core::default::Default::default(),
11723 ));
11724 };
11725 mut_ref.decode_len_delimited(decoder)?;
11726 }
11727 218u32 => {
11728 let mut_ref = loop {
11729 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11730 if let CtrlMsg_::Payload::RespOtaEnd(variant) = &mut *variant {
11731 break &mut *variant;
11732 }
11733 }
11734 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespOtaEnd(
11735 ::core::default::Default::default(),
11736 ));
11737 };
11738 mut_ref.decode_len_delimited(decoder)?;
11739 }
11740 219u32 => {
11741 let mut_ref = loop {
11742 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11743 if let CtrlMsg_::Payload::RespSetWifiMaxTxPower(variant) = &mut *variant {
11744 break &mut *variant;
11745 }
11746 }
11747 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetWifiMaxTxPower(
11748 ::core::default::Default::default(),
11749 ));
11750 };
11751 mut_ref.decode_len_delimited(decoder)?;
11752 }
11753 220u32 => {
11754 let mut_ref = loop {
11755 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11756 if let CtrlMsg_::Payload::RespGetWifiCurrTxPower(variant) = &mut *variant {
11757 break &mut *variant;
11758 }
11759 }
11760 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetWifiCurrTxPower(
11761 ::core::default::Default::default(),
11762 ));
11763 };
11764 mut_ref.decode_len_delimited(decoder)?;
11765 }
11766 221u32 => {
11767 let mut_ref = loop {
11768 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11769 if let CtrlMsg_::Payload::RespConfigHeartbeat(variant) = &mut *variant {
11770 break &mut *variant;
11771 }
11772 }
11773 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespConfigHeartbeat(
11774 ::core::default::Default::default(),
11775 ));
11776 };
11777 mut_ref.decode_len_delimited(decoder)?;
11778 }
11779 222u32 => {
11780 let mut_ref = loop {
11781 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11782 if let CtrlMsg_::Payload::RespEnableDisableFeat(variant) = &mut *variant {
11783 break &mut *variant;
11784 }
11785 }
11786 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespEnableDisableFeat(
11787 ::core::default::Default::default(),
11788 ));
11789 };
11790 mut_ref.decode_len_delimited(decoder)?;
11791 }
11792 223u32 => {
11793 let mut_ref = loop {
11794 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11795 if let CtrlMsg_::Payload::RespGetFwVersion(variant) = &mut *variant {
11796 break &mut *variant;
11797 }
11798 }
11799 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetFwVersion(
11800 ::core::default::Default::default(),
11801 ));
11802 };
11803 mut_ref.decode_len_delimited(decoder)?;
11804 }
11805 224u32 => {
11806 let mut_ref = loop {
11807 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11808 if let CtrlMsg_::Payload::RespSetCountryCode(variant) = &mut *variant {
11809 break &mut *variant;
11810 }
11811 }
11812 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetCountryCode(
11813 ::core::default::Default::default(),
11814 ));
11815 };
11816 mut_ref.decode_len_delimited(decoder)?;
11817 }
11818 225u32 => {
11819 let mut_ref = loop {
11820 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11821 if let CtrlMsg_::Payload::RespGetCountryCode(variant) = &mut *variant {
11822 break &mut *variant;
11823 }
11824 }
11825 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetCountryCode(
11826 ::core::default::Default::default(),
11827 ));
11828 };
11829 mut_ref.decode_len_delimited(decoder)?;
11830 }
11831 226u32 => {
11832 let mut_ref = loop {
11833 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11834 if let CtrlMsg_::Payload::RespSetDhcpDnsStatus(variant) = &mut *variant {
11835 break &mut *variant;
11836 }
11837 }
11838 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespSetDhcpDnsStatus(
11839 ::core::default::Default::default(),
11840 ));
11841 };
11842 mut_ref.decode_len_delimited(decoder)?;
11843 }
11844 227u32 => {
11845 let mut_ref = loop {
11846 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11847 if let CtrlMsg_::Payload::RespGetDhcpDnsStatus(variant) = &mut *variant {
11848 break &mut *variant;
11849 }
11850 }
11851 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespGetDhcpDnsStatus(
11852 ::core::default::Default::default(),
11853 ));
11854 };
11855 mut_ref.decode_len_delimited(decoder)?;
11856 }
11857 228u32 => {
11858 let mut_ref = loop {
11859 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11860 if let CtrlMsg_::Payload::RespCustomRpcUnserialisedMsg(variant) = &mut *variant {
11861 break &mut *variant;
11862 }
11863 }
11864 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::RespCustomRpcUnserialisedMsg(
11865 ::core::default::Default::default(),
11866 ));
11867 };
11868 mut_ref.decode_len_delimited(decoder)?;
11869 }
11870 301u32 => {
11871 let mut_ref = loop {
11872 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11873 if let CtrlMsg_::Payload::EventEspInit(variant) = &mut *variant {
11874 break &mut *variant;
11875 }
11876 }
11877 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::EventEspInit(
11878 ::core::default::Default::default(),
11879 ));
11880 };
11881 mut_ref.decode_len_delimited(decoder)?;
11882 }
11883 302u32 => {
11884 let mut_ref = loop {
11885 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11886 if let CtrlMsg_::Payload::EventHeartbeat(variant) = &mut *variant {
11887 break &mut *variant;
11888 }
11889 }
11890 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::EventHeartbeat(
11891 ::core::default::Default::default(),
11892 ));
11893 };
11894 mut_ref.decode_len_delimited(decoder)?;
11895 }
11896 303u32 => {
11897 let mut_ref = loop {
11898 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11899 if let CtrlMsg_::Payload::EventStationDisconnectFromAp(variant) = &mut *variant {
11900 break &mut *variant;
11901 }
11902 }
11903 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::EventStationDisconnectFromAp(
11904 ::core::default::Default::default(),
11905 ));
11906 };
11907 mut_ref.decode_len_delimited(decoder)?;
11908 }
11909 304u32 => {
11910 let mut_ref = loop {
11911 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11912 if let CtrlMsg_::Payload::EventStationDisconnectFromEspSoftAp(variant) = &mut *variant {
11913 break &mut *variant;
11914 }
11915 }
11916 self.r#payload = ::core::option::Option::Some(
11917 CtrlMsg_::Payload::EventStationDisconnectFromEspSoftAp(::core::default::Default::default()),
11918 );
11919 };
11920 mut_ref.decode_len_delimited(decoder)?;
11921 }
11922 305u32 => {
11923 let mut_ref = loop {
11924 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11925 if let CtrlMsg_::Payload::EventStationConnectedToAp(variant) = &mut *variant {
11926 break &mut *variant;
11927 }
11928 }
11929 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::EventStationConnectedToAp(
11930 ::core::default::Default::default(),
11931 ));
11932 };
11933 mut_ref.decode_len_delimited(decoder)?;
11934 }
11935 306u32 => {
11936 let mut_ref = loop {
11937 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11938 if let CtrlMsg_::Payload::EventStationConnectedToEspSoftAp(variant) = &mut *variant {
11939 break &mut *variant;
11940 }
11941 }
11942 self.r#payload = ::core::option::Option::Some(
11943 CtrlMsg_::Payload::EventStationConnectedToEspSoftAp(::core::default::Default::default()),
11944 );
11945 };
11946 mut_ref.decode_len_delimited(decoder)?;
11947 }
11948 307u32 => {
11949 let mut_ref = loop {
11950 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11951 if let CtrlMsg_::Payload::EventSetDhcpDnsStatus(variant) = &mut *variant {
11952 break &mut *variant;
11953 }
11954 }
11955 self.r#payload = ::core::option::Option::Some(CtrlMsg_::Payload::EventSetDhcpDnsStatus(
11956 ::core::default::Default::default(),
11957 ));
11958 };
11959 mut_ref.decode_len_delimited(decoder)?;
11960 }
11961 308u32 => {
11962 let mut_ref = loop {
11963 if let ::core::option::Option::Some(variant) = &mut self.r#payload {
11964 if let CtrlMsg_::Payload::EventCustomRpcUnserialisedMsg(variant) = &mut *variant {
11965 break &mut *variant;
11966 }
11967 }
11968 self.r#payload = ::core::option::Option::Some(
11969 CtrlMsg_::Payload::EventCustomRpcUnserialisedMsg(::core::default::Default::default()),
11970 );
11971 };
11972 mut_ref.decode_len_delimited(decoder)?;
11973 }
11974 _ => {
11975 decoder.skip_wire_value(tag.wire_type())?;
11976 }
11977 }
11978 }
11979 Ok(())
11980 }
11981}
11982impl ::micropb::MessageEncode for CtrlMsg {
11983 const MAX_SIZE: ::core::option::Option<usize> = 'msg: {
11984 let mut max_size = 0;
11985 if let ::core::option::Option::Some(size) =
11986 ::micropb::const_map!(::core::option::Option::Some(CtrlMsgType::_MAX_SIZE), |size| size
11987 + 1usize)
11988 {
11989 max_size += size;
11990 } else {
11991 break 'msg (::core::option::Option::<usize>::None);
11992 };
11993 if let ::core::option::Option::Some(size) =
11994 ::micropb::const_map!(::core::option::Option::Some(CtrlMsgId::_MAX_SIZE), |size| size + 1usize)
11995 {
11996 max_size += size;
11997 } else {
11998 break 'msg (::core::option::Option::<usize>::None);
11999 };
12000 if let ::core::option::Option::Some(size) =
12001 ::micropb::const_map!(::core::option::Option::Some(10usize), |size| size + 1usize)
12002 {
12003 max_size += size;
12004 } else {
12005 break 'msg (::core::option::Option::<usize>::None);
12006 };
12007 if let ::core::option::Option::Some(size) =
12008 ::micropb::const_map!(::core::option::Option::Some(5usize), |size| size + 1usize)
12009 {
12010 max_size += size;
12011 } else {
12012 break 'msg (::core::option::Option::<usize>::None);
12013 };
12014 if let ::core::option::Option::Some(size) = 'oneof: {
12015 let mut max_size = 0;
12016 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12017 ::micropb::const_map!(
12018 <CtrlMsg_Req_GetMacAddress as ::micropb::MessageEncode>::MAX_SIZE,
12019 |size| ::micropb::size::sizeof_len_record(size)
12020 ),
12021 |size| size + 2usize
12022 ) {
12023 if size > max_size {
12024 max_size = size;
12025 }
12026 } else {
12027 break 'oneof (::core::option::Option::<usize>::None);
12028 }
12029 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12030 ::micropb::const_map!(
12031 <CtrlMsg_Req_SetMacAddress as ::micropb::MessageEncode>::MAX_SIZE,
12032 |size| ::micropb::size::sizeof_len_record(size)
12033 ),
12034 |size| size + 2usize
12035 ) {
12036 if size > max_size {
12037 max_size = size;
12038 }
12039 } else {
12040 break 'oneof (::core::option::Option::<usize>::None);
12041 }
12042 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12043 ::micropb::const_map!(<CtrlMsg_Req_GetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12044 ::micropb::size::sizeof_len_record(size)
12045 }),
12046 |size| size + 2usize
12047 ) {
12048 if size > max_size {
12049 max_size = size;
12050 }
12051 } else {
12052 break 'oneof (::core::option::Option::<usize>::None);
12053 }
12054 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12055 ::micropb::const_map!(<CtrlMsg_Req_SetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12056 ::micropb::size::sizeof_len_record(size)
12057 }),
12058 |size| size + 2usize
12059 ) {
12060 if size > max_size {
12061 max_size = size;
12062 }
12063 } else {
12064 break 'oneof (::core::option::Option::<usize>::None);
12065 }
12066 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12067 ::micropb::const_map!(<CtrlMsg_Req_ScanResult as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12068 ::micropb::size::sizeof_len_record(size)
12069 }),
12070 |size| size + 2usize
12071 ) {
12072 if size > max_size {
12073 max_size = size;
12074 }
12075 } else {
12076 break 'oneof (::core::option::Option::<usize>::None);
12077 }
12078 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12079 ::micropb::const_map!(
12080 <CtrlMsg_Req_GetAPConfig as ::micropb::MessageEncode>::MAX_SIZE,
12081 |size| ::micropb::size::sizeof_len_record(size)
12082 ),
12083 |size| size + 2usize
12084 ) {
12085 if size > max_size {
12086 max_size = size;
12087 }
12088 } else {
12089 break 'oneof (::core::option::Option::<usize>::None);
12090 }
12091 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12092 ::micropb::const_map!(<CtrlMsg_Req_ConnectAP as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12093 ::micropb::size::sizeof_len_record(size)
12094 }),
12095 |size| size + 2usize
12096 ) {
12097 if size > max_size {
12098 max_size = size;
12099 }
12100 } else {
12101 break 'oneof (::core::option::Option::<usize>::None);
12102 }
12103 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12104 ::micropb::const_map!(<CtrlMsg_Req_GetStatus as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12105 ::micropb::size::sizeof_len_record(size)
12106 }),
12107 |size| size + 2usize
12108 ) {
12109 if size > max_size {
12110 max_size = size;
12111 }
12112 } else {
12113 break 'oneof (::core::option::Option::<usize>::None);
12114 }
12115 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12116 ::micropb::const_map!(
12117 <CtrlMsg_Req_GetSoftAPConfig as ::micropb::MessageEncode>::MAX_SIZE,
12118 |size| ::micropb::size::sizeof_len_record(size)
12119 ),
12120 |size| size + 2usize
12121 ) {
12122 if size > max_size {
12123 max_size = size;
12124 }
12125 } else {
12126 break 'oneof (::core::option::Option::<usize>::None);
12127 }
12128 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12129 ::micropb::const_map!(
12130 <CtrlMsg_Req_SetSoftAPVendorSpecificIE as ::micropb::MessageEncode>::MAX_SIZE,
12131 |size| ::micropb::size::sizeof_len_record(size)
12132 ),
12133 |size| size + 2usize
12134 ) {
12135 if size > max_size {
12136 max_size = size;
12137 }
12138 } else {
12139 break 'oneof (::core::option::Option::<usize>::None);
12140 }
12141 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12142 ::micropb::const_map!(
12143 <CtrlMsg_Req_StartSoftAP as ::micropb::MessageEncode>::MAX_SIZE,
12144 |size| ::micropb::size::sizeof_len_record(size)
12145 ),
12146 |size| size + 2usize
12147 ) {
12148 if size > max_size {
12149 max_size = size;
12150 }
12151 } else {
12152 break 'oneof (::core::option::Option::<usize>::None);
12153 }
12154 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12155 ::micropb::const_map!(
12156 <CtrlMsg_Req_SoftAPConnectedSTA as ::micropb::MessageEncode>::MAX_SIZE,
12157 |size| ::micropb::size::sizeof_len_record(size)
12158 ),
12159 |size| size + 2usize
12160 ) {
12161 if size > max_size {
12162 max_size = size;
12163 }
12164 } else {
12165 break 'oneof (::core::option::Option::<usize>::None);
12166 }
12167 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12168 ::micropb::const_map!(<CtrlMsg_Req_GetStatus as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12169 ::micropb::size::sizeof_len_record(size)
12170 }),
12171 |size| size + 2usize
12172 ) {
12173 if size > max_size {
12174 max_size = size;
12175 }
12176 } else {
12177 break 'oneof (::core::option::Option::<usize>::None);
12178 }
12179 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12180 ::micropb::const_map!(<CtrlMsg_Req_SetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12181 ::micropb::size::sizeof_len_record(size)
12182 }),
12183 |size| size + 2usize
12184 ) {
12185 if size > max_size {
12186 max_size = size;
12187 }
12188 } else {
12189 break 'oneof (::core::option::Option::<usize>::None);
12190 }
12191 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12192 ::micropb::const_map!(<CtrlMsg_Req_GetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12193 ::micropb::size::sizeof_len_record(size)
12194 }),
12195 |size| size + 2usize
12196 ) {
12197 if size > max_size {
12198 max_size = size;
12199 }
12200 } else {
12201 break 'oneof (::core::option::Option::<usize>::None);
12202 }
12203 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12204 ::micropb::const_map!(<CtrlMsg_Req_OTABegin as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12205 ::micropb::size::sizeof_len_record(size)
12206 }),
12207 |size| size + 2usize
12208 ) {
12209 if size > max_size {
12210 max_size = size;
12211 }
12212 } else {
12213 break 'oneof (::core::option::Option::<usize>::None);
12214 }
12215 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12216 ::micropb::const_map!(<CtrlMsg_Req_OTAWrite as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12217 ::micropb::size::sizeof_len_record(size)
12218 }),
12219 |size| size + 2usize
12220 ) {
12221 if size > max_size {
12222 max_size = size;
12223 }
12224 } else {
12225 break 'oneof (::core::option::Option::<usize>::None);
12226 }
12227 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12228 ::micropb::const_map!(<CtrlMsg_Req_OTAEnd as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12229 ::micropb::size::sizeof_len_record(size)
12230 }),
12231 |size| size + 2usize
12232 ) {
12233 if size > max_size {
12234 max_size = size;
12235 }
12236 } else {
12237 break 'oneof (::core::option::Option::<usize>::None);
12238 }
12239 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12240 ::micropb::const_map!(
12241 <CtrlMsg_Req_SetWifiMaxTxPower as ::micropb::MessageEncode>::MAX_SIZE,
12242 |size| ::micropb::size::sizeof_len_record(size)
12243 ),
12244 |size| size + 2usize
12245 ) {
12246 if size > max_size {
12247 max_size = size;
12248 }
12249 } else {
12250 break 'oneof (::core::option::Option::<usize>::None);
12251 }
12252 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12253 ::micropb::const_map!(
12254 <CtrlMsg_Req_GetWifiCurrTxPower as ::micropb::MessageEncode>::MAX_SIZE,
12255 |size| ::micropb::size::sizeof_len_record(size)
12256 ),
12257 |size| size + 2usize
12258 ) {
12259 if size > max_size {
12260 max_size = size;
12261 }
12262 } else {
12263 break 'oneof (::core::option::Option::<usize>::None);
12264 }
12265 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12266 ::micropb::const_map!(
12267 <CtrlMsg_Req_ConfigHeartbeat as ::micropb::MessageEncode>::MAX_SIZE,
12268 |size| ::micropb::size::sizeof_len_record(size)
12269 ),
12270 |size| size + 2usize
12271 ) {
12272 if size > max_size {
12273 max_size = size;
12274 }
12275 } else {
12276 break 'oneof (::core::option::Option::<usize>::None);
12277 }
12278 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12279 ::micropb::const_map!(
12280 <CtrlMsg_Req_EnableDisable as ::micropb::MessageEncode>::MAX_SIZE,
12281 |size| ::micropb::size::sizeof_len_record(size)
12282 ),
12283 |size| size + 2usize
12284 ) {
12285 if size > max_size {
12286 max_size = size;
12287 }
12288 } else {
12289 break 'oneof (::core::option::Option::<usize>::None);
12290 }
12291 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12292 ::micropb::const_map!(
12293 <CtrlMsg_Req_GetFwVersion as ::micropb::MessageEncode>::MAX_SIZE,
12294 |size| ::micropb::size::sizeof_len_record(size)
12295 ),
12296 |size| size + 2usize
12297 ) {
12298 if size > max_size {
12299 max_size = size;
12300 }
12301 } else {
12302 break 'oneof (::core::option::Option::<usize>::None);
12303 }
12304 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12305 ::micropb::const_map!(
12306 <CtrlMsg_Req_SetCountryCode as ::micropb::MessageEncode>::MAX_SIZE,
12307 |size| ::micropb::size::sizeof_len_record(size)
12308 ),
12309 |size| size + 2usize
12310 ) {
12311 if size > max_size {
12312 max_size = size;
12313 }
12314 } else {
12315 break 'oneof (::core::option::Option::<usize>::None);
12316 }
12317 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12318 ::micropb::const_map!(
12319 <CtrlMsg_Req_GetCountryCode as ::micropb::MessageEncode>::MAX_SIZE,
12320 |size| ::micropb::size::sizeof_len_record(size)
12321 ),
12322 |size| size + 2usize
12323 ) {
12324 if size > max_size {
12325 max_size = size;
12326 }
12327 } else {
12328 break 'oneof (::core::option::Option::<usize>::None);
12329 }
12330 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12331 ::micropb::const_map!(
12332 <CtrlMsg_Req_SetDhcpDnsStatus as ::micropb::MessageEncode>::MAX_SIZE,
12333 |size| ::micropb::size::sizeof_len_record(size)
12334 ),
12335 |size| size + 2usize
12336 ) {
12337 if size > max_size {
12338 max_size = size;
12339 }
12340 } else {
12341 break 'oneof (::core::option::Option::<usize>::None);
12342 }
12343 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12344 ::micropb::const_map!(
12345 <CtrlMsg_Req_GetDhcpDnsStatus as ::micropb::MessageEncode>::MAX_SIZE,
12346 |size| ::micropb::size::sizeof_len_record(size)
12347 ),
12348 |size| size + 2usize
12349 ) {
12350 if size > max_size {
12351 max_size = size;
12352 }
12353 } else {
12354 break 'oneof (::core::option::Option::<usize>::None);
12355 }
12356 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12357 ::micropb::const_map!(
12358 <CtrlMsg_Req_CustomRpcUnserialisedMsg as ::micropb::MessageEncode>::MAX_SIZE,
12359 |size| ::micropb::size::sizeof_len_record(size)
12360 ),
12361 |size| size + 2usize
12362 ) {
12363 if size > max_size {
12364 max_size = size;
12365 }
12366 } else {
12367 break 'oneof (::core::option::Option::<usize>::None);
12368 }
12369 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12370 ::micropb::const_map!(
12371 <CtrlMsg_Resp_GetMacAddress as ::micropb::MessageEncode>::MAX_SIZE,
12372 |size| ::micropb::size::sizeof_len_record(size)
12373 ),
12374 |size| size + 2usize
12375 ) {
12376 if size > max_size {
12377 max_size = size;
12378 }
12379 } else {
12380 break 'oneof (::core::option::Option::<usize>::None);
12381 }
12382 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12383 ::micropb::const_map!(
12384 <CtrlMsg_Resp_SetMacAddress as ::micropb::MessageEncode>::MAX_SIZE,
12385 |size| ::micropb::size::sizeof_len_record(size)
12386 ),
12387 |size| size + 2usize
12388 ) {
12389 if size > max_size {
12390 max_size = size;
12391 }
12392 } else {
12393 break 'oneof (::core::option::Option::<usize>::None);
12394 }
12395 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12396 ::micropb::const_map!(<CtrlMsg_Resp_GetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12397 ::micropb::size::sizeof_len_record(size)
12398 }),
12399 |size| size + 2usize
12400 ) {
12401 if size > max_size {
12402 max_size = size;
12403 }
12404 } else {
12405 break 'oneof (::core::option::Option::<usize>::None);
12406 }
12407 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12408 ::micropb::const_map!(<CtrlMsg_Resp_SetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12409 ::micropb::size::sizeof_len_record(size)
12410 }),
12411 |size| size + 2usize
12412 ) {
12413 if size > max_size {
12414 max_size = size;
12415 }
12416 } else {
12417 break 'oneof (::core::option::Option::<usize>::None);
12418 }
12419 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12420 ::micropb::const_map!(
12421 <CtrlMsg_Resp_ScanResult as ::micropb::MessageEncode>::MAX_SIZE,
12422 |size| ::micropb::size::sizeof_len_record(size)
12423 ),
12424 |size| size + 2usize
12425 ) {
12426 if size > max_size {
12427 max_size = size;
12428 }
12429 } else {
12430 break 'oneof (::core::option::Option::<usize>::None);
12431 }
12432 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12433 ::micropb::const_map!(
12434 <CtrlMsg_Resp_GetAPConfig as ::micropb::MessageEncode>::MAX_SIZE,
12435 |size| ::micropb::size::sizeof_len_record(size)
12436 ),
12437 |size| size + 2usize
12438 ) {
12439 if size > max_size {
12440 max_size = size;
12441 }
12442 } else {
12443 break 'oneof (::core::option::Option::<usize>::None);
12444 }
12445 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12446 ::micropb::const_map!(<CtrlMsg_Resp_ConnectAP as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12447 ::micropb::size::sizeof_len_record(size)
12448 }),
12449 |size| size + 2usize
12450 ) {
12451 if size > max_size {
12452 max_size = size;
12453 }
12454 } else {
12455 break 'oneof (::core::option::Option::<usize>::None);
12456 }
12457 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12458 ::micropb::const_map!(<CtrlMsg_Resp_GetStatus as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12459 ::micropb::size::sizeof_len_record(size)
12460 }),
12461 |size| size + 2usize
12462 ) {
12463 if size > max_size {
12464 max_size = size;
12465 }
12466 } else {
12467 break 'oneof (::core::option::Option::<usize>::None);
12468 }
12469 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12470 ::micropb::const_map!(
12471 <CtrlMsg_Resp_GetSoftAPConfig as ::micropb::MessageEncode>::MAX_SIZE,
12472 |size| ::micropb::size::sizeof_len_record(size)
12473 ),
12474 |size| size + 2usize
12475 ) {
12476 if size > max_size {
12477 max_size = size;
12478 }
12479 } else {
12480 break 'oneof (::core::option::Option::<usize>::None);
12481 }
12482 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12483 ::micropb::const_map!(
12484 <CtrlMsg_Resp_SetSoftAPVendorSpecificIE as ::micropb::MessageEncode>::MAX_SIZE,
12485 |size| ::micropb::size::sizeof_len_record(size)
12486 ),
12487 |size| size + 2usize
12488 ) {
12489 if size > max_size {
12490 max_size = size;
12491 }
12492 } else {
12493 break 'oneof (::core::option::Option::<usize>::None);
12494 }
12495 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12496 ::micropb::const_map!(
12497 <CtrlMsg_Resp_StartSoftAP as ::micropb::MessageEncode>::MAX_SIZE,
12498 |size| ::micropb::size::sizeof_len_record(size)
12499 ),
12500 |size| size + 2usize
12501 ) {
12502 if size > max_size {
12503 max_size = size;
12504 }
12505 } else {
12506 break 'oneof (::core::option::Option::<usize>::None);
12507 }
12508 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12509 ::micropb::const_map!(
12510 <CtrlMsg_Resp_SoftAPConnectedSTA as ::micropb::MessageEncode>::MAX_SIZE,
12511 |size| ::micropb::size::sizeof_len_record(size)
12512 ),
12513 |size| size + 2usize
12514 ) {
12515 if size > max_size {
12516 max_size = size;
12517 }
12518 } else {
12519 break 'oneof (::core::option::Option::<usize>::None);
12520 }
12521 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12522 ::micropb::const_map!(<CtrlMsg_Resp_GetStatus as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12523 ::micropb::size::sizeof_len_record(size)
12524 }),
12525 |size| size + 2usize
12526 ) {
12527 if size > max_size {
12528 max_size = size;
12529 }
12530 } else {
12531 break 'oneof (::core::option::Option::<usize>::None);
12532 }
12533 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12534 ::micropb::const_map!(<CtrlMsg_Resp_SetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12535 ::micropb::size::sizeof_len_record(size)
12536 }),
12537 |size| size + 2usize
12538 ) {
12539 if size > max_size {
12540 max_size = size;
12541 }
12542 } else {
12543 break 'oneof (::core::option::Option::<usize>::None);
12544 }
12545 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12546 ::micropb::const_map!(<CtrlMsg_Resp_GetMode as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12547 ::micropb::size::sizeof_len_record(size)
12548 }),
12549 |size| size + 2usize
12550 ) {
12551 if size > max_size {
12552 max_size = size;
12553 }
12554 } else {
12555 break 'oneof (::core::option::Option::<usize>::None);
12556 }
12557 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12558 ::micropb::const_map!(<CtrlMsg_Resp_OTABegin as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12559 ::micropb::size::sizeof_len_record(size)
12560 }),
12561 |size| size + 2usize
12562 ) {
12563 if size > max_size {
12564 max_size = size;
12565 }
12566 } else {
12567 break 'oneof (::core::option::Option::<usize>::None);
12568 }
12569 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12570 ::micropb::const_map!(<CtrlMsg_Resp_OTAWrite as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12571 ::micropb::size::sizeof_len_record(size)
12572 }),
12573 |size| size + 2usize
12574 ) {
12575 if size > max_size {
12576 max_size = size;
12577 }
12578 } else {
12579 break 'oneof (::core::option::Option::<usize>::None);
12580 }
12581 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12582 ::micropb::const_map!(<CtrlMsg_Resp_OTAEnd as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12583 ::micropb::size::sizeof_len_record(size)
12584 }),
12585 |size| size + 2usize
12586 ) {
12587 if size > max_size {
12588 max_size = size;
12589 }
12590 } else {
12591 break 'oneof (::core::option::Option::<usize>::None);
12592 }
12593 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12594 ::micropb::const_map!(
12595 <CtrlMsg_Resp_SetWifiMaxTxPower as ::micropb::MessageEncode>::MAX_SIZE,
12596 |size| ::micropb::size::sizeof_len_record(size)
12597 ),
12598 |size| size + 2usize
12599 ) {
12600 if size > max_size {
12601 max_size = size;
12602 }
12603 } else {
12604 break 'oneof (::core::option::Option::<usize>::None);
12605 }
12606 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12607 ::micropb::const_map!(
12608 <CtrlMsg_Resp_GetWifiCurrTxPower as ::micropb::MessageEncode>::MAX_SIZE,
12609 |size| ::micropb::size::sizeof_len_record(size)
12610 ),
12611 |size| size + 2usize
12612 ) {
12613 if size > max_size {
12614 max_size = size;
12615 }
12616 } else {
12617 break 'oneof (::core::option::Option::<usize>::None);
12618 }
12619 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12620 ::micropb::const_map!(
12621 <CtrlMsg_Resp_ConfigHeartbeat as ::micropb::MessageEncode>::MAX_SIZE,
12622 |size| ::micropb::size::sizeof_len_record(size)
12623 ),
12624 |size| size + 2usize
12625 ) {
12626 if size > max_size {
12627 max_size = size;
12628 }
12629 } else {
12630 break 'oneof (::core::option::Option::<usize>::None);
12631 }
12632 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12633 ::micropb::const_map!(
12634 <CtrlMsg_Resp_EnableDisable as ::micropb::MessageEncode>::MAX_SIZE,
12635 |size| ::micropb::size::sizeof_len_record(size)
12636 ),
12637 |size| size + 2usize
12638 ) {
12639 if size > max_size {
12640 max_size = size;
12641 }
12642 } else {
12643 break 'oneof (::core::option::Option::<usize>::None);
12644 }
12645 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12646 ::micropb::const_map!(
12647 <CtrlMsg_Resp_GetFwVersion as ::micropb::MessageEncode>::MAX_SIZE,
12648 |size| ::micropb::size::sizeof_len_record(size)
12649 ),
12650 |size| size + 2usize
12651 ) {
12652 if size > max_size {
12653 max_size = size;
12654 }
12655 } else {
12656 break 'oneof (::core::option::Option::<usize>::None);
12657 }
12658 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12659 ::micropb::const_map!(
12660 <CtrlMsg_Resp_SetCountryCode as ::micropb::MessageEncode>::MAX_SIZE,
12661 |size| ::micropb::size::sizeof_len_record(size)
12662 ),
12663 |size| size + 2usize
12664 ) {
12665 if size > max_size {
12666 max_size = size;
12667 }
12668 } else {
12669 break 'oneof (::core::option::Option::<usize>::None);
12670 }
12671 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12672 ::micropb::const_map!(
12673 <CtrlMsg_Resp_GetCountryCode as ::micropb::MessageEncode>::MAX_SIZE,
12674 |size| ::micropb::size::sizeof_len_record(size)
12675 ),
12676 |size| size + 2usize
12677 ) {
12678 if size > max_size {
12679 max_size = size;
12680 }
12681 } else {
12682 break 'oneof (::core::option::Option::<usize>::None);
12683 }
12684 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12685 ::micropb::const_map!(
12686 <CtrlMsg_Resp_SetDhcpDnsStatus as ::micropb::MessageEncode>::MAX_SIZE,
12687 |size| ::micropb::size::sizeof_len_record(size)
12688 ),
12689 |size| size + 2usize
12690 ) {
12691 if size > max_size {
12692 max_size = size;
12693 }
12694 } else {
12695 break 'oneof (::core::option::Option::<usize>::None);
12696 }
12697 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12698 ::micropb::const_map!(
12699 <CtrlMsg_Resp_GetDhcpDnsStatus as ::micropb::MessageEncode>::MAX_SIZE,
12700 |size| ::micropb::size::sizeof_len_record(size)
12701 ),
12702 |size| size + 2usize
12703 ) {
12704 if size > max_size {
12705 max_size = size;
12706 }
12707 } else {
12708 break 'oneof (::core::option::Option::<usize>::None);
12709 }
12710 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12711 ::micropb::const_map!(
12712 <CtrlMsg_Resp_CustomRpcUnserialisedMsg as ::micropb::MessageEncode>::MAX_SIZE,
12713 |size| ::micropb::size::sizeof_len_record(size)
12714 ),
12715 |size| size + 2usize
12716 ) {
12717 if size > max_size {
12718 max_size = size;
12719 }
12720 } else {
12721 break 'oneof (::core::option::Option::<usize>::None);
12722 }
12723 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12724 ::micropb::const_map!(<CtrlMsg_Event_ESPInit as ::micropb::MessageEncode>::MAX_SIZE, |size| {
12725 ::micropb::size::sizeof_len_record(size)
12726 }),
12727 |size| size + 2usize
12728 ) {
12729 if size > max_size {
12730 max_size = size;
12731 }
12732 } else {
12733 break 'oneof (::core::option::Option::<usize>::None);
12734 }
12735 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12736 ::micropb::const_map!(
12737 <CtrlMsg_Event_Heartbeat as ::micropb::MessageEncode>::MAX_SIZE,
12738 |size| ::micropb::size::sizeof_len_record(size)
12739 ),
12740 |size| size + 2usize
12741 ) {
12742 if size > max_size {
12743 max_size = size;
12744 }
12745 } else {
12746 break 'oneof (::core::option::Option::<usize>::None);
12747 }
12748 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12749 ::micropb::const_map!(
12750 <CtrlMsg_Event_StationDisconnectFromAP as ::micropb::MessageEncode>::MAX_SIZE,
12751 |size| ::micropb::size::sizeof_len_record(size)
12752 ),
12753 |size| size + 2usize
12754 ) {
12755 if size > max_size {
12756 max_size = size;
12757 }
12758 } else {
12759 break 'oneof (::core::option::Option::<usize>::None);
12760 }
12761 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12762 ::micropb::const_map!(
12763 <CtrlMsg_Event_StationDisconnectFromESPSoftAP as ::micropb::MessageEncode>::MAX_SIZE,
12764 |size| ::micropb::size::sizeof_len_record(size)
12765 ),
12766 |size| size + 2usize
12767 ) {
12768 if size > max_size {
12769 max_size = size;
12770 }
12771 } else {
12772 break 'oneof (::core::option::Option::<usize>::None);
12773 }
12774 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12775 ::micropb::const_map!(
12776 <CtrlMsg_Event_StationConnectedToAP as ::micropb::MessageEncode>::MAX_SIZE,
12777 |size| ::micropb::size::sizeof_len_record(size)
12778 ),
12779 |size| size + 2usize
12780 ) {
12781 if size > max_size {
12782 max_size = size;
12783 }
12784 } else {
12785 break 'oneof (::core::option::Option::<usize>::None);
12786 }
12787 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12788 ::micropb::const_map!(
12789 <CtrlMsg_Event_StationConnectedToESPSoftAP as ::micropb::MessageEncode>::MAX_SIZE,
12790 |size| ::micropb::size::sizeof_len_record(size)
12791 ),
12792 |size| size + 2usize
12793 ) {
12794 if size > max_size {
12795 max_size = size;
12796 }
12797 } else {
12798 break 'oneof (::core::option::Option::<usize>::None);
12799 }
12800 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12801 ::micropb::const_map!(
12802 <CtrlMsg_Event_SetDhcpDnsStatus as ::micropb::MessageEncode>::MAX_SIZE,
12803 |size| ::micropb::size::sizeof_len_record(size)
12804 ),
12805 |size| size + 2usize
12806 ) {
12807 if size > max_size {
12808 max_size = size;
12809 }
12810 } else {
12811 break 'oneof (::core::option::Option::<usize>::None);
12812 }
12813 if let ::core::option::Option::Some(size) = ::micropb::const_map!(
12814 ::micropb::const_map!(
12815 <CtrlMsg_Event_CustomRpcUnserialisedMsg as ::micropb::MessageEncode>::MAX_SIZE,
12816 |size| ::micropb::size::sizeof_len_record(size)
12817 ),
12818 |size| size + 2usize
12819 ) {
12820 if size > max_size {
12821 max_size = size;
12822 }
12823 } else {
12824 break 'oneof (::core::option::Option::<usize>::None);
12825 }
12826 ::core::option::Option::Some(max_size)
12827 } {
12828 max_size += size;
12829 } else {
12830 break 'msg (::core::option::Option::<usize>::None);
12831 };
12832 ::core::option::Option::Some(max_size)
12833 };
12834 fn encode<IMPL_MICROPB_WRITE: ::micropb::PbWrite>(
12835 &self,
12836 encoder: &mut ::micropb::PbEncoder<IMPL_MICROPB_WRITE>,
12837 ) -> Result<(), IMPL_MICROPB_WRITE::Error> {
12838 use ::micropb::{FieldEncode, PbMap};
12839 {
12840 let val_ref = &self.r#msg_type;
12841 if val_ref.0 != 0 {
12842 encoder.encode_varint32(8u32)?;
12843 encoder.encode_int32(val_ref.0 as _)?;
12844 }
12845 }
12846 {
12847 let val_ref = &self.r#msg_id;
12848 if val_ref.0 != 0 {
12849 encoder.encode_varint32(16u32)?;
12850 encoder.encode_int32(val_ref.0 as _)?;
12851 }
12852 }
12853 {
12854 let val_ref = &self.r#uid;
12855 if *val_ref != 0 {
12856 encoder.encode_varint32(24u32)?;
12857 encoder.encode_int32(*val_ref as _)?;
12858 }
12859 }
12860 {
12861 let val_ref = &self.r#req_resp_type;
12862 if *val_ref != 0 {
12863 encoder.encode_varint32(32u32)?;
12864 encoder.encode_varint32(*val_ref as _)?;
12865 }
12866 }
12867 if let Some(oneof) = &self.r#payload {
12868 match &*oneof {
12869 CtrlMsg_::Payload::ReqGetMacAddress(val_ref) => {
12870 let val_ref = &*val_ref;
12871 encoder.encode_varint32(810u32)?;
12872 val_ref.encode_len_delimited(encoder)?;
12873 }
12874 CtrlMsg_::Payload::ReqSetMacAddress(val_ref) => {
12875 let val_ref = &*val_ref;
12876 encoder.encode_varint32(818u32)?;
12877 val_ref.encode_len_delimited(encoder)?;
12878 }
12879 CtrlMsg_::Payload::ReqGetWifiMode(val_ref) => {
12880 let val_ref = &*val_ref;
12881 encoder.encode_varint32(826u32)?;
12882 val_ref.encode_len_delimited(encoder)?;
12883 }
12884 CtrlMsg_::Payload::ReqSetWifiMode(val_ref) => {
12885 let val_ref = &*val_ref;
12886 encoder.encode_varint32(834u32)?;
12887 val_ref.encode_len_delimited(encoder)?;
12888 }
12889 CtrlMsg_::Payload::ReqScanApList(val_ref) => {
12890 let val_ref = &*val_ref;
12891 encoder.encode_varint32(842u32)?;
12892 val_ref.encode_len_delimited(encoder)?;
12893 }
12894 CtrlMsg_::Payload::ReqGetApConfig(val_ref) => {
12895 let val_ref = &*val_ref;
12896 encoder.encode_varint32(850u32)?;
12897 val_ref.encode_len_delimited(encoder)?;
12898 }
12899 CtrlMsg_::Payload::ReqConnectAp(val_ref) => {
12900 let val_ref = &*val_ref;
12901 encoder.encode_varint32(858u32)?;
12902 val_ref.encode_len_delimited(encoder)?;
12903 }
12904 CtrlMsg_::Payload::ReqDisconnectAp(val_ref) => {
12905 let val_ref = &*val_ref;
12906 encoder.encode_varint32(866u32)?;
12907 val_ref.encode_len_delimited(encoder)?;
12908 }
12909 CtrlMsg_::Payload::ReqGetSoftapConfig(val_ref) => {
12910 let val_ref = &*val_ref;
12911 encoder.encode_varint32(874u32)?;
12912 val_ref.encode_len_delimited(encoder)?;
12913 }
12914 CtrlMsg_::Payload::ReqSetSoftapVendorSpecificIe(val_ref) => {
12915 let val_ref = &*val_ref;
12916 encoder.encode_varint32(882u32)?;
12917 val_ref.encode_len_delimited(encoder)?;
12918 }
12919 CtrlMsg_::Payload::ReqStartSoftap(val_ref) => {
12920 let val_ref = &*val_ref;
12921 encoder.encode_varint32(890u32)?;
12922 val_ref.encode_len_delimited(encoder)?;
12923 }
12924 CtrlMsg_::Payload::ReqSoftapConnectedStasList(val_ref) => {
12925 let val_ref = &*val_ref;
12926 encoder.encode_varint32(898u32)?;
12927 val_ref.encode_len_delimited(encoder)?;
12928 }
12929 CtrlMsg_::Payload::ReqStopSoftap(val_ref) => {
12930 let val_ref = &*val_ref;
12931 encoder.encode_varint32(906u32)?;
12932 val_ref.encode_len_delimited(encoder)?;
12933 }
12934 CtrlMsg_::Payload::ReqSetPowerSaveMode(val_ref) => {
12935 let val_ref = &*val_ref;
12936 encoder.encode_varint32(914u32)?;
12937 val_ref.encode_len_delimited(encoder)?;
12938 }
12939 CtrlMsg_::Payload::ReqGetPowerSaveMode(val_ref) => {
12940 let val_ref = &*val_ref;
12941 encoder.encode_varint32(922u32)?;
12942 val_ref.encode_len_delimited(encoder)?;
12943 }
12944 CtrlMsg_::Payload::ReqOtaBegin(val_ref) => {
12945 let val_ref = &*val_ref;
12946 encoder.encode_varint32(930u32)?;
12947 val_ref.encode_len_delimited(encoder)?;
12948 }
12949 CtrlMsg_::Payload::ReqOtaWrite(val_ref) => {
12950 let val_ref = &*val_ref;
12951 encoder.encode_varint32(938u32)?;
12952 val_ref.encode_len_delimited(encoder)?;
12953 }
12954 CtrlMsg_::Payload::ReqOtaEnd(val_ref) => {
12955 let val_ref = &*val_ref;
12956 encoder.encode_varint32(946u32)?;
12957 val_ref.encode_len_delimited(encoder)?;
12958 }
12959 CtrlMsg_::Payload::ReqSetWifiMaxTxPower(val_ref) => {
12960 let val_ref = &*val_ref;
12961 encoder.encode_varint32(954u32)?;
12962 val_ref.encode_len_delimited(encoder)?;
12963 }
12964 CtrlMsg_::Payload::ReqGetWifiCurrTxPower(val_ref) => {
12965 let val_ref = &*val_ref;
12966 encoder.encode_varint32(962u32)?;
12967 val_ref.encode_len_delimited(encoder)?;
12968 }
12969 CtrlMsg_::Payload::ReqConfigHeartbeat(val_ref) => {
12970 let val_ref = &*val_ref;
12971 encoder.encode_varint32(970u32)?;
12972 val_ref.encode_len_delimited(encoder)?;
12973 }
12974 CtrlMsg_::Payload::ReqEnableDisableFeat(val_ref) => {
12975 let val_ref = &*val_ref;
12976 encoder.encode_varint32(978u32)?;
12977 val_ref.encode_len_delimited(encoder)?;
12978 }
12979 CtrlMsg_::Payload::ReqGetFwVersion(val_ref) => {
12980 let val_ref = &*val_ref;
12981 encoder.encode_varint32(986u32)?;
12982 val_ref.encode_len_delimited(encoder)?;
12983 }
12984 CtrlMsg_::Payload::ReqSetCountryCode(val_ref) => {
12985 let val_ref = &*val_ref;
12986 encoder.encode_varint32(994u32)?;
12987 val_ref.encode_len_delimited(encoder)?;
12988 }
12989 CtrlMsg_::Payload::ReqGetCountryCode(val_ref) => {
12990 let val_ref = &*val_ref;
12991 encoder.encode_varint32(1002u32)?;
12992 val_ref.encode_len_delimited(encoder)?;
12993 }
12994 CtrlMsg_::Payload::ReqSetDhcpDnsStatus(val_ref) => {
12995 let val_ref = &*val_ref;
12996 encoder.encode_varint32(1010u32)?;
12997 val_ref.encode_len_delimited(encoder)?;
12998 }
12999 CtrlMsg_::Payload::ReqGetDhcpDnsStatus(val_ref) => {
13000 let val_ref = &*val_ref;
13001 encoder.encode_varint32(1018u32)?;
13002 val_ref.encode_len_delimited(encoder)?;
13003 }
13004 CtrlMsg_::Payload::ReqCustomRpcUnserialisedMsg(val_ref) => {
13005 let val_ref = &*val_ref;
13006 encoder.encode_varint32(1026u32)?;
13007 val_ref.encode_len_delimited(encoder)?;
13008 }
13009 CtrlMsg_::Payload::RespGetMacAddress(val_ref) => {
13010 let val_ref = &*val_ref;
13011 encoder.encode_varint32(1610u32)?;
13012 val_ref.encode_len_delimited(encoder)?;
13013 }
13014 CtrlMsg_::Payload::RespSetMacAddress(val_ref) => {
13015 let val_ref = &*val_ref;
13016 encoder.encode_varint32(1618u32)?;
13017 val_ref.encode_len_delimited(encoder)?;
13018 }
13019 CtrlMsg_::Payload::RespGetWifiMode(val_ref) => {
13020 let val_ref = &*val_ref;
13021 encoder.encode_varint32(1626u32)?;
13022 val_ref.encode_len_delimited(encoder)?;
13023 }
13024 CtrlMsg_::Payload::RespSetWifiMode(val_ref) => {
13025 let val_ref = &*val_ref;
13026 encoder.encode_varint32(1634u32)?;
13027 val_ref.encode_len_delimited(encoder)?;
13028 }
13029 CtrlMsg_::Payload::RespScanApList(val_ref) => {
13030 let val_ref = &*val_ref;
13031 encoder.encode_varint32(1642u32)?;
13032 val_ref.encode_len_delimited(encoder)?;
13033 }
13034 CtrlMsg_::Payload::RespGetApConfig(val_ref) => {
13035 let val_ref = &*val_ref;
13036 encoder.encode_varint32(1650u32)?;
13037 val_ref.encode_len_delimited(encoder)?;
13038 }
13039 CtrlMsg_::Payload::RespConnectAp(val_ref) => {
13040 let val_ref = &*val_ref;
13041 encoder.encode_varint32(1658u32)?;
13042 val_ref.encode_len_delimited(encoder)?;
13043 }
13044 CtrlMsg_::Payload::RespDisconnectAp(val_ref) => {
13045 let val_ref = &*val_ref;
13046 encoder.encode_varint32(1666u32)?;
13047 val_ref.encode_len_delimited(encoder)?;
13048 }
13049 CtrlMsg_::Payload::RespGetSoftapConfig(val_ref) => {
13050 let val_ref = &*val_ref;
13051 encoder.encode_varint32(1674u32)?;
13052 val_ref.encode_len_delimited(encoder)?;
13053 }
13054 CtrlMsg_::Payload::RespSetSoftapVendorSpecificIe(val_ref) => {
13055 let val_ref = &*val_ref;
13056 encoder.encode_varint32(1682u32)?;
13057 val_ref.encode_len_delimited(encoder)?;
13058 }
13059 CtrlMsg_::Payload::RespStartSoftap(val_ref) => {
13060 let val_ref = &*val_ref;
13061 encoder.encode_varint32(1690u32)?;
13062 val_ref.encode_len_delimited(encoder)?;
13063 }
13064 CtrlMsg_::Payload::RespSoftapConnectedStasList(val_ref) => {
13065 let val_ref = &*val_ref;
13066 encoder.encode_varint32(1698u32)?;
13067 val_ref.encode_len_delimited(encoder)?;
13068 }
13069 CtrlMsg_::Payload::RespStopSoftap(val_ref) => {
13070 let val_ref = &*val_ref;
13071 encoder.encode_varint32(1706u32)?;
13072 val_ref.encode_len_delimited(encoder)?;
13073 }
13074 CtrlMsg_::Payload::RespSetPowerSaveMode(val_ref) => {
13075 let val_ref = &*val_ref;
13076 encoder.encode_varint32(1714u32)?;
13077 val_ref.encode_len_delimited(encoder)?;
13078 }
13079 CtrlMsg_::Payload::RespGetPowerSaveMode(val_ref) => {
13080 let val_ref = &*val_ref;
13081 encoder.encode_varint32(1722u32)?;
13082 val_ref.encode_len_delimited(encoder)?;
13083 }
13084 CtrlMsg_::Payload::RespOtaBegin(val_ref) => {
13085 let val_ref = &*val_ref;
13086 encoder.encode_varint32(1730u32)?;
13087 val_ref.encode_len_delimited(encoder)?;
13088 }
13089 CtrlMsg_::Payload::RespOtaWrite(val_ref) => {
13090 let val_ref = &*val_ref;
13091 encoder.encode_varint32(1738u32)?;
13092 val_ref.encode_len_delimited(encoder)?;
13093 }
13094 CtrlMsg_::Payload::RespOtaEnd(val_ref) => {
13095 let val_ref = &*val_ref;
13096 encoder.encode_varint32(1746u32)?;
13097 val_ref.encode_len_delimited(encoder)?;
13098 }
13099 CtrlMsg_::Payload::RespSetWifiMaxTxPower(val_ref) => {
13100 let val_ref = &*val_ref;
13101 encoder.encode_varint32(1754u32)?;
13102 val_ref.encode_len_delimited(encoder)?;
13103 }
13104 CtrlMsg_::Payload::RespGetWifiCurrTxPower(val_ref) => {
13105 let val_ref = &*val_ref;
13106 encoder.encode_varint32(1762u32)?;
13107 val_ref.encode_len_delimited(encoder)?;
13108 }
13109 CtrlMsg_::Payload::RespConfigHeartbeat(val_ref) => {
13110 let val_ref = &*val_ref;
13111 encoder.encode_varint32(1770u32)?;
13112 val_ref.encode_len_delimited(encoder)?;
13113 }
13114 CtrlMsg_::Payload::RespEnableDisableFeat(val_ref) => {
13115 let val_ref = &*val_ref;
13116 encoder.encode_varint32(1778u32)?;
13117 val_ref.encode_len_delimited(encoder)?;
13118 }
13119 CtrlMsg_::Payload::RespGetFwVersion(val_ref) => {
13120 let val_ref = &*val_ref;
13121 encoder.encode_varint32(1786u32)?;
13122 val_ref.encode_len_delimited(encoder)?;
13123 }
13124 CtrlMsg_::Payload::RespSetCountryCode(val_ref) => {
13125 let val_ref = &*val_ref;
13126 encoder.encode_varint32(1794u32)?;
13127 val_ref.encode_len_delimited(encoder)?;
13128 }
13129 CtrlMsg_::Payload::RespGetCountryCode(val_ref) => {
13130 let val_ref = &*val_ref;
13131 encoder.encode_varint32(1802u32)?;
13132 val_ref.encode_len_delimited(encoder)?;
13133 }
13134 CtrlMsg_::Payload::RespSetDhcpDnsStatus(val_ref) => {
13135 let val_ref = &*val_ref;
13136 encoder.encode_varint32(1810u32)?;
13137 val_ref.encode_len_delimited(encoder)?;
13138 }
13139 CtrlMsg_::Payload::RespGetDhcpDnsStatus(val_ref) => {
13140 let val_ref = &*val_ref;
13141 encoder.encode_varint32(1818u32)?;
13142 val_ref.encode_len_delimited(encoder)?;
13143 }
13144 CtrlMsg_::Payload::RespCustomRpcUnserialisedMsg(val_ref) => {
13145 let val_ref = &*val_ref;
13146 encoder.encode_varint32(1826u32)?;
13147 val_ref.encode_len_delimited(encoder)?;
13148 }
13149 CtrlMsg_::Payload::EventEspInit(val_ref) => {
13150 let val_ref = &*val_ref;
13151 encoder.encode_varint32(2410u32)?;
13152 val_ref.encode_len_delimited(encoder)?;
13153 }
13154 CtrlMsg_::Payload::EventHeartbeat(val_ref) => {
13155 let val_ref = &*val_ref;
13156 encoder.encode_varint32(2418u32)?;
13157 val_ref.encode_len_delimited(encoder)?;
13158 }
13159 CtrlMsg_::Payload::EventStationDisconnectFromAp(val_ref) => {
13160 let val_ref = &*val_ref;
13161 encoder.encode_varint32(2426u32)?;
13162 val_ref.encode_len_delimited(encoder)?;
13163 }
13164 CtrlMsg_::Payload::EventStationDisconnectFromEspSoftAp(val_ref) => {
13165 let val_ref = &*val_ref;
13166 encoder.encode_varint32(2434u32)?;
13167 val_ref.encode_len_delimited(encoder)?;
13168 }
13169 CtrlMsg_::Payload::EventStationConnectedToAp(val_ref) => {
13170 let val_ref = &*val_ref;
13171 encoder.encode_varint32(2442u32)?;
13172 val_ref.encode_len_delimited(encoder)?;
13173 }
13174 CtrlMsg_::Payload::EventStationConnectedToEspSoftAp(val_ref) => {
13175 let val_ref = &*val_ref;
13176 encoder.encode_varint32(2450u32)?;
13177 val_ref.encode_len_delimited(encoder)?;
13178 }
13179 CtrlMsg_::Payload::EventSetDhcpDnsStatus(val_ref) => {
13180 let val_ref = &*val_ref;
13181 encoder.encode_varint32(2458u32)?;
13182 val_ref.encode_len_delimited(encoder)?;
13183 }
13184 CtrlMsg_::Payload::EventCustomRpcUnserialisedMsg(val_ref) => {
13185 let val_ref = &*val_ref;
13186 encoder.encode_varint32(2466u32)?;
13187 val_ref.encode_len_delimited(encoder)?;
13188 }
13189 }
13190 }
13191 Ok(())
13192 }
13193 fn compute_size(&self) -> usize {
13194 use ::micropb::{FieldEncode, PbMap};
13195 let mut size = 0;
13196 {
13197 let val_ref = &self.r#msg_type;
13198 if val_ref.0 != 0 {
13199 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
13200 }
13201 }
13202 {
13203 let val_ref = &self.r#msg_id;
13204 if val_ref.0 != 0 {
13205 size += 1usize + ::micropb::size::sizeof_int32(val_ref.0 as _);
13206 }
13207 }
13208 {
13209 let val_ref = &self.r#uid;
13210 if *val_ref != 0 {
13211 size += 1usize + ::micropb::size::sizeof_int32(*val_ref as _);
13212 }
13213 }
13214 {
13215 let val_ref = &self.r#req_resp_type;
13216 if *val_ref != 0 {
13217 size += 1usize + ::micropb::size::sizeof_varint32(*val_ref as _);
13218 }
13219 }
13220 if let Some(oneof) = &self.r#payload {
13221 match &*oneof {
13222 CtrlMsg_::Payload::ReqGetMacAddress(val_ref) => {
13223 let val_ref = &*val_ref;
13224 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13225 }
13226 CtrlMsg_::Payload::ReqSetMacAddress(val_ref) => {
13227 let val_ref = &*val_ref;
13228 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13229 }
13230 CtrlMsg_::Payload::ReqGetWifiMode(val_ref) => {
13231 let val_ref = &*val_ref;
13232 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13233 }
13234 CtrlMsg_::Payload::ReqSetWifiMode(val_ref) => {
13235 let val_ref = &*val_ref;
13236 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13237 }
13238 CtrlMsg_::Payload::ReqScanApList(val_ref) => {
13239 let val_ref = &*val_ref;
13240 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13241 }
13242 CtrlMsg_::Payload::ReqGetApConfig(val_ref) => {
13243 let val_ref = &*val_ref;
13244 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13245 }
13246 CtrlMsg_::Payload::ReqConnectAp(val_ref) => {
13247 let val_ref = &*val_ref;
13248 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13249 }
13250 CtrlMsg_::Payload::ReqDisconnectAp(val_ref) => {
13251 let val_ref = &*val_ref;
13252 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13253 }
13254 CtrlMsg_::Payload::ReqGetSoftapConfig(val_ref) => {
13255 let val_ref = &*val_ref;
13256 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13257 }
13258 CtrlMsg_::Payload::ReqSetSoftapVendorSpecificIe(val_ref) => {
13259 let val_ref = &*val_ref;
13260 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13261 }
13262 CtrlMsg_::Payload::ReqStartSoftap(val_ref) => {
13263 let val_ref = &*val_ref;
13264 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13265 }
13266 CtrlMsg_::Payload::ReqSoftapConnectedStasList(val_ref) => {
13267 let val_ref = &*val_ref;
13268 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13269 }
13270 CtrlMsg_::Payload::ReqStopSoftap(val_ref) => {
13271 let val_ref = &*val_ref;
13272 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13273 }
13274 CtrlMsg_::Payload::ReqSetPowerSaveMode(val_ref) => {
13275 let val_ref = &*val_ref;
13276 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13277 }
13278 CtrlMsg_::Payload::ReqGetPowerSaveMode(val_ref) => {
13279 let val_ref = &*val_ref;
13280 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13281 }
13282 CtrlMsg_::Payload::ReqOtaBegin(val_ref) => {
13283 let val_ref = &*val_ref;
13284 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13285 }
13286 CtrlMsg_::Payload::ReqOtaWrite(val_ref) => {
13287 let val_ref = &*val_ref;
13288 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13289 }
13290 CtrlMsg_::Payload::ReqOtaEnd(val_ref) => {
13291 let val_ref = &*val_ref;
13292 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13293 }
13294 CtrlMsg_::Payload::ReqSetWifiMaxTxPower(val_ref) => {
13295 let val_ref = &*val_ref;
13296 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13297 }
13298 CtrlMsg_::Payload::ReqGetWifiCurrTxPower(val_ref) => {
13299 let val_ref = &*val_ref;
13300 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13301 }
13302 CtrlMsg_::Payload::ReqConfigHeartbeat(val_ref) => {
13303 let val_ref = &*val_ref;
13304 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13305 }
13306 CtrlMsg_::Payload::ReqEnableDisableFeat(val_ref) => {
13307 let val_ref = &*val_ref;
13308 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13309 }
13310 CtrlMsg_::Payload::ReqGetFwVersion(val_ref) => {
13311 let val_ref = &*val_ref;
13312 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13313 }
13314 CtrlMsg_::Payload::ReqSetCountryCode(val_ref) => {
13315 let val_ref = &*val_ref;
13316 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13317 }
13318 CtrlMsg_::Payload::ReqGetCountryCode(val_ref) => {
13319 let val_ref = &*val_ref;
13320 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13321 }
13322 CtrlMsg_::Payload::ReqSetDhcpDnsStatus(val_ref) => {
13323 let val_ref = &*val_ref;
13324 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13325 }
13326 CtrlMsg_::Payload::ReqGetDhcpDnsStatus(val_ref) => {
13327 let val_ref = &*val_ref;
13328 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13329 }
13330 CtrlMsg_::Payload::ReqCustomRpcUnserialisedMsg(val_ref) => {
13331 let val_ref = &*val_ref;
13332 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13333 }
13334 CtrlMsg_::Payload::RespGetMacAddress(val_ref) => {
13335 let val_ref = &*val_ref;
13336 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13337 }
13338 CtrlMsg_::Payload::RespSetMacAddress(val_ref) => {
13339 let val_ref = &*val_ref;
13340 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13341 }
13342 CtrlMsg_::Payload::RespGetWifiMode(val_ref) => {
13343 let val_ref = &*val_ref;
13344 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13345 }
13346 CtrlMsg_::Payload::RespSetWifiMode(val_ref) => {
13347 let val_ref = &*val_ref;
13348 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13349 }
13350 CtrlMsg_::Payload::RespScanApList(val_ref) => {
13351 let val_ref = &*val_ref;
13352 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13353 }
13354 CtrlMsg_::Payload::RespGetApConfig(val_ref) => {
13355 let val_ref = &*val_ref;
13356 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13357 }
13358 CtrlMsg_::Payload::RespConnectAp(val_ref) => {
13359 let val_ref = &*val_ref;
13360 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13361 }
13362 CtrlMsg_::Payload::RespDisconnectAp(val_ref) => {
13363 let val_ref = &*val_ref;
13364 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13365 }
13366 CtrlMsg_::Payload::RespGetSoftapConfig(val_ref) => {
13367 let val_ref = &*val_ref;
13368 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13369 }
13370 CtrlMsg_::Payload::RespSetSoftapVendorSpecificIe(val_ref) => {
13371 let val_ref = &*val_ref;
13372 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13373 }
13374 CtrlMsg_::Payload::RespStartSoftap(val_ref) => {
13375 let val_ref = &*val_ref;
13376 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13377 }
13378 CtrlMsg_::Payload::RespSoftapConnectedStasList(val_ref) => {
13379 let val_ref = &*val_ref;
13380 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13381 }
13382 CtrlMsg_::Payload::RespStopSoftap(val_ref) => {
13383 let val_ref = &*val_ref;
13384 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13385 }
13386 CtrlMsg_::Payload::RespSetPowerSaveMode(val_ref) => {
13387 let val_ref = &*val_ref;
13388 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13389 }
13390 CtrlMsg_::Payload::RespGetPowerSaveMode(val_ref) => {
13391 let val_ref = &*val_ref;
13392 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13393 }
13394 CtrlMsg_::Payload::RespOtaBegin(val_ref) => {
13395 let val_ref = &*val_ref;
13396 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13397 }
13398 CtrlMsg_::Payload::RespOtaWrite(val_ref) => {
13399 let val_ref = &*val_ref;
13400 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13401 }
13402 CtrlMsg_::Payload::RespOtaEnd(val_ref) => {
13403 let val_ref = &*val_ref;
13404 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13405 }
13406 CtrlMsg_::Payload::RespSetWifiMaxTxPower(val_ref) => {
13407 let val_ref = &*val_ref;
13408 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13409 }
13410 CtrlMsg_::Payload::RespGetWifiCurrTxPower(val_ref) => {
13411 let val_ref = &*val_ref;
13412 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13413 }
13414 CtrlMsg_::Payload::RespConfigHeartbeat(val_ref) => {
13415 let val_ref = &*val_ref;
13416 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13417 }
13418 CtrlMsg_::Payload::RespEnableDisableFeat(val_ref) => {
13419 let val_ref = &*val_ref;
13420 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13421 }
13422 CtrlMsg_::Payload::RespGetFwVersion(val_ref) => {
13423 let val_ref = &*val_ref;
13424 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13425 }
13426 CtrlMsg_::Payload::RespSetCountryCode(val_ref) => {
13427 let val_ref = &*val_ref;
13428 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13429 }
13430 CtrlMsg_::Payload::RespGetCountryCode(val_ref) => {
13431 let val_ref = &*val_ref;
13432 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13433 }
13434 CtrlMsg_::Payload::RespSetDhcpDnsStatus(val_ref) => {
13435 let val_ref = &*val_ref;
13436 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13437 }
13438 CtrlMsg_::Payload::RespGetDhcpDnsStatus(val_ref) => {
13439 let val_ref = &*val_ref;
13440 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13441 }
13442 CtrlMsg_::Payload::RespCustomRpcUnserialisedMsg(val_ref) => {
13443 let val_ref = &*val_ref;
13444 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13445 }
13446 CtrlMsg_::Payload::EventEspInit(val_ref) => {
13447 let val_ref = &*val_ref;
13448 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13449 }
13450 CtrlMsg_::Payload::EventHeartbeat(val_ref) => {
13451 let val_ref = &*val_ref;
13452 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13453 }
13454 CtrlMsg_::Payload::EventStationDisconnectFromAp(val_ref) => {
13455 let val_ref = &*val_ref;
13456 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13457 }
13458 CtrlMsg_::Payload::EventStationDisconnectFromEspSoftAp(val_ref) => {
13459 let val_ref = &*val_ref;
13460 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13461 }
13462 CtrlMsg_::Payload::EventStationConnectedToAp(val_ref) => {
13463 let val_ref = &*val_ref;
13464 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13465 }
13466 CtrlMsg_::Payload::EventStationConnectedToEspSoftAp(val_ref) => {
13467 let val_ref = &*val_ref;
13468 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13469 }
13470 CtrlMsg_::Payload::EventSetDhcpDnsStatus(val_ref) => {
13471 let val_ref = &*val_ref;
13472 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13473 }
13474 CtrlMsg_::Payload::EventCustomRpcUnserialisedMsg(val_ref) => {
13475 let val_ref = &*val_ref;
13476 size += 2usize + ::micropb::size::sizeof_len_record(val_ref.compute_size());
13477 }
13478 }
13479 }
13480 size
13481 }
13482}
13483#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13484#[repr(transparent)]
13485#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13486pub struct Ctrl_VendorIEType(pub i32);
13487impl Ctrl_VendorIEType {
13488 pub const _MAX_SIZE: usize = 10usize;
13489 pub const Beacon: Self = Self(0);
13490 pub const ProbeReq: Self = Self(1);
13491 pub const ProbeResp: Self = Self(2);
13492 pub const AssocReq: Self = Self(3);
13493 pub const AssocResp: Self = Self(4);
13494}
13495impl core::default::Default for Ctrl_VendorIEType {
13496 fn default() -> Self {
13497 Self(0)
13498 }
13499}
13500impl core::convert::From<i32> for Ctrl_VendorIEType {
13501 fn from(val: i32) -> Self {
13502 Self(val)
13503 }
13504}
13505#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13506#[repr(transparent)]
13507#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13508pub struct Ctrl_VendorIEID(pub i32);
13509impl Ctrl_VendorIEID {
13510 pub const _MAX_SIZE: usize = 10usize;
13511 pub const Id0: Self = Self(0);
13512 pub const Id1: Self = Self(1);
13513}
13514impl core::default::Default for Ctrl_VendorIEID {
13515 fn default() -> Self {
13516 Self(0)
13517 }
13518}
13519impl core::convert::From<i32> for Ctrl_VendorIEID {
13520 fn from(val: i32) -> Self {
13521 Self(val)
13522 }
13523}
13524#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13525#[repr(transparent)]
13526#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13527pub struct Ctrl_WifiMode(pub i32);
13528impl Ctrl_WifiMode {
13529 pub const _MAX_SIZE: usize = 10usize;
13530 pub const None: Self = Self(0);
13531 pub const Sta: Self = Self(1);
13532 pub const Ap: Self = Self(2);
13533 pub const Apsta: Self = Self(3);
13534}
13535impl core::default::Default for Ctrl_WifiMode {
13536 fn default() -> Self {
13537 Self(0)
13538 }
13539}
13540impl core::convert::From<i32> for Ctrl_WifiMode {
13541 fn from(val: i32) -> Self {
13542 Self(val)
13543 }
13544}
13545#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13546#[repr(transparent)]
13547#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13548pub struct Ctrl_WifiBw(pub i32);
13549impl Ctrl_WifiBw {
13550 pub const _MAX_SIZE: usize = 10usize;
13551 pub const BwInvalid: Self = Self(0);
13552 pub const Ht20: Self = Self(1);
13553 pub const Ht40: Self = Self(2);
13554}
13555impl core::default::Default for Ctrl_WifiBw {
13556 fn default() -> Self {
13557 Self(0)
13558 }
13559}
13560impl core::convert::From<i32> for Ctrl_WifiBw {
13561 fn from(val: i32) -> Self {
13562 Self(val)
13563 }
13564}
13565#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13566#[repr(transparent)]
13567#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13568pub struct Ctrl_WifiPowerSave(pub i32);
13569impl Ctrl_WifiPowerSave {
13570 pub const _MAX_SIZE: usize = 10usize;
13571 pub const NoPs: Self = Self(0);
13572 pub const MinModem: Self = Self(1);
13573 pub const MaxModem: Self = Self(2);
13574 pub const PsInvalid: Self = Self(3);
13575}
13576impl core::default::Default for Ctrl_WifiPowerSave {
13577 fn default() -> Self {
13578 Self(0)
13579 }
13580}
13581impl core::convert::From<i32> for Ctrl_WifiPowerSave {
13582 fn from(val: i32) -> Self {
13583 Self(val)
13584 }
13585}
13586#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13587#[repr(transparent)]
13588#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13589pub struct Ctrl_WifiSecProt(pub i32);
13590impl Ctrl_WifiSecProt {
13591 pub const _MAX_SIZE: usize = 10usize;
13592 pub const Open: Self = Self(0);
13593 pub const Wep: Self = Self(1);
13594 pub const WpaPsk: Self = Self(2);
13595 pub const Wpa2Psk: Self = Self(3);
13596 pub const WpaWpa2Psk: Self = Self(4);
13597 pub const Wpa2Enterprise: Self = Self(5);
13598 pub const Wpa3Psk: Self = Self(6);
13599 pub const Wpa2Wpa3Psk: Self = Self(7);
13600}
13601impl core::default::Default for Ctrl_WifiSecProt {
13602 fn default() -> Self {
13603 Self(0)
13604 }
13605}
13606impl core::convert::From<i32> for Ctrl_WifiSecProt {
13607 fn from(val: i32) -> Self {
13608 Self(val)
13609 }
13610}
13611#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13612#[repr(transparent)]
13613#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13614pub struct Ctrl_Status(pub i32);
13615impl Ctrl_Status {
13616 pub const _MAX_SIZE: usize = 10usize;
13617 pub const Connected: Self = Self(0);
13618 pub const NotConnected: Self = Self(1);
13619 pub const NoApFound: Self = Self(2);
13620 pub const ConnectionFail: Self = Self(3);
13621 pub const InvalidArgument: Self = Self(4);
13622 pub const OutOfRange: Self = Self(5);
13623}
13624impl core::default::Default for Ctrl_Status {
13625 fn default() -> Self {
13626 Self(0)
13627 }
13628}
13629impl core::convert::From<i32> for Ctrl_Status {
13630 fn from(val: i32) -> Self {
13631 Self(val)
13632 }
13633}
13634#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13635#[repr(transparent)]
13636#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13637pub struct CtrlMsgType(pub i32);
13638impl CtrlMsgType {
13639 pub const _MAX_SIZE: usize = 10usize;
13640 pub const MsgTypeInvalid: Self = Self(0);
13641 pub const Req: Self = Self(1);
13642 pub const Resp: Self = Self(2);
13643 pub const Event: Self = Self(3);
13644 pub const MsgTypeMax: Self = Self(4);
13645}
13646impl core::default::Default for CtrlMsgType {
13647 fn default() -> Self {
13648 Self(0)
13649 }
13650}
13651impl core::convert::From<i32> for CtrlMsgType {
13652 fn from(val: i32) -> Self {
13653 Self(val)
13654 }
13655}
13656#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13657#[repr(transparent)]
13658#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13659pub struct CtrlMsgId(pub i32);
13660impl CtrlMsgId {
13661 pub const _MAX_SIZE: usize = 10usize;
13662 pub const MsgIdInvalid: Self = Self(0);
13663 pub const ReqBase: Self = Self(100);
13664 pub const ReqGetMacAddress: Self = Self(101);
13665 pub const ReqSetMacAddress: Self = Self(102);
13666 pub const ReqGetWifiMode: Self = Self(103);
13667 pub const ReqSetWifiMode: Self = Self(104);
13668 pub const ReqGetApScanList: Self = Self(105);
13669 pub const ReqGetApConfig: Self = Self(106);
13670 pub const ReqConnectAp: Self = Self(107);
13671 pub const ReqDisconnectAp: Self = Self(108);
13672 pub const ReqGetSoftApConfig: Self = Self(109);
13673 pub const ReqSetSoftApVendorSpecificIe: Self = Self(110);
13674 pub const ReqStartSoftAp: Self = Self(111);
13675 pub const ReqGetSoftApConnectedStaList: Self = Self(112);
13676 pub const ReqStopSoftAp: Self = Self(113);
13677 pub const ReqSetPowerSaveMode: Self = Self(114);
13678 pub const ReqGetPowerSaveMode: Self = Self(115);
13679 pub const ReqOtaBegin: Self = Self(116);
13680 pub const ReqOtaWrite: Self = Self(117);
13681 pub const ReqOtaEnd: Self = Self(118);
13682 pub const ReqSetWifiMaxTxPower: Self = Self(119);
13683 pub const ReqGetWifiCurrTxPower: Self = Self(120);
13684 pub const ReqConfigHeartbeat: Self = Self(121);
13685 pub const ReqEnableDisable: Self = Self(122);
13686 pub const ReqGetFwVersion: Self = Self(123);
13687 pub const ReqSetCountryCode: Self = Self(124);
13688 pub const ReqGetCountryCode: Self = Self(125);
13689 pub const ReqSetDhcpDnsStatus: Self = Self(126);
13690 pub const ReqGetDhcpDnsStatus: Self = Self(127);
13691 pub const ReqCustomRpcUnserialisedMsg: Self = Self(128);
13692 pub const ReqMax: Self = Self(129);
13693 pub const RespBase: Self = Self(200);
13694 pub const RespGetMacAddress: Self = Self(201);
13695 pub const RespSetMacAddress: Self = Self(202);
13696 pub const RespGetWifiMode: Self = Self(203);
13697 pub const RespSetWifiMode: Self = Self(204);
13698 pub const RespGetApScanList: Self = Self(205);
13699 pub const RespGetApConfig: Self = Self(206);
13700 pub const RespConnectAp: Self = Self(207);
13701 pub const RespDisconnectAp: Self = Self(208);
13702 pub const RespGetSoftApConfig: Self = Self(209);
13703 pub const RespSetSoftApVendorSpecificIe: Self = Self(210);
13704 pub const RespStartSoftAp: Self = Self(211);
13705 pub const RespGetSoftApConnectedStaList: Self = Self(212);
13706 pub const RespStopSoftAp: Self = Self(213);
13707 pub const RespSetPowerSaveMode: Self = Self(214);
13708 pub const RespGetPowerSaveMode: Self = Self(215);
13709 pub const RespOtaBegin: Self = Self(216);
13710 pub const RespOtaWrite: Self = Self(217);
13711 pub const RespOtaEnd: Self = Self(218);
13712 pub const RespSetWifiMaxTxPower: Self = Self(219);
13713 pub const RespGetWifiCurrTxPower: Self = Self(220);
13714 pub const RespConfigHeartbeat: Self = Self(221);
13715 pub const RespEnableDisable: Self = Self(222);
13716 pub const RespGetFwVersion: Self = Self(223);
13717 pub const RespSetCountryCode: Self = Self(224);
13718 pub const RespGetCountryCode: Self = Self(225);
13719 pub const RespSetDhcpDnsStatus: Self = Self(226);
13720 pub const RespGetDhcpDnsStatus: Self = Self(227);
13721 pub const RespCustomRpcUnserialisedMsg: Self = Self(228);
13722 pub const RespMax: Self = Self(229);
13723 pub const EventBase: Self = Self(300);
13724 pub const EventEspInit: Self = Self(301);
13725 pub const EventHeartbeat: Self = Self(302);
13726 pub const EventStationDisconnectFromAp: Self = Self(303);
13727 pub const EventStationDisconnectFromEspSoftAp: Self = Self(304);
13728 pub const EventStationConnectedToAp: Self = Self(305);
13729 pub const EventStationConnectedToEspSoftAp: Self = Self(306);
13730 pub const EventSetDhcpDnsStatus: Self = Self(307);
13731 pub const EventCustomRpcUnserialisedMsg: Self = Self(308);
13732 pub const EventMax: Self = Self(309);
13733}
13734impl core::default::Default for CtrlMsgId {
13735 fn default() -> Self {
13736 Self(0)
13737 }
13738}
13739impl core::convert::From<i32> for CtrlMsgId {
13740 fn from(val: i32) -> Self {
13741 Self(val)
13742 }
13743}
13744#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13745#[repr(transparent)]
13746#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13747pub struct HostedFeature(pub i32);
13748impl HostedFeature {
13749 pub const _MAX_SIZE: usize = 10usize;
13750 pub const HostedInvalidFeature: Self = Self(0);
13751 pub const HostedWifi: Self = Self(1);
13752 pub const HostedBluetooth: Self = Self(2);
13753 pub const HostedIsNetworkSplitOn: Self = Self(3);
13754}
13755impl core::default::Default for HostedFeature {
13756 fn default() -> Self {
13757 Self(0)
13758 }
13759}
13760impl core::convert::From<i32> for HostedFeature {
13761 fn from(val: i32) -> Self {
13762 Self(val)
13763 }
656} 13764}
diff --git a/embassy-net-nrf91/CHANGELOG.md b/embassy-net-nrf91/CHANGELOG.md
index 52cbf5ef3..11974ac04 100644
--- a/embassy-net-nrf91/CHANGELOG.md
+++ b/embassy-net-nrf91/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- changed: updated to nrf-pac with nrf52/nrf53/nrf91 register layout more similar to nrf54
12
11## 0.1.1 - 2025-08-14 13## 0.1.1 - 2025-08-14
12 14
13- First release with changelog. 15- First release with changelog.
diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml
index ecb10246a..75b7aeeb2 100644
--- a/embassy-net-nrf91/Cargo.toml
+++ b/embassy-net-nrf91/Cargo.toml
@@ -18,7 +18,7 @@ log = ["dep:log"]
18defmt = { version = "1.0.1", optional = true } 18defmt = { version = "1.0.1", optional = true }
19log = { version = "0.4.14", optional = true } 19log = { version = "0.4.14", optional = true }
20 20
21nrf-pac = "0.1.0" 21nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "58198c23bce72edc10b4e1656d1b54441fc74e7c" }
22cortex-m = "0.7.7" 22cortex-m = "0.7.7"
23 23
24embassy-time = { version = "0.5.0", path = "../embassy-time" } 24embassy-time = { version = "0.5.0", path = "../embassy-time" }
diff --git a/embassy-net/CHANGELOG.md b/embassy-net/CHANGELOG.md
index 1ae4f2a68..40f720d0d 100644
--- a/embassy-net/CHANGELOG.md
+++ b/embassy-net/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- tcp: Add `set_nagle_enabled()` to control TcpSocket nagle algorithm.
12
11## 0.7.1 - 2025-08-26 13## 0.7.1 - 2025-08-26
12 14
13No unreleased changes yet... Quick, go send a PR! 15No unreleased changes yet... Quick, go send a PR!
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index 6792c5526..b4db7b88c 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -373,6 +373,20 @@ impl<'a> TcpSocket<'a> {
373 self.io.with_mut(|s, _| s.set_hop_limit(hop_limit)) 373 self.io.with_mut(|s, _| s.set_hop_limit(hop_limit))
374 } 374 }
375 375
376 /// Enable or disable Nagles's algorithm.
377 ///
378 /// By default, Nagle's algorithm is enabled.
379 /// When enabled, Nagle’s Algorithm prevents sending segments smaller
380 /// than MSS if there is data in flight (sent but not acknowledged).
381 /// In other words, it ensures at most only one segment smaller than
382 /// MSS is in flight at a time.
383 /// It ensures better network utilization by preventing sending many
384 /// very small packets, at the cost of increased latency in some
385 /// situations, particularly when the remote peer has ACK delay enabled.
386 pub fn set_nagle_enabled(&mut self, enabled: bool) {
387 self.io.with_mut(|s, _| s.set_nagle_enabled(enabled))
388 }
389
376 /// Get the local endpoint of the socket. 390 /// Get the local endpoint of the socket.
377 /// 391 ///
378 /// Returns `None` if the socket is not bound (listening) or not connected. 392 /// Returns `None` if the socket is not bound (listening) or not connected.
diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md
index 0244dedab..72ecb116a 100644
--- a/embassy-nrf/CHANGELOG.md
+++ b/embassy-nrf/CHANGELOG.md
@@ -7,7 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10
11- added: Add basic RTC support for nRF54L
10- changed: apply trimming values from FICR.TRIMCNF on nrf53/54l 12- changed: apply trimming values from FICR.TRIMCNF on nrf53/54l
13- changed: do not panic on BufferedUarte overrun
14- added: allow direct access to the input pin of `gpiote::InputChannel`
15- bugfix: use DETECTMODE_SEC in GPIOTE in secure mode
16- added: allow configuring the idle state of GPIO pins connected to PWM channels
17- changed: allow configuring the PWM peripheral in the constructor of `SimplePwm`
18- changed: support setting duty cycles with inverted polarity in `SimplePwm`
19- added: support setting the duty cycles of all channels at once in `SimplePwm`
20- changed: updated to nrf-pac with nrf52/nrf53/nrf91 register layout more similar to nrf54
21- added: support for nrf54l peripherals: uart, gpiote, twim, twis, spim, spis, dppi, pwm, saadc, cracen
22- added: support for changing nrf54l clock speed
23- bugfix: Do not write to UICR from non-secure code on nrf53
24- bugfix: Add delay to uart init anomaly fix
25- changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned
11 26
12## 0.8.0 - 2025-09-30 27## 0.8.0 - 2025-09-30
13 28
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 17ffaf439..08f4b280b 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -80,6 +80,8 @@ unstable-pac = []
80gpiote = [] 80gpiote = []
81 81
82## Use RTC1 as the time driver for `embassy-time`, with a tick rate of 32.768khz 82## Use RTC1 as the time driver for `embassy-time`, with a tick rate of 32.768khz
83##
84## Note: For nRF54L, it's actually RTC30
83time-driver-rtc1 = ["_time-driver"] 85time-driver-rtc1 = ["_time-driver"]
84 86
85## Enable embassy-net 802.15.4 driver 87## Enable embassy-net 802.15.4 driver
@@ -102,17 +104,17 @@ qspi-multiwrite-flash = []
102 104
103#! ### Chip selection features 105#! ### Chip selection features
104## nRF51 106## nRF51
105nrf51 = ["nrf-pac/nrf51", "_nrf51"] 107nrf51 = ["nrf-pac/nrf51", "_nrf51", "_spi-v1"]
106## nRF52805 108## nRF52805
107nrf52805 = ["nrf-pac/nrf52805", "_nrf52"] 109nrf52805 = ["nrf-pac/nrf52805", "_nrf52", "_spi-v1"]
108## nRF52810 110## nRF52810
109nrf52810 = ["nrf-pac/nrf52810", "_nrf52"] 111nrf52810 = ["nrf-pac/nrf52810", "_nrf52", "_spi-v1"]
110## nRF52811 112## nRF52811
111nrf52811 = ["nrf-pac/nrf52811", "_nrf52"] 113nrf52811 = ["nrf-pac/nrf52811", "_nrf52", "_spi-v1"]
112## nRF52820 114## nRF52820
113nrf52820 = ["nrf-pac/nrf52820", "_nrf52"] 115nrf52820 = ["nrf-pac/nrf52820", "_nrf52", "_spi-v1"]
114## nRF52832 116## nRF52832
115nrf52832 = ["nrf-pac/nrf52832", "_nrf52", "_nrf52832_anomaly_109"] 117nrf52832 = ["nrf-pac/nrf52832", "_nrf52", "_nrf52832_anomaly_109", "_spi-v1"]
116## nRF52833 118## nRF52833
117nrf52833 = ["nrf-pac/nrf52833", "_nrf52", "_gpio-p1"] 119nrf52833 = ["nrf-pac/nrf52833", "_nrf52", "_gpio-p1"]
118## nRF52840 120## nRF52840
@@ -152,10 +154,10 @@ _nrf54l15-app = ["_nrf54l15", "nrf-pac/nrf54l15-app"]
152_nrf54l15 = ["_nrf54l", "_gpio-p1", "_gpio-p2"] 154_nrf54l15 = ["_nrf54l", "_gpio-p1", "_gpio-p2"]
153_nrf54l = ["_dppi"] 155_nrf54l = ["_dppi"]
154 156
155_nrf9160 = ["nrf-pac/nrf9160", "_dppi"] 157_nrf9160 = ["nrf-pac/nrf9160", "_dppi", "_spi-v1"]
156_nrf9120 = ["nrf-pac/nrf9120", "_dppi"] 158_nrf9120 = ["nrf-pac/nrf9120", "_dppi", "_spi-v1"]
157_nrf52 = ["_ppi"] 159_nrf52 = ["_ppi"]
158_nrf51 = ["_ppi"] 160_nrf51 = ["_ppi", "_spi-v1"]
159_nrf91 = [] 161_nrf91 = []
160 162
161_time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768", "dep:embassy-time-queue-utils", "embassy-embedded-hal/time"] 163_time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768", "dep:embassy-time-queue-utils", "embassy-embedded-hal/time"]
@@ -170,6 +172,7 @@ _ppi = []
170_dppi = [] 172_dppi = []
171_gpio-p1 = [] 173_gpio-p1 = []
172_gpio-p2 = [] 174_gpio-p2 = []
175_spi-v1 = []
173 176
174# Errata workarounds 177# Errata workarounds
175_nrf52832_anomaly_109 = [] 178_nrf52832_anomaly_109 = []
@@ -197,7 +200,7 @@ embedded-io-async = { version = "0.6.1" }
197rand-core-06 = { package = "rand_core", version = "0.6" } 200rand-core-06 = { package = "rand_core", version = "0.6" }
198rand-core-09 = { package = "rand_core", version = "0.9" } 201rand-core-09 = { package = "rand_core", version = "0.9" }
199 202
200nrf-pac = "0.1.0" 203nrf-pac = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-pac.git", rev = "58198c23bce72edc10b4e1656d1b54441fc74e7c" }
201 204
202defmt = { version = "1.0.1", optional = true } 205defmt = { version = "1.0.1", optional = true }
203bitflags = "2.4.2" 206bitflags = "2.4.2"
diff --git a/embassy-nrf/src/buffered_uarte/mod.rs b/embassy-nrf/src/buffered_uarte/mod.rs
new file mode 100644
index 000000000..75d84baac
--- /dev/null
+++ b/embassy-nrf/src/buffered_uarte/mod.rs
@@ -0,0 +1,14 @@
1//! Async buffered UART driver.
2//!
3//! Note that discarding a future from a read or write operation may lead to losing
4//! data. For example, when using `futures_util::future::select` and completion occurs
5//! on the "other" future, you should capture the incomplete future and continue to use
6//! it for the next read or write. This pattern is a consideration for all IO, and not
7//! just serial communications.
8//!
9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
10#[cfg_attr(not(feature = "_nrf54l"), path = "v1.rs")]
11#[cfg_attr(feature = "_nrf54l", path = "v2.rs")]
12mod _version;
13
14pub use _version::*;
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte/v1.rs
index 4c946497d..ec360f7d0 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte/v1.rs
@@ -40,6 +40,7 @@ pub(crate) struct State {
40 rx_started_count: AtomicU8, 40 rx_started_count: AtomicU8,
41 rx_ended_count: AtomicU8, 41 rx_ended_count: AtomicU8,
42 rx_ppi_ch: AtomicU8, 42 rx_ppi_ch: AtomicU8,
43 rx_overrun: AtomicBool,
43} 44}
44 45
45/// UART error. 46/// UART error.
@@ -47,7 +48,8 @@ pub(crate) struct State {
47#[cfg_attr(feature = "defmt", derive(defmt::Format))] 48#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[non_exhaustive] 49#[non_exhaustive]
49pub enum Error { 50pub enum Error {
50 // No errors for now 51 /// Buffer Overrun
52 Overrun,
51} 53}
52 54
53impl State { 55impl State {
@@ -61,6 +63,7 @@ impl State {
61 rx_started_count: AtomicU8::new(0), 63 rx_started_count: AtomicU8::new(0),
62 rx_ended_count: AtomicU8::new(0), 64 rx_ended_count: AtomicU8::new(0),
63 rx_ppi_ch: AtomicU8::new(0), 65 rx_ppi_ch: AtomicU8::new(0),
66 rx_overrun: AtomicBool::new(false),
64 } 67 }
65 } 68 }
66} 69}
@@ -87,7 +90,8 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
87 r.errorsrc().write_value(errs); 90 r.errorsrc().write_value(errs);
88 91
89 if errs.overrun() { 92 if errs.overrun() {
90 panic!("BufferedUarte overrun"); 93 s.rx_overrun.store(true, Ordering::Release);
94 ss.rx_waker.wake();
91 } 95 }
92 } 96 }
93 97
@@ -98,25 +102,25 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
98 ss.rx_waker.wake(); 102 ss.rx_waker.wake();
99 } 103 }
100 104
101 if r.events_endrx().read() != 0 { 105 if r.events_dma().rx().end().read() != 0 {
102 //trace!(" irq_rx: endrx"); 106 //trace!(" irq_rx: endrx");
103 r.events_endrx().write_value(0); 107 r.events_dma().rx().end().write_value(0);
104 108
105 let val = s.rx_ended_count.load(Ordering::Relaxed); 109 let val = s.rx_ended_count.load(Ordering::Relaxed);
106 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); 110 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
107 } 111 }
108 112
109 if r.events_rxstarted().read() != 0 || !s.rx_started.load(Ordering::Relaxed) { 113 if r.events_dma().rx().ready().read() != 0 || !s.rx_started.load(Ordering::Relaxed) {
110 //trace!(" irq_rx: rxstarted"); 114 //trace!(" irq_rx: rxstarted");
111 let (ptr, len) = rx.push_buf(); 115 let (ptr, len) = rx.push_buf();
112 if len >= half_len { 116 if len >= half_len {
113 r.events_rxstarted().write_value(0); 117 r.events_dma().rx().ready().write_value(0);
114 118
115 //trace!(" irq_rx: starting second {:?}", half_len); 119 //trace!(" irq_rx: starting second {:?}", half_len);
116 120
117 // Set up the DMA read 121 // Set up the DMA read
118 r.rxd().ptr().write_value(ptr as u32); 122 r.dma().rx().ptr().write_value(ptr as u32);
119 r.rxd().maxcnt().write(|w| w.set_maxcnt(half_len as _)); 123 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(half_len as _));
120 124
121 let chn = s.rx_ppi_ch.load(Ordering::Relaxed); 125 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
122 126
@@ -129,9 +133,9 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
129 // and manually start. 133 // and manually start.
130 134
131 // check again in case endrx has happened between the last check and now. 135 // check again in case endrx has happened between the last check and now.
132 if r.events_endrx().read() != 0 { 136 if r.events_dma().rx().end().read() != 0 {
133 //trace!(" irq_rx: endrx"); 137 //trace!(" irq_rx: endrx");
134 r.events_endrx().write_value(0); 138 r.events_dma().rx().end().write_value(0);
135 139
136 let val = s.rx_ended_count.load(Ordering::Relaxed); 140 let val = s.rx_ended_count.load(Ordering::Relaxed);
137 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); 141 s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
@@ -157,7 +161,7 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
157 ppi::regs().chenclr().write(|w| w.set_ch(chn as _, true)); 161 ppi::regs().chenclr().write(|w| w.set_ch(chn as _, true));
158 162
159 // manually start 163 // manually start
160 r.tasks_startrx().write_value(1); 164 r.tasks_dma().rx().start().write_value(1);
161 } 165 }
162 166
163 rx.push_done(half_len); 167 rx.push_done(half_len);
@@ -166,7 +170,7 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
166 s.rx_started.store(true, Ordering::Relaxed); 170 s.rx_started.store(true, Ordering::Relaxed);
167 } else { 171 } else {
168 //trace!(" irq_rx: rxstarted no buf"); 172 //trace!(" irq_rx: rxstarted no buf");
169 r.intenclr().write(|w| w.set_rxstarted(true)); 173 r.intenclr().write(|w| w.set_dmarxready(true));
170 } 174 }
171 } 175 }
172 } 176 }
@@ -175,8 +179,8 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
175 179
176 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } { 180 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } {
177 // TX end 181 // TX end
178 if r.events_endtx().read() != 0 { 182 if r.events_dma().tx().end().read() != 0 {
179 r.events_endtx().write_value(0); 183 r.events_dma().tx().end().write_value(0);
180 184
181 let n = s.tx_count.load(Ordering::Relaxed); 185 let n = s.tx_count.load(Ordering::Relaxed);
182 //trace!(" irq_tx: endtx {:?}", n); 186 //trace!(" irq_tx: endtx {:?}", n);
@@ -194,11 +198,11 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
194 s.tx_count.store(len, Ordering::Relaxed); 198 s.tx_count.store(len, Ordering::Relaxed);
195 199
196 // Set up the DMA write 200 // Set up the DMA write
197 r.txd().ptr().write_value(ptr as u32); 201 r.dma().tx().ptr().write_value(ptr as u32);
198 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 202 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
199 203
200 // Start UARTE Transmit transaction 204 // Start UARTE Transmit transaction
201 r.tasks_starttx().write_value(1); 205 r.tasks_dma().tx().start().write_value(1);
202 } 206 }
203 } 207 }
204 } 208 }
@@ -452,11 +456,11 @@ impl<'d> BufferedUarteTx<'d> {
452 let len = tx_buffer.len(); 456 let len = tx_buffer.len();
453 unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; 457 unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
454 458
455 r.events_txstarted().write_value(0); 459 r.events_dma().tx().ready().write_value(0);
456 460
457 // Enable interrupts 461 // Enable interrupts
458 r.intenset().write(|w| { 462 r.intenset().write(|w| {
459 w.set_endtx(true); 463 w.set_dmatxend(true);
460 }); 464 });
461 465
462 Self { 466 Self {
@@ -547,11 +551,11 @@ impl<'a> Drop for BufferedUarteTx<'a> {
547 551
548 r.intenclr().write(|w| { 552 r.intenclr().write(|w| {
549 w.set_txdrdy(true); 553 w.set_txdrdy(true);
550 w.set_txstarted(true); 554 w.set_dmatxready(true);
551 w.set_txstopped(true); 555 w.set_txstopped(true);
552 }); 556 });
553 r.events_txstopped().write_value(0); 557 r.events_txstopped().write_value(0);
554 r.tasks_stoptx().write_value(1); 558 r.tasks_dma().tx().stop().write_value(1);
555 while r.events_txstopped().read() == 0 {} 559 while r.events_txstopped().read() == 0 {}
556 560
557 let s = self.buffered_state; 561 let s = self.buffered_state;
@@ -689,6 +693,7 @@ impl<'d> BufferedUarteRx<'d> {
689 buffered_state.rx_started_count.store(0, Ordering::Relaxed); 693 buffered_state.rx_started_count.store(0, Ordering::Relaxed);
690 buffered_state.rx_ended_count.store(0, Ordering::Relaxed); 694 buffered_state.rx_ended_count.store(0, Ordering::Relaxed);
691 buffered_state.rx_started.store(false, Ordering::Relaxed); 695 buffered_state.rx_started.store(false, Ordering::Relaxed);
696 buffered_state.rx_overrun.store(false, Ordering::Relaxed);
692 let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2); 697 let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2);
693 unsafe { buffered_state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) }; 698 unsafe { buffered_state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) };
694 699
@@ -696,16 +701,16 @@ impl<'d> BufferedUarteRx<'d> {
696 let errors = r.errorsrc().read(); 701 let errors = r.errorsrc().read();
697 r.errorsrc().write_value(errors); 702 r.errorsrc().write_value(errors);
698 703
699 r.events_rxstarted().write_value(0); 704 r.events_dma().rx().ready().write_value(0);
700 r.events_error().write_value(0); 705 r.events_error().write_value(0);
701 r.events_endrx().write_value(0); 706 r.events_dma().rx().end().write_value(0);
702 707
703 // Enable interrupts 708 // Enable interrupts
704 r.intenset().write(|w| { 709 r.intenset().write(|w| {
705 w.set_endtx(true); 710 w.set_dmatxend(true);
706 w.set_rxstarted(true); 711 w.set_dmarxready(true);
707 w.set_error(true); 712 w.set_error(true);
708 w.set_endrx(true); 713 w.set_dmarxend(true);
709 }); 714 });
710 715
711 // Configure byte counter. 716 // Configure byte counter.
@@ -724,8 +729,8 @@ impl<'d> BufferedUarteRx<'d> {
724 let mut ppi_group = PpiGroup::new(ppi_group); 729 let mut ppi_group = PpiGroup::new(ppi_group);
725 let mut ppi_ch2 = Ppi::new_one_to_two( 730 let mut ppi_ch2 = Ppi::new_one_to_two(
726 ppi_ch2, 731 ppi_ch2,
727 Event::from_reg(r.events_endrx()), 732 Event::from_reg(r.events_dma().rx().end()),
728 Task::from_reg(r.tasks_startrx()), 733 Task::from_reg(r.tasks_dma().rx().start()),
729 ppi_group.task_disable_all(), 734 ppi_group.task_disable_all(),
730 ); 735 );
731 ppi_ch2.disable(); 736 ppi_ch2.disable();
@@ -743,6 +748,30 @@ impl<'d> BufferedUarteRx<'d> {
743 } 748 }
744 } 749 }
745 750
751 fn get_rxdrdy_counter(&self) -> usize {
752 let s = self.buffered_state;
753 let timer = &self.timer;
754
755 // Read the RXDRDY counter.
756 timer.cc(0).capture();
757 let mut rxdrdy = timer.cc(0).read() as usize;
758 //trace!(" rxdrdy count = {:?}", rxdrdy);
759
760 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
761 // However, it's unclear if that's instant, or there's a small window where you can
762 // still read `len()*2`.
763 // This could happen if in one clock cycle the counter is updated, and in the next the
764 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
765 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
766 // clock cycle of the PCLK16M." :shrug:
767 // So, we wrap the counter ourselves, just in case.
768 if rxdrdy > s.rx_buf.len() * 2 {
769 rxdrdy = 0;
770 }
771
772 rxdrdy
773 }
774
746 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. 775 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
747 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 776 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
748 let data = self.fill_buf().await?; 777 let data = self.fill_buf().await?;
@@ -757,28 +786,17 @@ impl<'d> BufferedUarteRx<'d> {
757 let r = self.r; 786 let r = self.r;
758 let s = self.buffered_state; 787 let s = self.buffered_state;
759 let ss = self.state; 788 let ss = self.state;
760 let timer = &self.timer; 789
761 poll_fn(move |cx| { 790 poll_fn(move |cx| {
762 compiler_fence(Ordering::SeqCst); 791 compiler_fence(Ordering::SeqCst);
763 //trace!("poll_read"); 792 //trace!("poll_read");
764 793
765 // Read the RXDRDY counter. 794 if s.rx_overrun.swap(false, Ordering::Acquire) {
766 timer.cc(0).capture(); 795 return Poll::Ready(Err(Error::Overrun));
767 let mut end = timer.cc(0).read() as usize;
768 //trace!(" rxdrdy count = {:?}", end);
769
770 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
771 // However, it's unclear if that's instant, or there's a small window where you can
772 // still read `len()*2`.
773 // This could happen if in one clock cycle the counter is updated, and in the next the
774 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
775 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
776 // clock cycle of the PCLK16M." :shrug:
777 // So, we wrap the counter ourselves, just in case.
778 if end > s.rx_buf.len() * 2 {
779 end = 0
780 } 796 }
781 797
798 let mut end = self.get_rxdrdy_counter();
799
782 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()` 800 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()`
783 let mut start = s.rx_buf.start.load(Ordering::Relaxed); 801 let mut start = s.rx_buf.start.load(Ordering::Relaxed);
784 let len = s.rx_buf.len(); 802 let len = s.rx_buf.len();
@@ -814,13 +832,20 @@ impl<'d> BufferedUarteRx<'d> {
814 let s = self.buffered_state; 832 let s = self.buffered_state;
815 let mut rx = unsafe { s.rx_buf.reader() }; 833 let mut rx = unsafe { s.rx_buf.reader() };
816 rx.pop_done(amt); 834 rx.pop_done(amt);
817 self.r.intenset().write(|w| w.set_rxstarted(true)); 835 self.r.intenset().write(|w| w.set_dmarxready(true));
818 } 836 }
819 837
820 /// we are ready to read if there is data in the buffer 838 /// we are ready to read if there is data in the buffer
821 fn read_ready(&self) -> Result<bool, Error> { 839 fn read_ready(&self) -> Result<bool, Error> {
822 let state = self.buffered_state; 840 let state = self.buffered_state;
823 Ok(!state.rx_buf.is_empty()) 841 if state.rx_overrun.swap(false, Ordering::Acquire) {
842 return Err(Error::Overrun);
843 }
844
845 let start = state.rx_buf.start.load(Ordering::Relaxed);
846 let end = self.get_rxdrdy_counter();
847
848 Ok(start != end)
824 } 849 }
825} 850}
826 851
@@ -834,11 +859,11 @@ impl<'a> Drop for BufferedUarteRx<'a> {
834 859
835 r.intenclr().write(|w| { 860 r.intenclr().write(|w| {
836 w.set_rxdrdy(true); 861 w.set_rxdrdy(true);
837 w.set_rxstarted(true); 862 w.set_dmarxready(true);
838 w.set_rxto(true); 863 w.set_rxto(true);
839 }); 864 });
840 r.events_rxto().write_value(0); 865 r.events_rxto().write_value(0);
841 r.tasks_stoprx().write_value(1); 866 r.tasks_dma().rx().stop().write_value(1);
842 while r.events_rxto().read() == 0 {} 867 while r.events_rxto().read() == 0 {}
843 868
844 let s = self.buffered_state; 869 let s = self.buffered_state;
@@ -854,7 +879,9 @@ mod _embedded_io {
854 879
855 impl embedded_io_async::Error for Error { 880 impl embedded_io_async::Error for Error {
856 fn kind(&self) -> embedded_io_async::ErrorKind { 881 fn kind(&self) -> embedded_io_async::ErrorKind {
857 match *self {} 882 match *self {
883 Error::Overrun => embedded_io_async::ErrorKind::OutOfMemory,
884 }
858 } 885 }
859 } 886 }
860 887
diff --git a/embassy-nrf/src/buffered_uarte/v2.rs b/embassy-nrf/src/buffered_uarte/v2.rs
new file mode 100644
index 000000000..d0d2d97d1
--- /dev/null
+++ b/embassy-nrf/src/buffered_uarte/v2.rs
@@ -0,0 +1,687 @@
1//! Async buffered UART driver.
2//!
3//! Note that discarding a future from a read or write operation may lead to losing
4//! data. For example, when using `futures_util::future::select` and completion occurs
5//! on the "other" future, you should capture the incomplete future and continue to use
6//! it for the next read or write. This pattern is a consideration for all IO, and not
7//! just serial communications.
8//!
9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
10//!
11//! The code is based on the generic buffered_uarte implementation but uses the nrf54l
12//! frame timeout event to correctly determine the size of transferred data.
13//! Counting of rxrdy events, used in the generic implementation, cannot be applied
14//! to nrf54l chips, as they buffer up to 4 bytes in a single DMA transaction.
15//! The only reliable way to find the number of bytes received is to stop the transfer,
16//! wait for the DMA stopped event, and read the value in the rx.dma.amount register.
17//! This also flushes all in-flight data to RAM.
18
19use core::cmp::min;
20use core::future::{Future, poll_fn};
21use core::marker::PhantomData;
22use core::slice;
23use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering, compiler_fence};
24use core::task::Poll;
25
26use embassy_hal_internal::Peri;
27use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
28use pac::uarte::vals;
29// Re-export SVD variants to allow user to directly set values
30pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity};
31
32use crate::gpio::{AnyPin, Pin as GpioPin};
33use crate::interrupt::typelevel::Interrupt;
34use crate::uarte::{Config, Instance as UarteInstance, configure, configure_rx_pins, configure_tx_pins, drop_tx_rx};
35use crate::{EASY_DMA_SIZE, interrupt, pac};
36
37pub(crate) struct State {
38 tx_buf: RingBuffer,
39 tx_count: AtomicUsize,
40
41 rx_buf: RingBuffer,
42 rx_started: AtomicBool,
43}
44
45/// UART error.
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[non_exhaustive]
49pub enum Error {
50 // No errors for now
51}
52
53impl State {
54 pub(crate) const fn new() -> Self {
55 Self {
56 tx_buf: RingBuffer::new(),
57 tx_count: AtomicUsize::new(0),
58
59 rx_buf: RingBuffer::new(),
60 rx_started: AtomicBool::new(false),
61 }
62 }
63}
64
65/// Interrupt handler.
66pub struct InterruptHandler<U: UarteInstance> {
67 _phantom: PhantomData<U>,
68}
69
70impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for InterruptHandler<U> {
71 unsafe fn on_interrupt() {
72 info!("irq: start");
73 let r = U::regs();
74 let ss = U::state();
75 let s = U::buffered_state();
76
77 if let Some(mut rx) = unsafe { s.rx_buf.try_writer() } {
78 let buf_len = s.rx_buf.len();
79 let half_len = buf_len / 2;
80
81 if r.events_error().read() != 0 {
82 r.events_error().write_value(0);
83 let errs = r.errorsrc().read();
84 r.errorsrc().write_value(errs);
85
86 if errs.overrun() {
87 panic!("BufferedUarte UART overrun");
88 }
89 }
90
91 let first_run = !s.rx_started.swap(true, Ordering::Relaxed);
92 if r.events_dma().rx().end().read() != 0 || first_run {
93 //trace!(" irq_rx: endrx");
94 r.events_dma().rx().end().write_value(0);
95
96 if !first_run {
97 // Received some bytes, wake task.
98 let rxed = r.dma().rx().amount().read().amount() as usize;
99 rx.push_done(rxed);
100 ss.rx_waker.wake();
101 }
102
103 let (ptr, len) = rx.push_buf();
104 if len == 0 {
105 panic!("BufferedUarte buffer overrun");
106 }
107
108 let len = if len > half_len { half_len } else { len };
109
110 // Set up the DMA read
111 r.dma().rx().ptr().write_value(ptr as u32);
112 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
113
114 // manually start
115 r.tasks_dma().rx().start().write_value(1);
116 }
117 }
118
119 // =============================
120
121 if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } {
122 // TX end
123 if r.events_dma().tx().end().read() != 0 {
124 r.events_dma().tx().end().write_value(0);
125
126 let n = s.tx_count.load(Ordering::Relaxed);
127 //trace!(" irq_tx: endtx {:?}", n);
128 tx.pop_done(n);
129 ss.tx_waker.wake();
130 s.tx_count.store(0, Ordering::Relaxed);
131 }
132
133 // If not TXing, start.
134 if s.tx_count.load(Ordering::Relaxed) == 0 {
135 let (ptr, len) = tx.pop_buf();
136 let len = len.min(EASY_DMA_SIZE);
137 if len != 0 {
138 //trace!(" irq_tx: starting {:?}", len);
139 s.tx_count.store(len, Ordering::Relaxed);
140
141 // Set up the DMA write
142 r.dma().tx().ptr().write_value(ptr as u32);
143 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
144
145 // Start UARTE Transmit transaction
146 r.tasks_dma().tx().start().write_value(1);
147 }
148 }
149 }
150
151 //trace!("irq: end");
152 }
153}
154
155/// Buffered UARTE driver.
156pub struct BufferedUarte<'d, U: UarteInstance> {
157 tx: BufferedUarteTx<'d, U>,
158 rx: BufferedUarteRx<'d, U>,
159}
160
161impl<'d, U: UarteInstance> Unpin for BufferedUarte<'d, U> {}
162
163impl<'d, U: UarteInstance> BufferedUarte<'d, U> {
164 /// Create a new BufferedUarte without hardware flow control.
165 #[allow(clippy::too_many_arguments)]
166 pub fn new(
167 uarte: Peri<'d, U>,
168 rxd: Peri<'d, impl GpioPin>,
169 txd: Peri<'d, impl GpioPin>,
170 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
171 config: Config,
172 rx_buffer: &'d mut [u8],
173 tx_buffer: &'d mut [u8],
174 ) -> Self {
175 Self::new_inner(uarte, rxd.into(), txd.into(), None, None, config, rx_buffer, tx_buffer)
176 }
177
178 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
179 #[allow(clippy::too_many_arguments)]
180 pub fn new_with_rtscts(
181 uarte: Peri<'d, U>,
182 rxd: Peri<'d, impl GpioPin>,
183 txd: Peri<'d, impl GpioPin>,
184 cts: Peri<'d, impl GpioPin>,
185 rts: Peri<'d, impl GpioPin>,
186 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
187 config: Config,
188 rx_buffer: &'d mut [u8],
189 tx_buffer: &'d mut [u8],
190 ) -> Self {
191 Self::new_inner(
192 uarte,
193 rxd.into(),
194 txd.into(),
195 Some(cts.into()),
196 Some(rts.into()),
197 config,
198 rx_buffer,
199 tx_buffer,
200 )
201 }
202
203 #[allow(clippy::too_many_arguments)]
204 fn new_inner(
205 peri: Peri<'d, U>,
206 rxd: Peri<'d, AnyPin>,
207 txd: Peri<'d, AnyPin>,
208 cts: Option<Peri<'d, AnyPin>>,
209 rts: Option<Peri<'d, AnyPin>>,
210 config: Config,
211 rx_buffer: &'d mut [u8],
212 tx_buffer: &'d mut [u8],
213 ) -> Self {
214 configure(U::regs(), config, cts.is_some());
215
216 let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer);
217 let rx = BufferedUarteRx::new_innerer(peri, rxd, rts, rx_buffer);
218
219 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
220 U::Interrupt::pend();
221 unsafe { U::Interrupt::enable() };
222
223 U::state().tx_rx_refcount.store(2, Ordering::Relaxed);
224
225 Self { tx, rx }
226 }
227
228 /// Adjust the baud rate to the provided value.
229 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
230 let r = U::regs();
231 r.baudrate().write(|w| w.set_baudrate(baudrate));
232 }
233
234 /// Split the UART in reader and writer parts.
235 ///
236 /// This allows reading and writing concurrently from independent tasks.
237 pub fn split(self) -> (BufferedUarteRx<'d, U>, BufferedUarteTx<'d, U>) {
238 (self.rx, self.tx)
239 }
240
241 /// Split the UART in reader and writer parts, by reference.
242 ///
243 /// The returned halves borrow from `self`, so you can drop them and go back to using
244 /// the "un-split" `self`. This allows temporarily splitting the UART.
245 pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d, U>, &mut BufferedUarteTx<'d, U>) {
246 (&mut self.rx, &mut self.tx)
247 }
248
249 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
250 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
251 self.rx.read(buf).await
252 }
253
254 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
255 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
256 self.rx.fill_buf().await
257 }
258
259 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
260 pub fn consume(&mut self, amt: usize) {
261 self.rx.consume(amt)
262 }
263
264 /// Write a buffer into this writer, returning how many bytes were written.
265 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
266 self.tx.write(buf).await
267 }
268
269 /// Try writing a buffer without waiting, returning how many bytes were written.
270 pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
271 self.tx.try_write(buf)
272 }
273
274 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
275 pub async fn flush(&mut self) -> Result<(), Error> {
276 self.tx.flush().await
277 }
278}
279
280/// Reader part of the buffered UARTE driver.
281pub struct BufferedUarteTx<'d, U: UarteInstance> {
282 _peri: Peri<'d, U>,
283}
284
285impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
286 /// Create a new BufferedUarteTx without hardware flow control.
287 pub fn new(
288 uarte: Peri<'d, U>,
289 txd: Peri<'d, impl GpioPin>,
290 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
291 config: Config,
292 tx_buffer: &'d mut [u8],
293 ) -> Self {
294 Self::new_inner(uarte, txd.into(), None, config, tx_buffer)
295 }
296
297 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
298 pub fn new_with_cts(
299 uarte: Peri<'d, U>,
300 txd: Peri<'d, impl GpioPin>,
301 cts: Peri<'d, impl GpioPin>,
302 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
303 config: Config,
304 tx_buffer: &'d mut [u8],
305 ) -> Self {
306 Self::new_inner(uarte, txd.into(), Some(cts.into()), config, tx_buffer)
307 }
308
309 fn new_inner(
310 peri: Peri<'d, U>,
311 txd: Peri<'d, AnyPin>,
312 cts: Option<Peri<'d, AnyPin>>,
313 config: Config,
314 tx_buffer: &'d mut [u8],
315 ) -> Self {
316 configure(U::regs(), config, cts.is_some());
317
318 let this = Self::new_innerer(peri, txd, cts, tx_buffer);
319
320 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
321 U::Interrupt::pend();
322 unsafe { U::Interrupt::enable() };
323
324 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
325
326 this
327 }
328
329 fn new_innerer(
330 peri: Peri<'d, U>,
331 txd: Peri<'d, AnyPin>,
332 cts: Option<Peri<'d, AnyPin>>,
333 tx_buffer: &'d mut [u8],
334 ) -> Self {
335 let r = U::regs();
336
337 configure_tx_pins(r, txd, cts);
338
339 // Initialize state
340 let s = U::buffered_state();
341 s.tx_count.store(0, Ordering::Relaxed);
342 let len = tx_buffer.len();
343 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
344
345 r.events_dma().tx().ready().write_value(0);
346
347 // Enable interrupts
348 r.intenset().write(|w| {
349 w.set_dmatxend(true);
350 });
351
352 Self { _peri: peri }
353 }
354
355 /// Write a buffer into this writer, returning how many bytes were written.
356 pub fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = Result<usize, Error>> + 'a {
357 poll_fn(move |cx| {
358 //trace!("poll_write: {:?}", buf.len());
359 let ss = U::state();
360 let s = U::buffered_state();
361 let mut tx = unsafe { s.tx_buf.writer() };
362
363 let tx_buf = tx.push_slice();
364 if tx_buf.is_empty() {
365 //trace!("poll_write: pending");
366 ss.tx_waker.register(cx.waker());
367 return Poll::Pending;
368 }
369
370 let n = min(tx_buf.len(), buf.len());
371 tx_buf[..n].copy_from_slice(&buf[..n]);
372 tx.push_done(n);
373
374 //trace!("poll_write: queued {:?}", n);
375
376 compiler_fence(Ordering::SeqCst);
377 U::Interrupt::pend();
378
379 Poll::Ready(Ok(n))
380 })
381 }
382
383 /// Try writing a buffer without waiting, returning how many bytes were written.
384 pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
385 //trace!("poll_write: {:?}", buf.len());
386 let s = U::buffered_state();
387 let mut tx = unsafe { s.tx_buf.writer() };
388
389 let tx_buf = tx.push_slice();
390 if tx_buf.is_empty() {
391 return Ok(0);
392 }
393
394 let n = min(tx_buf.len(), buf.len());
395 tx_buf[..n].copy_from_slice(&buf[..n]);
396 tx.push_done(n);
397
398 //trace!("poll_write: queued {:?}", n);
399
400 compiler_fence(Ordering::SeqCst);
401 U::Interrupt::pend();
402
403 Ok(n)
404 }
405
406 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
407 pub fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + '_ {
408 poll_fn(move |cx| {
409 //trace!("poll_flush");
410 let ss = U::state();
411 let s = U::buffered_state();
412 if !s.tx_buf.is_empty() {
413 //trace!("poll_flush: pending");
414 ss.tx_waker.register(cx.waker());
415 return Poll::Pending;
416 }
417
418 Poll::Ready(Ok(()))
419 })
420 }
421}
422
423impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> {
424 fn drop(&mut self) {
425 let r = U::regs();
426
427 r.intenclr().write(|w| {
428 w.set_txdrdy(true);
429 w.set_dmatxready(true);
430 w.set_txstopped(true);
431 });
432 r.events_txstopped().write_value(0);
433 r.tasks_dma().tx().stop().write_value(1);
434 while r.events_txstopped().read() == 0 {}
435
436 let s = U::buffered_state();
437 unsafe { s.tx_buf.deinit() }
438
439 let s = U::state();
440 drop_tx_rx(r, s);
441 }
442}
443
444/// Reader part of the buffered UARTE driver.
445pub struct BufferedUarteRx<'d, U: UarteInstance> {
446 _peri: Peri<'d, U>,
447}
448
449impl<'d, U: UarteInstance> BufferedUarteRx<'d, U> {
450 /// Create a new BufferedUarte without hardware flow control.
451 #[allow(clippy::too_many_arguments)]
452 pub fn new(
453 uarte: Peri<'d, U>,
454 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
455 rxd: Peri<'d, impl GpioPin>,
456 config: Config,
457 rx_buffer: &'d mut [u8],
458 ) -> Self {
459 Self::new_inner(uarte, rxd.into(), None, config, rx_buffer)
460 }
461
462 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
463 #[allow(clippy::too_many_arguments)]
464 pub fn new_with_rts(
465 uarte: Peri<'d, U>,
466 rxd: Peri<'d, impl GpioPin>,
467 rts: Peri<'d, impl GpioPin>,
468 _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
469 config: Config,
470 rx_buffer: &'d mut [u8],
471 ) -> Self {
472 Self::new_inner(uarte, rxd.into(), Some(rts.into()), config, rx_buffer)
473 }
474
475 #[allow(clippy::too_many_arguments)]
476 fn new_inner(
477 peri: Peri<'d, U>,
478 rxd: Peri<'d, AnyPin>,
479 rts: Option<Peri<'d, AnyPin>>,
480 config: Config,
481 rx_buffer: &'d mut [u8],
482 ) -> Self {
483 configure(U::regs(), config, rts.is_some());
484
485 let this = Self::new_innerer(peri, rxd, rts, rx_buffer);
486
487 U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED));
488 U::Interrupt::pend();
489 unsafe { U::Interrupt::enable() };
490
491 U::state().tx_rx_refcount.store(1, Ordering::Relaxed);
492
493 this
494 }
495
496 #[allow(clippy::too_many_arguments)]
497 fn new_innerer(
498 peri: Peri<'d, U>,
499 rxd: Peri<'d, AnyPin>,
500 rts: Option<Peri<'d, AnyPin>>,
501 rx_buffer: &'d mut [u8],
502 ) -> Self {
503 let r = U::regs();
504
505 configure_rx_pins(r, rxd, rts);
506
507 // Initialize state
508 let s = U::buffered_state();
509 let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2);
510 let rx_ptr = rx_buffer.as_mut_ptr();
511 unsafe { s.rx_buf.init(rx_ptr, rx_len) };
512
513 // clear errors
514 let errors = r.errorsrc().read();
515 r.errorsrc().write_value(errors);
516
517 r.events_error().write_value(0);
518 r.events_dma().rx().end().write_value(0);
519
520 // set timeout-to-stop short
521 r.shorts().write(|w| {
522 w.set_frametimeout_dma_rx_stop(true);
523 });
524
525 // set default timeout
526 r.frametimeout().write_value(pac::uarte::regs::Frametimeout(0x10));
527
528 // Enable interrupts
529 r.intenset().write(|w| {
530 w.set_dmatxend(true);
531 w.set_error(true);
532 w.set_dmarxend(true);
533 });
534
535 Self { _peri: peri }
536 }
537
538 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
539 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
540 let data = self.fill_buf().await?;
541 let n = data.len().min(buf.len());
542 buf[..n].copy_from_slice(&data[..n]);
543 self.consume(n);
544 Ok(n)
545 }
546
547 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
548 pub fn fill_buf(&mut self) -> impl Future<Output = Result<&'_ [u8], Error>> {
549 poll_fn(move |cx| {
550 compiler_fence(Ordering::SeqCst);
551 //trace!("poll_read");
552
553 let s = U::buffered_state();
554 let ss = U::state();
555 let mut rx = unsafe { s.rx_buf.reader() };
556
557 let (ptr, n) = rx.pop_buf();
558 if n == 0 {
559 //trace!(" empty");
560 ss.rx_waker.register(cx.waker());
561 Poll::Pending
562 } else {
563 Poll::Ready(Ok(unsafe { slice::from_raw_parts(ptr, n) }))
564 }
565 })
566 }
567
568 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
569 pub fn consume(&mut self, amt: usize) {
570 if amt == 0 {
571 return;
572 }
573
574 let s = U::buffered_state();
575 let mut rx = unsafe { s.rx_buf.reader() };
576 rx.pop_done(amt);
577 }
578
579 /// we are ready to read if there is data in the buffer
580 fn read_ready() -> Result<bool, Error> {
581 let state = U::buffered_state();
582 Ok(!state.rx_buf.is_empty())
583 }
584}
585
586impl<'a, U: UarteInstance> Drop for BufferedUarteRx<'a, U> {
587 fn drop(&mut self) {
588 let r = U::regs();
589
590 r.intenclr().write(|w| {
591 w.set_rxto(true);
592 });
593 r.events_rxto().write_value(0);
594
595 let s = U::buffered_state();
596 unsafe { s.rx_buf.deinit() }
597
598 let s = U::state();
599 drop_tx_rx(r, s);
600 }
601}
602
603mod _embedded_io {
604 use super::*;
605
606 impl embedded_io_async::Error for Error {
607 fn kind(&self) -> embedded_io_async::ErrorKind {
608 match *self {}
609 }
610 }
611
612 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarte<'d, U> {
613 type Error = Error;
614 }
615
616 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteRx<'d, U> {
617 type Error = Error;
618 }
619
620 impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteTx<'d, U> {
621 type Error = Error;
622 }
623
624 impl<'d, U: UarteInstance> embedded_io_async::Read for BufferedUarte<'d, U> {
625 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
626 self.read(buf).await
627 }
628 }
629
630 impl<'d: 'd, U: UarteInstance> embedded_io_async::Read for BufferedUarteRx<'d, U> {
631 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
632 self.read(buf).await
633 }
634 }
635
636 impl<'d, U: UarteInstance> embedded_io_async::ReadReady for BufferedUarte<'d, U> {
637 fn read_ready(&mut self) -> Result<bool, Self::Error> {
638 BufferedUarteRx::<'d, U>::read_ready()
639 }
640 }
641
642 impl<'d, U: UarteInstance> embedded_io_async::ReadReady for BufferedUarteRx<'d, U> {
643 fn read_ready(&mut self) -> Result<bool, Self::Error> {
644 Self::read_ready()
645 }
646 }
647
648 impl<'d, U: UarteInstance> embedded_io_async::BufRead for BufferedUarte<'d, U> {
649 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
650 self.fill_buf().await
651 }
652
653 fn consume(&mut self, amt: usize) {
654 self.consume(amt)
655 }
656 }
657
658 impl<'d: 'd, U: UarteInstance> embedded_io_async::BufRead for BufferedUarteRx<'d, U> {
659 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
660 self.fill_buf().await
661 }
662
663 fn consume(&mut self, amt: usize) {
664 self.consume(amt)
665 }
666 }
667
668 impl<'d, U: UarteInstance> embedded_io_async::Write for BufferedUarte<'d, U> {
669 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
670 self.write(buf).await
671 }
672
673 async fn flush(&mut self) -> Result<(), Self::Error> {
674 self.flush().await
675 }
676 }
677
678 impl<'d: 'd, U: UarteInstance> embedded_io_async::Write for BufferedUarteTx<'d, U> {
679 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
680 self.write(buf).await
681 }
682
683 async fn flush(&mut self) -> Result<(), Self::Error> {
684 self.flush().await
685 }
686 }
687}
diff --git a/embassy-nrf/src/chips/nrf51.rs b/embassy-nrf/src/chips/nrf51.rs
index 3976e8ff0..1184c4409 100644
--- a/embassy-nrf/src/chips/nrf51.rs
+++ b/embassy-nrf/src/chips/nrf51.rs
@@ -115,6 +115,11 @@ impl_rtc!(RTC0, RTC0, RTC0);
115#[cfg(not(feature = "time-driver-rtc1"))] 115#[cfg(not(feature = "time-driver-rtc1"))]
116impl_rtc!(RTC1, RTC1, RTC1); 116impl_rtc!(RTC1, RTC1, RTC1);
117 117
118impl_ppi_group!(PPI_GROUP0, PPI, 0);
119impl_ppi_group!(PPI_GROUP1, PPI, 1);
120impl_ppi_group!(PPI_GROUP2, PPI, 2);
121impl_ppi_group!(PPI_GROUP3, PPI, 3);
122
118impl_pin!(P0_00, 0, 0); 123impl_pin!(P0_00, 0, 0);
119impl_pin!(P0_01, 0, 1); 124impl_pin!(P0_01, 0, 1);
120impl_pin!(P0_02, 0, 2); 125impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 63ba6999a..dd2e66927 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -195,28 +195,35 @@ impl_pin!(P0_29, 0, 29);
195impl_pin!(P0_30, 0, 30); 195impl_pin!(P0_30, 0, 30);
196impl_pin!(P0_31, 0, 31); 196impl_pin!(P0_31, 0, 31);
197 197
198impl_ppi_channel!(PPI_CH0, 0 => configurable); 198impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
199impl_ppi_channel!(PPI_CH1, 1 => configurable); 199impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
200impl_ppi_channel!(PPI_CH2, 2 => configurable); 200impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
201impl_ppi_channel!(PPI_CH3, 3 => configurable); 201impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
202impl_ppi_channel!(PPI_CH4, 4 => configurable); 202impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
203impl_ppi_channel!(PPI_CH5, 5 => configurable); 203impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
204impl_ppi_channel!(PPI_CH6, 6 => configurable); 204impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
205impl_ppi_channel!(PPI_CH7, 7 => configurable); 205impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
206impl_ppi_channel!(PPI_CH8, 8 => configurable); 206impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
207impl_ppi_channel!(PPI_CH9, 9 => configurable); 207impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
208impl_ppi_channel!(PPI_CH20, 20 => static); 208impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
209impl_ppi_channel!(PPI_CH21, 21 => static); 209impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
210impl_ppi_channel!(PPI_CH22, 22 => static); 210impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
211impl_ppi_channel!(PPI_CH23, 23 => static); 211impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
212impl_ppi_channel!(PPI_CH24, 24 => static); 212impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
213impl_ppi_channel!(PPI_CH25, 25 => static); 213impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
214impl_ppi_channel!(PPI_CH26, 26 => static); 214impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
215impl_ppi_channel!(PPI_CH27, 27 => static); 215impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
216impl_ppi_channel!(PPI_CH28, 28 => static); 216impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
217impl_ppi_channel!(PPI_CH29, 29 => static); 217impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
218impl_ppi_channel!(PPI_CH30, 30 => static); 218impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
219impl_ppi_channel!(PPI_CH31, 31 => static); 219impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
220
221impl_ppi_group!(PPI_GROUP0, PPI, 0);
222impl_ppi_group!(PPI_GROUP1, PPI, 1);
223impl_ppi_group!(PPI_GROUP2, PPI, 2);
224impl_ppi_group!(PPI_GROUP3, PPI, 3);
225impl_ppi_group!(PPI_GROUP4, PPI, 4);
226impl_ppi_group!(PPI_GROUP5, PPI, 5);
220 227
221impl_saadc_input!(P0_04, ANALOG_INPUT2); 228impl_saadc_input!(P0_04, ANALOG_INPUT2);
222impl_saadc_input!(P0_05, ANALOG_INPUT3); 229impl_saadc_input!(P0_05, ANALOG_INPUT3);
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 7f744f9fb..7acb53a03 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -205,38 +205,45 @@ impl_pin!(P0_29, 0, 29);
205impl_pin!(P0_30, 0, 30); 205impl_pin!(P0_30, 0, 30);
206impl_pin!(P0_31, 0, 31); 206impl_pin!(P0_31, 0, 31);
207 207
208impl_ppi_channel!(PPI_CH0, 0 => configurable); 208impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
209impl_ppi_channel!(PPI_CH1, 1 => configurable); 209impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
210impl_ppi_channel!(PPI_CH2, 2 => configurable); 210impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
211impl_ppi_channel!(PPI_CH3, 3 => configurable); 211impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
212impl_ppi_channel!(PPI_CH4, 4 => configurable); 212impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
213impl_ppi_channel!(PPI_CH5, 5 => configurable); 213impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
214impl_ppi_channel!(PPI_CH6, 6 => configurable); 214impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
215impl_ppi_channel!(PPI_CH7, 7 => configurable); 215impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
216impl_ppi_channel!(PPI_CH8, 8 => configurable); 216impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
217impl_ppi_channel!(PPI_CH9, 9 => configurable); 217impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
218impl_ppi_channel!(PPI_CH10, 10 => configurable); 218impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
219impl_ppi_channel!(PPI_CH11, 11 => configurable); 219impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
220impl_ppi_channel!(PPI_CH12, 12 => configurable); 220impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
221impl_ppi_channel!(PPI_CH13, 13 => configurable); 221impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
222impl_ppi_channel!(PPI_CH14, 14 => configurable); 222impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
223impl_ppi_channel!(PPI_CH15, 15 => configurable); 223impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
224impl_ppi_channel!(PPI_CH16, 16 => configurable); 224impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
225impl_ppi_channel!(PPI_CH17, 17 => configurable); 225impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
226impl_ppi_channel!(PPI_CH18, 18 => configurable); 226impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
227impl_ppi_channel!(PPI_CH19, 19 => configurable); 227impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
228impl_ppi_channel!(PPI_CH20, 20 => static); 228impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
229impl_ppi_channel!(PPI_CH21, 21 => static); 229impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
230impl_ppi_channel!(PPI_CH22, 22 => static); 230impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
231impl_ppi_channel!(PPI_CH23, 23 => static); 231impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
232impl_ppi_channel!(PPI_CH24, 24 => static); 232impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
233impl_ppi_channel!(PPI_CH25, 25 => static); 233impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
234impl_ppi_channel!(PPI_CH26, 26 => static); 234impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
235impl_ppi_channel!(PPI_CH27, 27 => static); 235impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
236impl_ppi_channel!(PPI_CH28, 28 => static); 236impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
237impl_ppi_channel!(PPI_CH29, 29 => static); 237impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
238impl_ppi_channel!(PPI_CH30, 30 => static); 238impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
239impl_ppi_channel!(PPI_CH31, 31 => static); 239impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
240
241impl_ppi_group!(PPI_GROUP0, PPI, 0);
242impl_ppi_group!(PPI_GROUP1, PPI, 1);
243impl_ppi_group!(PPI_GROUP2, PPI, 2);
244impl_ppi_group!(PPI_GROUP3, PPI, 3);
245impl_ppi_group!(PPI_GROUP4, PPI, 4);
246impl_ppi_group!(PPI_GROUP5, PPI, 5);
240 247
241impl_saadc_input!(P0_02, ANALOG_INPUT0); 248impl_saadc_input!(P0_02, ANALOG_INPUT0);
242impl_saadc_input!(P0_03, ANALOG_INPUT1); 249impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 908167e31..4178ef6cd 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -207,38 +207,45 @@ impl_pin!(P0_29, 0, 29);
207impl_pin!(P0_30, 0, 30); 207impl_pin!(P0_30, 0, 30);
208impl_pin!(P0_31, 0, 31); 208impl_pin!(P0_31, 0, 31);
209 209
210impl_ppi_channel!(PPI_CH0, 0 => configurable); 210impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
211impl_ppi_channel!(PPI_CH1, 1 => configurable); 211impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
212impl_ppi_channel!(PPI_CH2, 2 => configurable); 212impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
213impl_ppi_channel!(PPI_CH3, 3 => configurable); 213impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
214impl_ppi_channel!(PPI_CH4, 4 => configurable); 214impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
215impl_ppi_channel!(PPI_CH5, 5 => configurable); 215impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
216impl_ppi_channel!(PPI_CH6, 6 => configurable); 216impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
217impl_ppi_channel!(PPI_CH7, 7 => configurable); 217impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
218impl_ppi_channel!(PPI_CH8, 8 => configurable); 218impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
219impl_ppi_channel!(PPI_CH9, 9 => configurable); 219impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
220impl_ppi_channel!(PPI_CH10, 10 => configurable); 220impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
221impl_ppi_channel!(PPI_CH11, 11 => configurable); 221impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
222impl_ppi_channel!(PPI_CH12, 12 => configurable); 222impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
223impl_ppi_channel!(PPI_CH13, 13 => configurable); 223impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
224impl_ppi_channel!(PPI_CH14, 14 => configurable); 224impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
225impl_ppi_channel!(PPI_CH15, 15 => configurable); 225impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
226impl_ppi_channel!(PPI_CH16, 16 => configurable); 226impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
227impl_ppi_channel!(PPI_CH17, 17 => configurable); 227impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
228impl_ppi_channel!(PPI_CH18, 18 => configurable); 228impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
229impl_ppi_channel!(PPI_CH19, 19 => configurable); 229impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
230impl_ppi_channel!(PPI_CH20, 20 => static); 230impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
231impl_ppi_channel!(PPI_CH21, 21 => static); 231impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
232impl_ppi_channel!(PPI_CH22, 22 => static); 232impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
233impl_ppi_channel!(PPI_CH23, 23 => static); 233impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
234impl_ppi_channel!(PPI_CH24, 24 => static); 234impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
235impl_ppi_channel!(PPI_CH25, 25 => static); 235impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
236impl_ppi_channel!(PPI_CH26, 26 => static); 236impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
237impl_ppi_channel!(PPI_CH27, 27 => static); 237impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
238impl_ppi_channel!(PPI_CH28, 28 => static); 238impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
239impl_ppi_channel!(PPI_CH29, 29 => static); 239impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
240impl_ppi_channel!(PPI_CH30, 30 => static); 240impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
241impl_ppi_channel!(PPI_CH31, 31 => static); 241impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
242
243impl_ppi_group!(PPI_GROUP0, PPI, 0);
244impl_ppi_group!(PPI_GROUP1, PPI, 1);
245impl_ppi_group!(PPI_GROUP2, PPI, 2);
246impl_ppi_group!(PPI_GROUP3, PPI, 3);
247impl_ppi_group!(PPI_GROUP4, PPI, 4);
248impl_ppi_group!(PPI_GROUP5, PPI, 5);
242 249
243impl_saadc_input!(P0_02, ANALOG_INPUT0); 250impl_saadc_input!(P0_02, ANALOG_INPUT0);
244impl_saadc_input!(P0_03, ANALOG_INPUT1); 251impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 22360575b..32304b3ea 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -207,38 +207,45 @@ impl_pin!(P0_29, 0, 29);
207impl_pin!(P0_30, 0, 30); 207impl_pin!(P0_30, 0, 30);
208impl_pin!(P0_31, 0, 31); 208impl_pin!(P0_31, 0, 31);
209 209
210impl_ppi_channel!(PPI_CH0, 0 => configurable); 210impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
211impl_ppi_channel!(PPI_CH1, 1 => configurable); 211impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
212impl_ppi_channel!(PPI_CH2, 2 => configurable); 212impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
213impl_ppi_channel!(PPI_CH3, 3 => configurable); 213impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
214impl_ppi_channel!(PPI_CH4, 4 => configurable); 214impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
215impl_ppi_channel!(PPI_CH5, 5 => configurable); 215impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
216impl_ppi_channel!(PPI_CH6, 6 => configurable); 216impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
217impl_ppi_channel!(PPI_CH7, 7 => configurable); 217impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
218impl_ppi_channel!(PPI_CH8, 8 => configurable); 218impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
219impl_ppi_channel!(PPI_CH9, 9 => configurable); 219impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
220impl_ppi_channel!(PPI_CH10, 10 => configurable); 220impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
221impl_ppi_channel!(PPI_CH11, 11 => configurable); 221impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
222impl_ppi_channel!(PPI_CH12, 12 => configurable); 222impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
223impl_ppi_channel!(PPI_CH13, 13 => configurable); 223impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
224impl_ppi_channel!(PPI_CH14, 14 => configurable); 224impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
225impl_ppi_channel!(PPI_CH15, 15 => configurable); 225impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
226impl_ppi_channel!(PPI_CH16, 16 => configurable); 226impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
227impl_ppi_channel!(PPI_CH17, 17 => configurable); 227impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
228impl_ppi_channel!(PPI_CH18, 18 => configurable); 228impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
229impl_ppi_channel!(PPI_CH19, 19 => configurable); 229impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
230impl_ppi_channel!(PPI_CH20, 20 => static); 230impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
231impl_ppi_channel!(PPI_CH21, 21 => static); 231impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
232impl_ppi_channel!(PPI_CH22, 22 => static); 232impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
233impl_ppi_channel!(PPI_CH23, 23 => static); 233impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
234impl_ppi_channel!(PPI_CH24, 24 => static); 234impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
235impl_ppi_channel!(PPI_CH25, 25 => static); 235impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
236impl_ppi_channel!(PPI_CH26, 26 => static); 236impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
237impl_ppi_channel!(PPI_CH27, 27 => static); 237impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
238impl_ppi_channel!(PPI_CH28, 28 => static); 238impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
239impl_ppi_channel!(PPI_CH29, 29 => static); 239impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
240impl_ppi_channel!(PPI_CH30, 30 => static); 240impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
241impl_ppi_channel!(PPI_CH31, 31 => static); 241impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
242
243impl_ppi_group!(PPI_GROUP0, PPI, 0);
244impl_ppi_group!(PPI_GROUP1, PPI, 1);
245impl_ppi_group!(PPI_GROUP2, PPI, 2);
246impl_ppi_group!(PPI_GROUP3, PPI, 3);
247impl_ppi_group!(PPI_GROUP4, PPI, 4);
248impl_ppi_group!(PPI_GROUP5, PPI, 5);
242 249
243impl_radio!(RADIO, RADIO, RADIO); 250impl_radio!(RADIO, RADIO, RADIO);
244 251
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index 1598df3fe..06363a467 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -240,38 +240,45 @@ impl_pin!(P0_29, 0, 29);
240impl_pin!(P0_30, 0, 30); 240impl_pin!(P0_30, 0, 30);
241impl_pin!(P0_31, 0, 31); 241impl_pin!(P0_31, 0, 31);
242 242
243impl_ppi_channel!(PPI_CH0, 0 => configurable); 243impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
244impl_ppi_channel!(PPI_CH1, 1 => configurable); 244impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
245impl_ppi_channel!(PPI_CH2, 2 => configurable); 245impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
246impl_ppi_channel!(PPI_CH3, 3 => configurable); 246impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
247impl_ppi_channel!(PPI_CH4, 4 => configurable); 247impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
248impl_ppi_channel!(PPI_CH5, 5 => configurable); 248impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
249impl_ppi_channel!(PPI_CH6, 6 => configurable); 249impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
250impl_ppi_channel!(PPI_CH7, 7 => configurable); 250impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
251impl_ppi_channel!(PPI_CH8, 8 => configurable); 251impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
252impl_ppi_channel!(PPI_CH9, 9 => configurable); 252impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
253impl_ppi_channel!(PPI_CH10, 10 => configurable); 253impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
254impl_ppi_channel!(PPI_CH11, 11 => configurable); 254impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
255impl_ppi_channel!(PPI_CH12, 12 => configurable); 255impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
256impl_ppi_channel!(PPI_CH13, 13 => configurable); 256impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
257impl_ppi_channel!(PPI_CH14, 14 => configurable); 257impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
258impl_ppi_channel!(PPI_CH15, 15 => configurable); 258impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
259impl_ppi_channel!(PPI_CH16, 16 => configurable); 259impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
260impl_ppi_channel!(PPI_CH17, 17 => configurable); 260impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
261impl_ppi_channel!(PPI_CH18, 18 => configurable); 261impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
262impl_ppi_channel!(PPI_CH19, 19 => configurable); 262impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
263impl_ppi_channel!(PPI_CH20, 20 => static); 263impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
264impl_ppi_channel!(PPI_CH21, 21 => static); 264impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
265impl_ppi_channel!(PPI_CH22, 22 => static); 265impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
266impl_ppi_channel!(PPI_CH23, 23 => static); 266impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
267impl_ppi_channel!(PPI_CH24, 24 => static); 267impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
268impl_ppi_channel!(PPI_CH25, 25 => static); 268impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
269impl_ppi_channel!(PPI_CH26, 26 => static); 269impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
270impl_ppi_channel!(PPI_CH27, 27 => static); 270impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
271impl_ppi_channel!(PPI_CH28, 28 => static); 271impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
272impl_ppi_channel!(PPI_CH29, 29 => static); 272impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
273impl_ppi_channel!(PPI_CH30, 30 => static); 273impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
274impl_ppi_channel!(PPI_CH31, 31 => static); 274impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
275
276impl_ppi_group!(PPI_GROUP0, PPI, 0);
277impl_ppi_group!(PPI_GROUP1, PPI, 1);
278impl_ppi_group!(PPI_GROUP2, PPI, 2);
279impl_ppi_group!(PPI_GROUP3, PPI, 3);
280impl_ppi_group!(PPI_GROUP4, PPI, 4);
281impl_ppi_group!(PPI_GROUP5, PPI, 5);
275 282
276impl_saadc_input!(P0_02, ANALOG_INPUT0); 283impl_saadc_input!(P0_02, ANALOG_INPUT0);
277impl_saadc_input!(P0_03, ANALOG_INPUT1); 284impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 6931fb064..754943d33 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -282,38 +282,45 @@ impl_pin!(P1_13, 1, 13);
282impl_pin!(P1_14, 1, 14); 282impl_pin!(P1_14, 1, 14);
283impl_pin!(P1_15, 1, 15); 283impl_pin!(P1_15, 1, 15);
284 284
285impl_ppi_channel!(PPI_CH0, 0 => configurable); 285impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
286impl_ppi_channel!(PPI_CH1, 1 => configurable); 286impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
287impl_ppi_channel!(PPI_CH2, 2 => configurable); 287impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
288impl_ppi_channel!(PPI_CH3, 3 => configurable); 288impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
289impl_ppi_channel!(PPI_CH4, 4 => configurable); 289impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
290impl_ppi_channel!(PPI_CH5, 5 => configurable); 290impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
291impl_ppi_channel!(PPI_CH6, 6 => configurable); 291impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
292impl_ppi_channel!(PPI_CH7, 7 => configurable); 292impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
293impl_ppi_channel!(PPI_CH8, 8 => configurable); 293impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
294impl_ppi_channel!(PPI_CH9, 9 => configurable); 294impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
295impl_ppi_channel!(PPI_CH10, 10 => configurable); 295impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
296impl_ppi_channel!(PPI_CH11, 11 => configurable); 296impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
297impl_ppi_channel!(PPI_CH12, 12 => configurable); 297impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
298impl_ppi_channel!(PPI_CH13, 13 => configurable); 298impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
299impl_ppi_channel!(PPI_CH14, 14 => configurable); 299impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
300impl_ppi_channel!(PPI_CH15, 15 => configurable); 300impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
301impl_ppi_channel!(PPI_CH16, 16 => configurable); 301impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
302impl_ppi_channel!(PPI_CH17, 17 => configurable); 302impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
303impl_ppi_channel!(PPI_CH18, 18 => configurable); 303impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
304impl_ppi_channel!(PPI_CH19, 19 => configurable); 304impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
305impl_ppi_channel!(PPI_CH20, 20 => static); 305impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
306impl_ppi_channel!(PPI_CH21, 21 => static); 306impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
307impl_ppi_channel!(PPI_CH22, 22 => static); 307impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
308impl_ppi_channel!(PPI_CH23, 23 => static); 308impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
309impl_ppi_channel!(PPI_CH24, 24 => static); 309impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
310impl_ppi_channel!(PPI_CH25, 25 => static); 310impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
311impl_ppi_channel!(PPI_CH26, 26 => static); 311impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
312impl_ppi_channel!(PPI_CH27, 27 => static); 312impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
313impl_ppi_channel!(PPI_CH28, 28 => static); 313impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
314impl_ppi_channel!(PPI_CH29, 29 => static); 314impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
315impl_ppi_channel!(PPI_CH30, 30 => static); 315impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
316impl_ppi_channel!(PPI_CH31, 31 => static); 316impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
317
318impl_ppi_group!(PPI_GROUP0, PPI, 0);
319impl_ppi_group!(PPI_GROUP1, PPI, 1);
320impl_ppi_group!(PPI_GROUP2, PPI, 2);
321impl_ppi_group!(PPI_GROUP3, PPI, 3);
322impl_ppi_group!(PPI_GROUP4, PPI, 4);
323impl_ppi_group!(PPI_GROUP5, PPI, 5);
317 324
318impl_saadc_input!(P0_02, ANALOG_INPUT0); 325impl_saadc_input!(P0_02, ANALOG_INPUT0);
319impl_saadc_input!(P0_03, ANALOG_INPUT1); 326impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 5fa521aae..ac07cd820 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -287,38 +287,45 @@ impl_pin!(P1_13, 1, 13);
287impl_pin!(P1_14, 1, 14); 287impl_pin!(P1_14, 1, 14);
288impl_pin!(P1_15, 1, 15); 288impl_pin!(P1_15, 1, 15);
289 289
290impl_ppi_channel!(PPI_CH0, 0 => configurable); 290impl_ppi_channel!(PPI_CH0, PPI, 0 => configurable);
291impl_ppi_channel!(PPI_CH1, 1 => configurable); 291impl_ppi_channel!(PPI_CH1, PPI, 1 => configurable);
292impl_ppi_channel!(PPI_CH2, 2 => configurable); 292impl_ppi_channel!(PPI_CH2, PPI, 2 => configurable);
293impl_ppi_channel!(PPI_CH3, 3 => configurable); 293impl_ppi_channel!(PPI_CH3, PPI, 3 => configurable);
294impl_ppi_channel!(PPI_CH4, 4 => configurable); 294impl_ppi_channel!(PPI_CH4, PPI, 4 => configurable);
295impl_ppi_channel!(PPI_CH5, 5 => configurable); 295impl_ppi_channel!(PPI_CH5, PPI, 5 => configurable);
296impl_ppi_channel!(PPI_CH6, 6 => configurable); 296impl_ppi_channel!(PPI_CH6, PPI, 6 => configurable);
297impl_ppi_channel!(PPI_CH7, 7 => configurable); 297impl_ppi_channel!(PPI_CH7, PPI, 7 => configurable);
298impl_ppi_channel!(PPI_CH8, 8 => configurable); 298impl_ppi_channel!(PPI_CH8, PPI, 8 => configurable);
299impl_ppi_channel!(PPI_CH9, 9 => configurable); 299impl_ppi_channel!(PPI_CH9, PPI, 9 => configurable);
300impl_ppi_channel!(PPI_CH10, 10 => configurable); 300impl_ppi_channel!(PPI_CH10, PPI, 10 => configurable);
301impl_ppi_channel!(PPI_CH11, 11 => configurable); 301impl_ppi_channel!(PPI_CH11, PPI, 11 => configurable);
302impl_ppi_channel!(PPI_CH12, 12 => configurable); 302impl_ppi_channel!(PPI_CH12, PPI, 12 => configurable);
303impl_ppi_channel!(PPI_CH13, 13 => configurable); 303impl_ppi_channel!(PPI_CH13, PPI, 13 => configurable);
304impl_ppi_channel!(PPI_CH14, 14 => configurable); 304impl_ppi_channel!(PPI_CH14, PPI, 14 => configurable);
305impl_ppi_channel!(PPI_CH15, 15 => configurable); 305impl_ppi_channel!(PPI_CH15, PPI, 15 => configurable);
306impl_ppi_channel!(PPI_CH16, 16 => configurable); 306impl_ppi_channel!(PPI_CH16, PPI, 16 => configurable);
307impl_ppi_channel!(PPI_CH17, 17 => configurable); 307impl_ppi_channel!(PPI_CH17, PPI, 17 => configurable);
308impl_ppi_channel!(PPI_CH18, 18 => configurable); 308impl_ppi_channel!(PPI_CH18, PPI, 18 => configurable);
309impl_ppi_channel!(PPI_CH19, 19 => configurable); 309impl_ppi_channel!(PPI_CH19, PPI, 19 => configurable);
310impl_ppi_channel!(PPI_CH20, 20 => static); 310impl_ppi_channel!(PPI_CH20, PPI, 20 => static);
311impl_ppi_channel!(PPI_CH21, 21 => static); 311impl_ppi_channel!(PPI_CH21, PPI, 21 => static);
312impl_ppi_channel!(PPI_CH22, 22 => static); 312impl_ppi_channel!(PPI_CH22, PPI, 22 => static);
313impl_ppi_channel!(PPI_CH23, 23 => static); 313impl_ppi_channel!(PPI_CH23, PPI, 23 => static);
314impl_ppi_channel!(PPI_CH24, 24 => static); 314impl_ppi_channel!(PPI_CH24, PPI, 24 => static);
315impl_ppi_channel!(PPI_CH25, 25 => static); 315impl_ppi_channel!(PPI_CH25, PPI, 25 => static);
316impl_ppi_channel!(PPI_CH26, 26 => static); 316impl_ppi_channel!(PPI_CH26, PPI, 26 => static);
317impl_ppi_channel!(PPI_CH27, 27 => static); 317impl_ppi_channel!(PPI_CH27, PPI, 27 => static);
318impl_ppi_channel!(PPI_CH28, 28 => static); 318impl_ppi_channel!(PPI_CH28, PPI, 28 => static);
319impl_ppi_channel!(PPI_CH29, 29 => static); 319impl_ppi_channel!(PPI_CH29, PPI, 29 => static);
320impl_ppi_channel!(PPI_CH30, 30 => static); 320impl_ppi_channel!(PPI_CH30, PPI, 30 => static);
321impl_ppi_channel!(PPI_CH31, 31 => static); 321impl_ppi_channel!(PPI_CH31, PPI, 31 => static);
322
323impl_ppi_group!(PPI_GROUP0, PPI, 0);
324impl_ppi_group!(PPI_GROUP1, PPI, 1);
325impl_ppi_group!(PPI_GROUP2, PPI, 2);
326impl_ppi_group!(PPI_GROUP3, PPI, 3);
327impl_ppi_group!(PPI_GROUP4, PPI, 4);
328impl_ppi_group!(PPI_GROUP5, PPI, 5);
322 329
323impl_saadc_input!(P0_02, ANALOG_INPUT0); 330impl_saadc_input!(P0_02, ANALOG_INPUT0);
324impl_saadc_input!(P0_03, ANALOG_INPUT1); 331impl_saadc_input!(P0_03, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 730c9842d..aa51527fb 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -435,38 +435,45 @@ impl_pin!(P1_13, 1, 13);
435impl_pin!(P1_14, 1, 14); 435impl_pin!(P1_14, 1, 14);
436impl_pin!(P1_15, 1, 15); 436impl_pin!(P1_15, 1, 15);
437 437
438impl_ppi_channel!(PPI_CH0, 0 => configurable); 438impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
439impl_ppi_channel!(PPI_CH1, 1 => configurable); 439impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
440impl_ppi_channel!(PPI_CH2, 2 => configurable); 440impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
441impl_ppi_channel!(PPI_CH3, 3 => configurable); 441impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
442impl_ppi_channel!(PPI_CH4, 4 => configurable); 442impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
443impl_ppi_channel!(PPI_CH5, 5 => configurable); 443impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
444impl_ppi_channel!(PPI_CH6, 6 => configurable); 444impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
445impl_ppi_channel!(PPI_CH7, 7 => configurable); 445impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
446impl_ppi_channel!(PPI_CH8, 8 => configurable); 446impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
447impl_ppi_channel!(PPI_CH9, 9 => configurable); 447impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
448impl_ppi_channel!(PPI_CH10, 10 => configurable); 448impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
449impl_ppi_channel!(PPI_CH11, 11 => configurable); 449impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
450impl_ppi_channel!(PPI_CH12, 12 => configurable); 450impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
451impl_ppi_channel!(PPI_CH13, 13 => configurable); 451impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
452impl_ppi_channel!(PPI_CH14, 14 => configurable); 452impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
453impl_ppi_channel!(PPI_CH15, 15 => configurable); 453impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
454impl_ppi_channel!(PPI_CH16, 16 => configurable); 454impl_ppi_channel!(PPI_CH16, DPPIC, 16 => configurable);
455impl_ppi_channel!(PPI_CH17, 17 => configurable); 455impl_ppi_channel!(PPI_CH17, DPPIC, 17 => configurable);
456impl_ppi_channel!(PPI_CH18, 18 => configurable); 456impl_ppi_channel!(PPI_CH18, DPPIC, 18 => configurable);
457impl_ppi_channel!(PPI_CH19, 19 => configurable); 457impl_ppi_channel!(PPI_CH19, DPPIC, 19 => configurable);
458impl_ppi_channel!(PPI_CH20, 20 => configurable); 458impl_ppi_channel!(PPI_CH20, DPPIC, 20 => configurable);
459impl_ppi_channel!(PPI_CH21, 21 => configurable); 459impl_ppi_channel!(PPI_CH21, DPPIC, 21 => configurable);
460impl_ppi_channel!(PPI_CH22, 22 => configurable); 460impl_ppi_channel!(PPI_CH22, DPPIC, 22 => configurable);
461impl_ppi_channel!(PPI_CH23, 23 => configurable); 461impl_ppi_channel!(PPI_CH23, DPPIC, 23 => configurable);
462impl_ppi_channel!(PPI_CH24, 24 => configurable); 462impl_ppi_channel!(PPI_CH24, DPPIC, 24 => configurable);
463impl_ppi_channel!(PPI_CH25, 25 => configurable); 463impl_ppi_channel!(PPI_CH25, DPPIC, 25 => configurable);
464impl_ppi_channel!(PPI_CH26, 26 => configurable); 464impl_ppi_channel!(PPI_CH26, DPPIC, 26 => configurable);
465impl_ppi_channel!(PPI_CH27, 27 => configurable); 465impl_ppi_channel!(PPI_CH27, DPPIC, 27 => configurable);
466impl_ppi_channel!(PPI_CH28, 28 => configurable); 466impl_ppi_channel!(PPI_CH28, DPPIC, 28 => configurable);
467impl_ppi_channel!(PPI_CH29, 29 => configurable); 467impl_ppi_channel!(PPI_CH29, DPPIC, 29 => configurable);
468impl_ppi_channel!(PPI_CH30, 30 => configurable); 468impl_ppi_channel!(PPI_CH30, DPPIC, 30 => configurable);
469impl_ppi_channel!(PPI_CH31, 31 => configurable); 469impl_ppi_channel!(PPI_CH31, DPPIC, 31 => configurable);
470
471impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
472impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
473impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
474impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
475impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
476impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
470 477
471impl_saadc_input!(P0_04, ANALOG_INPUT0); 478impl_saadc_input!(P0_04, ANALOG_INPUT0);
472impl_saadc_input!(P0_05, ANALOG_INPUT1); 479impl_saadc_input!(P0_05, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index 413afc5c5..2207e7bda 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -275,38 +275,45 @@ impl_pin!(P1_13, 1, 13);
275impl_pin!(P1_14, 1, 14); 275impl_pin!(P1_14, 1, 14);
276impl_pin!(P1_15, 1, 15); 276impl_pin!(P1_15, 1, 15);
277 277
278impl_ppi_channel!(PPI_CH0, 0 => configurable); 278impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
279impl_ppi_channel!(PPI_CH1, 1 => configurable); 279impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
280impl_ppi_channel!(PPI_CH2, 2 => configurable); 280impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
281impl_ppi_channel!(PPI_CH3, 3 => configurable); 281impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
282impl_ppi_channel!(PPI_CH4, 4 => configurable); 282impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
283impl_ppi_channel!(PPI_CH5, 5 => configurable); 283impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
284impl_ppi_channel!(PPI_CH6, 6 => configurable); 284impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
285impl_ppi_channel!(PPI_CH7, 7 => configurable); 285impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
286impl_ppi_channel!(PPI_CH8, 8 => configurable); 286impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
287impl_ppi_channel!(PPI_CH9, 9 => configurable); 287impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
288impl_ppi_channel!(PPI_CH10, 10 => configurable); 288impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
289impl_ppi_channel!(PPI_CH11, 11 => configurable); 289impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
290impl_ppi_channel!(PPI_CH12, 12 => configurable); 290impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
291impl_ppi_channel!(PPI_CH13, 13 => configurable); 291impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
292impl_ppi_channel!(PPI_CH14, 14 => configurable); 292impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
293impl_ppi_channel!(PPI_CH15, 15 => configurable); 293impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
294impl_ppi_channel!(PPI_CH16, 16 => configurable); 294impl_ppi_channel!(PPI_CH16, DPPIC, 16 => configurable);
295impl_ppi_channel!(PPI_CH17, 17 => configurable); 295impl_ppi_channel!(PPI_CH17, DPPIC, 17 => configurable);
296impl_ppi_channel!(PPI_CH18, 18 => configurable); 296impl_ppi_channel!(PPI_CH18, DPPIC, 18 => configurable);
297impl_ppi_channel!(PPI_CH19, 19 => configurable); 297impl_ppi_channel!(PPI_CH19, DPPIC, 19 => configurable);
298impl_ppi_channel!(PPI_CH20, 20 => configurable); 298impl_ppi_channel!(PPI_CH20, DPPIC, 20 => configurable);
299impl_ppi_channel!(PPI_CH21, 21 => configurable); 299impl_ppi_channel!(PPI_CH21, DPPIC, 21 => configurable);
300impl_ppi_channel!(PPI_CH22, 22 => configurable); 300impl_ppi_channel!(PPI_CH22, DPPIC, 22 => configurable);
301impl_ppi_channel!(PPI_CH23, 23 => configurable); 301impl_ppi_channel!(PPI_CH23, DPPIC, 23 => configurable);
302impl_ppi_channel!(PPI_CH24, 24 => configurable); 302impl_ppi_channel!(PPI_CH24, DPPIC, 24 => configurable);
303impl_ppi_channel!(PPI_CH25, 25 => configurable); 303impl_ppi_channel!(PPI_CH25, DPPIC, 25 => configurable);
304impl_ppi_channel!(PPI_CH26, 26 => configurable); 304impl_ppi_channel!(PPI_CH26, DPPIC, 26 => configurable);
305impl_ppi_channel!(PPI_CH27, 27 => configurable); 305impl_ppi_channel!(PPI_CH27, DPPIC, 27 => configurable);
306impl_ppi_channel!(PPI_CH28, 28 => configurable); 306impl_ppi_channel!(PPI_CH28, DPPIC, 28 => configurable);
307impl_ppi_channel!(PPI_CH29, 29 => configurable); 307impl_ppi_channel!(PPI_CH29, DPPIC, 29 => configurable);
308impl_ppi_channel!(PPI_CH30, 30 => configurable); 308impl_ppi_channel!(PPI_CH30, DPPIC, 30 => configurable);
309impl_ppi_channel!(PPI_CH31, 31 => configurable); 309impl_ppi_channel!(PPI_CH31, DPPIC, 31 => configurable);
310
311impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
312impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
313impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
314impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
315impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
316impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
310 317
311impl_radio!(RADIO, RADIO, RADIO); 318impl_radio!(RADIO, RADIO, RADIO);
312 319
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs
index 82d30104f..0724f2ff6 100644
--- a/embassy-nrf/src/chips/nrf54l15_app.rs
+++ b/embassy-nrf/src/chips/nrf54l15_app.rs
@@ -200,13 +200,180 @@ pub mod pac {
200 200
201/// The maximum buffer size that the EasyDMA can send/recv in one operation. 201/// The maximum buffer size that the EasyDMA can send/recv in one operation.
202pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; 202pub const EASY_DMA_SIZE: usize = (1 << 16) - 1;
203//pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; 203pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
204 204
205// 1.5 MB NVM 205// 1.5 MB NVM
206#[allow(unused)] 206#[allow(unused)]
207pub const FLASH_SIZE: usize = 1536 * 1024; 207pub const FLASH_SIZE: usize = 1536 * 1024;
208 208
209embassy_hal_internal::peripherals! { 209embassy_hal_internal::peripherals! {
210 // PPI
211 PPI00_CH0,
212 PPI00_CH1,
213 PPI00_CH2,
214 PPI00_CH3,
215 PPI00_CH4,
216 PPI00_CH5,
217 PPI00_CH6,
218 PPI00_CH7,
219
220 PPI10_CH0,
221 PPI10_CH1,
222 PPI10_CH2,
223 PPI10_CH3,
224 PPI10_CH4,
225 PPI10_CH5,
226 PPI10_CH6,
227 PPI10_CH7,
228 PPI10_CH8,
229 PPI10_CH9,
230 PPI10_CH10,
231 PPI10_CH11,
232 PPI10_CH12,
233 PPI10_CH13,
234 PPI10_CH14,
235 PPI10_CH15,
236 PPI10_CH16,
237 PPI10_CH17,
238 PPI10_CH18,
239 PPI10_CH19,
240 PPI10_CH20,
241 PPI10_CH21,
242 PPI10_CH22,
243 PPI10_CH23,
244
245 PPI20_CH0,
246 PPI20_CH1,
247 PPI20_CH2,
248 PPI20_CH3,
249 PPI20_CH4,
250 PPI20_CH5,
251 PPI20_CH6,
252 PPI20_CH7,
253 PPI20_CH8,
254 PPI20_CH9,
255 PPI20_CH10,
256 PPI20_CH11,
257 PPI20_CH12,
258 PPI20_CH13,
259 PPI20_CH14,
260 PPI20_CH15,
261
262 PPI30_CH0,
263 PPI30_CH1,
264 PPI30_CH2,
265 PPI30_CH3,
266
267 PPI00_GROUP0,
268 PPI00_GROUP1,
269
270 PPI10_GROUP0,
271 PPI10_GROUP1,
272 PPI10_GROUP2,
273 PPI10_GROUP3,
274 PPI10_GROUP4,
275 PPI10_GROUP5,
276
277 PPI20_GROUP0,
278 PPI20_GROUP1,
279 PPI20_GROUP2,
280 PPI20_GROUP3,
281 PPI20_GROUP4,
282 PPI20_GROUP5,
283
284 PPI30_GROUP0,
285 PPI30_GROUP1,
286
287 // PPI BRIDGE channels
288 PPIB00_CH0,
289 PPIB00_CH1,
290 PPIB00_CH2,
291 PPIB00_CH3,
292 PPIB00_CH4,
293 PPIB00_CH5,
294 PPIB00_CH6,
295 PPIB00_CH7,
296
297 PPIB01_CH0,
298 PPIB01_CH1,
299 PPIB01_CH2,
300 PPIB01_CH3,
301 PPIB01_CH4,
302 PPIB01_CH5,
303 PPIB01_CH6,
304 PPIB01_CH7,
305
306 PPIB10_CH0,
307 PPIB10_CH1,
308 PPIB10_CH2,
309 PPIB10_CH3,
310 PPIB10_CH4,
311 PPIB10_CH5,
312 PPIB10_CH6,
313 PPIB10_CH7,
314
315 PPIB11_CH0,
316 PPIB11_CH1,
317 PPIB11_CH2,
318 PPIB11_CH3,
319 PPIB11_CH4,
320 PPIB11_CH5,
321 PPIB11_CH6,
322 PPIB11_CH7,
323 PPIB11_CH8,
324 PPIB11_CH9,
325 PPIB11_CH10,
326 PPIB11_CH11,
327 PPIB11_CH12,
328 PPIB11_CH13,
329 PPIB11_CH14,
330 PPIB11_CH15,
331
332 PPIB20_CH0,
333 PPIB20_CH1,
334 PPIB20_CH2,
335 PPIB20_CH3,
336 PPIB20_CH4,
337 PPIB20_CH5,
338 PPIB20_CH6,
339 PPIB20_CH7,
340
341 PPIB21_CH0,
342 PPIB21_CH1,
343 PPIB21_CH2,
344 PPIB21_CH3,
345 PPIB21_CH4,
346 PPIB21_CH5,
347 PPIB21_CH6,
348 PPIB21_CH7,
349 PPIB21_CH8,
350 PPIB21_CH9,
351 PPIB21_CH10,
352 PPIB21_CH11,
353 PPIB21_CH12,
354 PPIB21_CH13,
355 PPIB21_CH14,
356 PPIB21_CH15,
357
358 PPIB22_CH0,
359 PPIB22_CH1,
360 PPIB22_CH2,
361 PPIB22_CH3,
362
363 PPIB30_CH0,
364 PPIB30_CH1,
365 PPIB30_CH2,
366 PPIB30_CH3,
367
368 // Timers
369 TIMER00,
370 TIMER10,
371 TIMER20,
372 TIMER21,
373 TIMER22,
374 TIMER23,
375 TIMER24,
376
210 // GPIO port 0 377 // GPIO port 0
211 P0_00, 378 P0_00,
212 P0_01, 379 P0_01,
@@ -249,6 +416,54 @@ embassy_hal_internal::peripherals! {
249 P2_09, 416 P2_09,
250 P2_10, 417 P2_10,
251 418
419 // GRTC
420 GRTC,
421
422 // RTC
423 RTC10,
424 RTC30,
425
426 // PWM
427 PWM20,
428 PWM21,
429 PWM22,
430
431 // SERIAL
432 SERIAL00,
433 SERIAL20,
434 SERIAL21,
435 SERIAL22,
436 SERIAL30,
437
438 // SAADC
439 SAADC,
440
441 // RADIO
442 RADIO,
443
444
445 // GPIOTE instances
446 GPIOTE20,
447 GPIOTE30,
448
449 // GPIOTE channels
450 GPIOTE20_CH0,
451 GPIOTE20_CH1,
452 GPIOTE20_CH2,
453 GPIOTE20_CH3,
454 GPIOTE20_CH4,
455 GPIOTE20_CH5,
456 GPIOTE20_CH6,
457 GPIOTE20_CH7,
458 GPIOTE30_CH0,
459 GPIOTE30_CH1,
460 GPIOTE30_CH2,
461 GPIOTE30_CH3,
462
463 // CRACEN
464 #[cfg(feature = "_s")]
465 CRACEN,
466
252 #[cfg(feature = "_s")] 467 #[cfg(feature = "_s")]
253 // RRAMC 468 // RRAMC
254 RRAMC, 469 RRAMC,
@@ -303,12 +518,173 @@ impl_pin!(P2_08, 2, 8);
303impl_pin!(P2_09, 2, 9); 518impl_pin!(P2_09, 2, 9);
304impl_pin!(P2_10, 2, 10); 519impl_pin!(P2_10, 2, 10);
305 520
521cfg_if::cfg_if! {
522 if #[cfg(feature = "gpiote")] {
523 impl_gpiote_pin!(P0_00, GPIOTE30);
524 impl_gpiote_pin!(P0_01, GPIOTE30);
525 impl_gpiote_pin!(P0_02, GPIOTE30);
526 impl_gpiote_pin!(P0_03, GPIOTE30);
527 impl_gpiote_pin!(P0_04, GPIOTE30);
528 impl_gpiote_pin!(P0_05, GPIOTE30);
529 impl_gpiote_pin!(P0_06, GPIOTE30);
530
531 impl_gpiote_pin!(P1_00, GPIOTE20);
532 impl_gpiote_pin!(P1_01, GPIOTE20);
533 impl_gpiote_pin!(P1_02, GPIOTE20);
534 impl_gpiote_pin!(P1_03, GPIOTE20);
535 impl_gpiote_pin!(P1_04, GPIOTE20);
536 impl_gpiote_pin!(P1_05, GPIOTE20);
537 impl_gpiote_pin!(P1_06, GPIOTE20);
538 impl_gpiote_pin!(P1_07, GPIOTE20);
539 impl_gpiote_pin!(P1_08, GPIOTE20);
540 impl_gpiote_pin!(P1_09, GPIOTE20);
541 impl_gpiote_pin!(P1_10, GPIOTE20);
542 impl_gpiote_pin!(P1_11, GPIOTE20);
543 impl_gpiote_pin!(P1_12, GPIOTE20);
544 impl_gpiote_pin!(P1_13, GPIOTE20);
545 impl_gpiote_pin!(P1_14, GPIOTE20);
546 impl_gpiote_pin!(P1_15, GPIOTE20);
547 impl_gpiote_pin!(P1_16, GPIOTE20);
548 }
549}
550
551impl_rtc!(RTC10, RTC10, RTC10);
552impl_rtc!(RTC30, RTC30, RTC30);
553
306#[cfg(feature = "_ns")] 554#[cfg(feature = "_ns")]
307impl_wdt!(WDT, WDT31, WDT31, 0); 555impl_wdt!(WDT, WDT31, WDT31, 0);
308#[cfg(feature = "_s")] 556#[cfg(feature = "_s")]
309impl_wdt!(WDT0, WDT31, WDT31, 0); 557impl_wdt!(WDT0, WDT31, WDT31, 0);
310#[cfg(feature = "_s")] 558#[cfg(feature = "_s")]
311impl_wdt!(WDT1, WDT30, WDT30, 1); 559impl_wdt!(WDT1, WDT30, WDT30, 1);
560// DPPI00 channels
561impl_ppi_channel!(PPI00_CH0, DPPIC00, 0 => configurable);
562impl_ppi_channel!(PPI00_CH1, DPPIC00, 1 => configurable);
563impl_ppi_channel!(PPI00_CH2, DPPIC00, 2 => configurable);
564impl_ppi_channel!(PPI00_CH3, DPPIC00, 3 => configurable);
565impl_ppi_channel!(PPI00_CH4, DPPIC00, 4 => configurable);
566impl_ppi_channel!(PPI00_CH5, DPPIC00, 5 => configurable);
567impl_ppi_channel!(PPI00_CH6, DPPIC00, 6 => configurable);
568impl_ppi_channel!(PPI00_CH7, DPPIC00, 7 => configurable);
569
570// DPPI10 channels
571impl_ppi_channel!(PPI10_CH0, DPPIC10, 0 => static);
572
573// DPPI20 channels
574impl_ppi_channel!(PPI20_CH0, DPPIC20, 0 => configurable);
575impl_ppi_channel!(PPI20_CH1, DPPIC20, 1 => configurable);
576impl_ppi_channel!(PPI20_CH2, DPPIC20, 2 => configurable);
577impl_ppi_channel!(PPI20_CH3, DPPIC20, 3 => configurable);
578impl_ppi_channel!(PPI20_CH4, DPPIC20, 4 => configurable);
579impl_ppi_channel!(PPI20_CH5, DPPIC20, 5 => configurable);
580impl_ppi_channel!(PPI20_CH6, DPPIC20, 6 => configurable);
581impl_ppi_channel!(PPI20_CH7, DPPIC20, 7 => configurable);
582impl_ppi_channel!(PPI20_CH8, DPPIC20, 8 => configurable);
583impl_ppi_channel!(PPI20_CH9, DPPIC20, 9 => configurable);
584impl_ppi_channel!(PPI20_CH10, DPPIC20, 10 => configurable);
585impl_ppi_channel!(PPI20_CH11, DPPIC20, 11 => configurable);
586impl_ppi_channel!(PPI20_CH12, DPPIC20, 12 => configurable);
587impl_ppi_channel!(PPI20_CH13, DPPIC20, 13 => configurable);
588impl_ppi_channel!(PPI20_CH14, DPPIC20, 14 => configurable);
589impl_ppi_channel!(PPI20_CH15, DPPIC20, 15 => configurable);
590
591// DPPI30 channels
592impl_ppi_channel!(PPI30_CH0, DPPIC30, 0 => configurable);
593impl_ppi_channel!(PPI30_CH1, DPPIC30, 1 => configurable);
594impl_ppi_channel!(PPI30_CH2, DPPIC30, 2 => configurable);
595impl_ppi_channel!(PPI30_CH3, DPPIC30, 3 => configurable);
596
597// DPPI00 groups
598impl_ppi_group!(PPI00_GROUP0, DPPIC00, 0);
599impl_ppi_group!(PPI00_GROUP1, DPPIC00, 1);
600
601// DPPI10 groups
602impl_ppi_group!(PPI10_GROUP0, DPPIC10, 0);
603
604// DPPI20 groups
605impl_ppi_group!(PPI20_GROUP0, DPPIC20, 0);
606impl_ppi_group!(PPI20_GROUP1, DPPIC20, 1);
607impl_ppi_group!(PPI20_GROUP2, DPPIC20, 2);
608impl_ppi_group!(PPI20_GROUP3, DPPIC20, 3);
609impl_ppi_group!(PPI20_GROUP4, DPPIC20, 4);
610impl_ppi_group!(PPI20_GROUP5, DPPIC20, 5);
611
612// DPPI30 groups
613impl_ppi_group!(PPI30_GROUP0, DPPIC30, 0);
614impl_ppi_group!(PPI30_GROUP1, DPPIC30, 1);
615
616impl_timer!(TIMER00, TIMER00, TIMER00);
617impl_timer!(TIMER10, TIMER10, TIMER10);
618impl_timer!(TIMER20, TIMER20, TIMER20);
619impl_timer!(TIMER21, TIMER21, TIMER21);
620impl_timer!(TIMER22, TIMER22, TIMER22);
621impl_timer!(TIMER23, TIMER23, TIMER23);
622impl_timer!(TIMER24, TIMER24, TIMER24);
623
624impl_twim!(SERIAL20, TWIM20, SERIAL20);
625impl_twim!(SERIAL21, TWIM21, SERIAL21);
626impl_twim!(SERIAL22, TWIM22, SERIAL22);
627impl_twim!(SERIAL30, TWIM30, SERIAL30);
628
629impl_twis!(SERIAL20, TWIS20, SERIAL20);
630impl_twis!(SERIAL21, TWIS21, SERIAL21);
631impl_twis!(SERIAL22, TWIS22, SERIAL22);
632impl_twis!(SERIAL30, TWIS30, SERIAL30);
633
634impl_pwm!(PWM20, PWM20, PWM20);
635impl_pwm!(PWM21, PWM21, PWM21);
636impl_pwm!(PWM22, PWM22, PWM22);
637
638#[cfg(feature = "_s")]
639impl_spim!(
640 SERIAL00,
641 SPIM00,
642 SERIAL00,
643 match pac::OSCILLATORS_S.pll().currentfreq().read().currentfreq() {
644 pac::oscillators::vals::Currentfreq::CK128M => 128_000_000,
645 pac::oscillators::vals::Currentfreq::CK64M => 64_000_000,
646 _ => unreachable!(),
647 }
648);
649#[cfg(feature = "_ns")]
650impl_spim!(
651 SERIAL00,
652 SPIM00,
653 SERIAL00,
654 match pac::OSCILLATORS_NS.pll().currentfreq().read().currentfreq() {
655 pac::oscillators::vals::Currentfreq::CK128M => 128_000_000,
656 pac::oscillators::vals::Currentfreq::CK64M => 64_000_000,
657 _ => unreachable!(),
658 }
659);
660impl_spim!(SERIAL20, SPIM20, SERIAL20, 16_000_000);
661impl_spim!(SERIAL21, SPIM21, SERIAL21, 16_000_000);
662impl_spim!(SERIAL22, SPIM22, SERIAL22, 16_000_000);
663impl_spim!(SERIAL30, SPIM30, SERIAL30, 16_000_000);
664
665impl_spis!(SERIAL20, SPIS20, SERIAL20);
666impl_spis!(SERIAL21, SPIS21, SERIAL21);
667impl_spis!(SERIAL22, SPIS22, SERIAL22);
668impl_spis!(SERIAL30, SPIS30, SERIAL30);
669
670impl_uarte!(SERIAL00, UARTE00, SERIAL00);
671impl_uarte!(SERIAL20, UARTE20, SERIAL20);
672impl_uarte!(SERIAL21, UARTE21, SERIAL21);
673impl_uarte!(SERIAL22, UARTE22, SERIAL22);
674impl_uarte!(SERIAL30, UARTE30, SERIAL30);
675
676// NB: SAADC uses "pin" abstraction, not "AIN"
677impl_saadc_input!(P1_04, 1, 4);
678impl_saadc_input!(P1_05, 1, 5);
679impl_saadc_input!(P1_06, 1, 6);
680impl_saadc_input!(P1_07, 1, 7);
681impl_saadc_input!(P1_11, 1, 11);
682impl_saadc_input!(P1_12, 1, 12);
683impl_saadc_input!(P1_13, 1, 13);
684impl_saadc_input!(P1_14, 1, 14);
685
686#[cfg(feature = "_s")]
687impl_cracen!(CRACEN, CRACEN, CRACEN);
312 688
313embassy_hal_internal::interrupt_mod!( 689embassy_hal_internal::interrupt_mod!(
314 SWI00, 690 SWI00,
diff --git a/embassy-nrf/src/chips/nrf9120.rs b/embassy-nrf/src/chips/nrf9120.rs
index 5aee19d97..e9f313fef 100644
--- a/embassy-nrf/src/chips/nrf9120.rs
+++ b/embassy-nrf/src/chips/nrf9120.rs
@@ -314,22 +314,29 @@ impl_pin!(P0_29, 0, 29);
314impl_pin!(P0_30, 0, 30); 314impl_pin!(P0_30, 0, 30);
315impl_pin!(P0_31, 0, 31); 315impl_pin!(P0_31, 0, 31);
316 316
317impl_ppi_channel!(PPI_CH0, 0 => configurable); 317impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
318impl_ppi_channel!(PPI_CH1, 1 => configurable); 318impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
319impl_ppi_channel!(PPI_CH2, 2 => configurable); 319impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
320impl_ppi_channel!(PPI_CH3, 3 => configurable); 320impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
321impl_ppi_channel!(PPI_CH4, 4 => configurable); 321impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
322impl_ppi_channel!(PPI_CH5, 5 => configurable); 322impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
323impl_ppi_channel!(PPI_CH6, 6 => configurable); 323impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
324impl_ppi_channel!(PPI_CH7, 7 => configurable); 324impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
325impl_ppi_channel!(PPI_CH8, 8 => configurable); 325impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
326impl_ppi_channel!(PPI_CH9, 9 => configurable); 326impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
327impl_ppi_channel!(PPI_CH10, 10 => configurable); 327impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
328impl_ppi_channel!(PPI_CH11, 11 => configurable); 328impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
329impl_ppi_channel!(PPI_CH12, 12 => configurable); 329impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
330impl_ppi_channel!(PPI_CH13, 13 => configurable); 330impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
331impl_ppi_channel!(PPI_CH14, 14 => configurable); 331impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
332impl_ppi_channel!(PPI_CH15, 15 => configurable); 332impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
333
334impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
335impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
336impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
337impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
338impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
339impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
333 340
334impl_saadc_input!(P0_13, ANALOG_INPUT0); 341impl_saadc_input!(P0_13, ANALOG_INPUT0);
335impl_saadc_input!(P0_14, ANALOG_INPUT1); 342impl_saadc_input!(P0_14, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 64aec217c..4c6f055dd 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -314,22 +314,29 @@ impl_pin!(P0_29, 0, 29);
314impl_pin!(P0_30, 0, 30); 314impl_pin!(P0_30, 0, 30);
315impl_pin!(P0_31, 0, 31); 315impl_pin!(P0_31, 0, 31);
316 316
317impl_ppi_channel!(PPI_CH0, 0 => configurable); 317impl_ppi_channel!(PPI_CH0, DPPIC, 0 => configurable);
318impl_ppi_channel!(PPI_CH1, 1 => configurable); 318impl_ppi_channel!(PPI_CH1, DPPIC, 1 => configurable);
319impl_ppi_channel!(PPI_CH2, 2 => configurable); 319impl_ppi_channel!(PPI_CH2, DPPIC, 2 => configurable);
320impl_ppi_channel!(PPI_CH3, 3 => configurable); 320impl_ppi_channel!(PPI_CH3, DPPIC, 3 => configurable);
321impl_ppi_channel!(PPI_CH4, 4 => configurable); 321impl_ppi_channel!(PPI_CH4, DPPIC, 4 => configurable);
322impl_ppi_channel!(PPI_CH5, 5 => configurable); 322impl_ppi_channel!(PPI_CH5, DPPIC, 5 => configurable);
323impl_ppi_channel!(PPI_CH6, 6 => configurable); 323impl_ppi_channel!(PPI_CH6, DPPIC, 6 => configurable);
324impl_ppi_channel!(PPI_CH7, 7 => configurable); 324impl_ppi_channel!(PPI_CH7, DPPIC, 7 => configurable);
325impl_ppi_channel!(PPI_CH8, 8 => configurable); 325impl_ppi_channel!(PPI_CH8, DPPIC, 8 => configurable);
326impl_ppi_channel!(PPI_CH9, 9 => configurable); 326impl_ppi_channel!(PPI_CH9, DPPIC, 9 => configurable);
327impl_ppi_channel!(PPI_CH10, 10 => configurable); 327impl_ppi_channel!(PPI_CH10, DPPIC, 10 => configurable);
328impl_ppi_channel!(PPI_CH11, 11 => configurable); 328impl_ppi_channel!(PPI_CH11, DPPIC, 11 => configurable);
329impl_ppi_channel!(PPI_CH12, 12 => configurable); 329impl_ppi_channel!(PPI_CH12, DPPIC, 12 => configurable);
330impl_ppi_channel!(PPI_CH13, 13 => configurable); 330impl_ppi_channel!(PPI_CH13, DPPIC, 13 => configurable);
331impl_ppi_channel!(PPI_CH14, 14 => configurable); 331impl_ppi_channel!(PPI_CH14, DPPIC, 14 => configurable);
332impl_ppi_channel!(PPI_CH15, 15 => configurable); 332impl_ppi_channel!(PPI_CH15, DPPIC, 15 => configurable);
333
334impl_ppi_group!(PPI_GROUP0, DPPIC, 0);
335impl_ppi_group!(PPI_GROUP1, DPPIC, 1);
336impl_ppi_group!(PPI_GROUP2, DPPIC, 2);
337impl_ppi_group!(PPI_GROUP3, DPPIC, 3);
338impl_ppi_group!(PPI_GROUP4, DPPIC, 4);
339impl_ppi_group!(PPI_GROUP5, DPPIC, 5);
333 340
334impl_saadc_input!(P0_13, ANALOG_INPUT0); 341impl_saadc_input!(P0_13, ANALOG_INPUT0);
335impl_saadc_input!(P0_14, ANALOG_INPUT1); 342impl_saadc_input!(P0_14, ANALOG_INPUT1);
diff --git a/embassy-nrf/src/cracen.rs b/embassy-nrf/src/cracen.rs
new file mode 100644
index 000000000..47ef1cd87
--- /dev/null
+++ b/embassy-nrf/src/cracen.rs
@@ -0,0 +1,157 @@
1//! CRACEN - Cryptographic Accelerator Engine driver.
2
3#![macro_use]
4
5use core::marker::PhantomData;
6
7use crate::mode::{Blocking, Mode};
8use crate::{Peri, interrupt, pac, peripherals};
9
10/// A wrapper around an nRF54 CRACEN peripheral.
11///
12/// It has a blocking api through `rand`.
13pub struct Cracen<'d, M: Mode> {
14 _peri: Peri<'d, peripherals::CRACEN>,
15 _p: PhantomData<M>,
16}
17
18impl<'d> Cracen<'d, Blocking> {
19 /// Create a new CRACEN driver.
20 pub fn new_blocking(_peri: Peri<'d, peripherals::CRACEN>) -> Self {
21 let me = Self { _peri, _p: PhantomData };
22
23 me.stop();
24 me
25 }
26}
27
28impl<'d, M: Mode> Cracen<'d, M> {
29 fn regs() -> pac::cracen::Cracen {
30 pac::CRACEN
31 }
32
33 fn core() -> pac::cracencore::Cracencore {
34 pac::CRACENCORE
35 }
36
37 fn start_rng(&self) {
38 let r = Self::regs();
39 r.enable().write(|w| {
40 w.set_rng(true);
41 });
42
43 let r = Self::core();
44 r.rngcontrol().control().write(|w| {
45 w.set_enable(true);
46 });
47
48 while r.rngcontrol().status().read().state() == pac::cracencore::vals::State::STARTUP {}
49 }
50
51 fn stop(&self) {
52 let r = Self::regs();
53 r.enable().write(|w| {
54 w.set_cryptomaster(false);
55 w.set_rng(false);
56 w.set_pkeikg(false);
57 });
58 }
59
60 /// Fill the buffer with random bytes, blocking version.
61 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
62 self.start_rng();
63
64 let r = Self::core();
65 for chunk in dest.chunks_mut(4) {
66 while r.rngcontrol().fifolevel().read() == 0 {}
67 let word = r.rngcontrol().fifo(0).read().to_ne_bytes();
68 let to_copy = word.len().min(chunk.len());
69 chunk[..to_copy].copy_from_slice(&word[..to_copy]);
70 }
71
72 self.stop();
73 }
74
75 /// Generate a random u32
76 pub fn blocking_next_u32(&mut self) -> u32 {
77 let mut bytes = [0; 4];
78 self.blocking_fill_bytes(&mut bytes);
79 // We don't care about the endianness, so just use the native one.
80 u32::from_ne_bytes(bytes)
81 }
82
83 /// Generate a random u64
84 pub fn blocking_next_u64(&mut self) -> u64 {
85 let mut bytes = [0; 8];
86 self.blocking_fill_bytes(&mut bytes);
87 u64::from_ne_bytes(bytes)
88 }
89}
90
91impl<'d, M: Mode> Drop for Cracen<'d, M> {
92 fn drop(&mut self) {
93 let r = Self::core();
94 r.rngcontrol().control().write(|w| {
95 w.set_enable(false);
96 });
97
98 while r.rngcontrol().status().read().state() != pac::cracencore::vals::State::RESET {}
99
100 let r = Self::regs();
101 r.enable().write(|w| {
102 w.set_cryptomaster(false);
103 w.set_rng(false);
104 w.set_pkeikg(false);
105 });
106 }
107}
108
109impl<'d, M: Mode> rand_core_06::RngCore for Cracen<'d, M> {
110 fn fill_bytes(&mut self, dest: &mut [u8]) {
111 self.blocking_fill_bytes(dest);
112 }
113 fn next_u32(&mut self) -> u32 {
114 self.blocking_next_u32()
115 }
116 fn next_u64(&mut self) -> u64 {
117 self.blocking_next_u64()
118 }
119 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
120 self.blocking_fill_bytes(dest);
121 Ok(())
122 }
123}
124
125impl<'d, M: Mode> rand_core_06::CryptoRng for Cracen<'d, M> {}
126
127impl<'d, M: Mode> rand_core_09::RngCore for Cracen<'d, M> {
128 fn fill_bytes(&mut self, dest: &mut [u8]) {
129 self.blocking_fill_bytes(dest);
130 }
131 fn next_u32(&mut self) -> u32 {
132 self.blocking_next_u32()
133 }
134 fn next_u64(&mut self) -> u64 {
135 self.blocking_next_u64()
136 }
137}
138
139impl<'d, M: Mode> rand_core_09::CryptoRng for Cracen<'d, M> {}
140
141pub(crate) trait SealedInstance {}
142
143/// CRACEN peripheral instance.
144#[allow(private_bounds)]
145pub trait Instance: SealedInstance + 'static + Send {
146 /// Interrupt for this peripheral.
147 type Interrupt: interrupt::typelevel::Interrupt;
148}
149
150macro_rules! impl_cracen {
151 ($type:ident, $pac_type:ident, $irq:ident) => {
152 impl crate::cracen::SealedInstance for peripherals::$type {}
153 impl crate::cracen::Instance for peripherals::$type {
154 type Interrupt = crate::interrupt::typelevel::$irq;
155 }
156 };
157}
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 7ed3a7927..43d1b9cb2 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -585,7 +585,6 @@ impl SealedPin for AnyPin {
585// ==================== 585// ====================
586 586
587#[cfg(not(feature = "_nrf51"))] 587#[cfg(not(feature = "_nrf51"))]
588#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
589pub(crate) trait PselBits { 588pub(crate) trait PselBits {
590 fn psel_bits(&self) -> pac::shared::regs::Psel; 589 fn psel_bits(&self) -> pac::shared::regs::Psel;
591} 590}
@@ -602,7 +601,6 @@ impl<'a, P: Pin> PselBits for Option<Peri<'a, P>> {
602} 601}
603 602
604#[cfg(not(feature = "_nrf51"))] 603#[cfg(not(feature = "_nrf51"))]
605#[cfg_attr(feature = "_nrf54l", allow(unused))] // TODO
606pub(crate) const DISCONNECTED: Psel = Psel(1 << 31); 604pub(crate) const DISCONNECTED: Psel = Psel(1 << 31);
607 605
608#[cfg(not(feature = "_nrf51"))] 606#[cfg(not(feature = "_nrf51"))]
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index a490d5b60..91944d8cd 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -1,4 +1,5 @@
1//! GPIO task/event (GPIOTE) driver. 1//! GPIO task/event (GPIOTE) driver.
2#![macro_use]
2 3
3use core::convert::Infallible; 4use core::convert::Infallible;
4use core::future::{Future, poll_fn}; 5use core::future::{Future, poll_fn};
@@ -7,7 +8,7 @@ use core::task::{Context, Poll};
7use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; 8use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral};
8use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
9 10
10use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin, SealedPin as _}; 11use crate::gpio::{AnyPin, Flex, Input, Level, Output, OutputDrive, Pin as GpioPin, Pull, SealedPin as _};
11use crate::interrupt::InterruptExt; 12use crate::interrupt::InterruptExt;
12#[cfg(not(feature = "_nrf51"))] 13#[cfg(not(feature = "_nrf51"))]
13use crate::pac::gpio::vals::Detectmode; 14use crate::pac::gpio::vals::Detectmode;
@@ -19,13 +20,28 @@ use crate::{interrupt, pac, peripherals};
19#[cfg(feature = "_nrf51")] 20#[cfg(feature = "_nrf51")]
20/// Amount of GPIOTE channels in the chip. 21/// Amount of GPIOTE channels in the chip.
21const CHANNEL_COUNT: usize = 4; 22const CHANNEL_COUNT: usize = 4;
22#[cfg(not(feature = "_nrf51"))] 23#[cfg(not(any(feature = "_nrf51", feature = "_nrf54l")))]
23/// Amount of GPIOTE channels in the chip. 24/// Amount of GPIOTE channels in the chip.
24const CHANNEL_COUNT: usize = 8; 25const CHANNEL_COUNT: usize = 8;
25 26#[cfg(any(feature = "_nrf54l"))]
26#[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 27/// Amount of GPIOTE channels in the chip.
28const CHANNEL_COUNT: usize = 12;
29/// Max channels per port
30const CHANNELS_PER_PORT: usize = 8;
31
32#[cfg(any(
33 feature = "nrf52833",
34 feature = "nrf52840",
35 feature = "_nrf5340",
36 feature = "_nrf54l"
37))]
27const PIN_COUNT: usize = 48; 38const PIN_COUNT: usize = 48;
28#[cfg(not(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 39#[cfg(not(any(
40 feature = "nrf52833",
41 feature = "nrf52840",
42 feature = "_nrf5340",
43 feature = "_nrf54l"
44)))]
29const PIN_COUNT: usize = 32; 45const PIN_COUNT: usize = 32;
30 46
31#[allow(clippy::declare_interior_mutable_const)] 47#[allow(clippy::declare_interior_mutable_const)]
@@ -54,18 +70,6 @@ pub enum OutputChannelPolarity {
54 Toggle, 70 Toggle,
55} 71}
56 72
57fn regs() -> pac::gpiote::Gpiote {
58 cfg_if::cfg_if! {
59 if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s", feature="nrf9120-s"))] {
60 pac::GPIOTE0
61 } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns", feature="nrf9120-ns"))] {
62 pac::GPIOTE1
63 } else {
64 pac::GPIOTE
65 }
66 }
67}
68
69pub(crate) fn init(irq_prio: crate::interrupt::Priority) { 73pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
70 // no latched GPIO detect in nrf51. 74 // no latched GPIO detect in nrf51.
71 #[cfg(not(feature = "_nrf51"))] 75 #[cfg(not(feature = "_nrf51"))]
@@ -77,6 +81,9 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
77 81
78 for &p in ports { 82 for &p in ports {
79 // Enable latched detection 83 // Enable latched detection
84 #[cfg(all(feature = "_s", not(feature = "_nrf54l")))]
85 p.detectmode_sec().write(|w| w.set_detectmode(Detectmode::LDETECT));
86 #[cfg(any(not(feature = "_s"), all(feature = "_s", feature = "_nrf54l")))]
80 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT)); 87 p.detectmode().write(|w| w.set_detectmode(Detectmode::LDETECT));
81 // Clear latch 88 // Clear latch
82 p.latch().write(|w| w.0 = 0xFFFFFFFF) 89 p.latch().write(|w| w.0 = 0xFFFFFFFF)
@@ -85,57 +92,130 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
85 92
86 // Enable interrupts 93 // Enable interrupts
87 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 94 #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
88 let irq = interrupt::GPIOTE0; 95 let irqs = &[(pac::GPIOTE0, interrupt::GPIOTE0)];
89 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 96 #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
90 let irq = interrupt::GPIOTE1; 97 let irqs = &[(pac::GPIOTE1, interrupt::GPIOTE1)];
91 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 98 #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
92 let irq = interrupt::GPIOTE; 99 let irqs = &[(pac::GPIOTE, interrupt::GPIOTE)];
100 #[cfg(any(feature = "_nrf54l"))]
101 let irqs = &[
102 #[cfg(feature = "_s")]
103 (pac::GPIOTE20, interrupt::GPIOTE20_0),
104 #[cfg(feature = "_s")]
105 (pac::GPIOTE30, interrupt::GPIOTE30_0),
106 #[cfg(feature = "_ns")]
107 (pac::GPIOTE20, interrupt::GPIOTE20_1),
108 #[cfg(feature = "_ns")]
109 (pac::GPIOTE30, interrupt::GPIOTE30_1),
110 ];
111
112 for (inst, irq) in irqs {
113 irq.unpend();
114 irq.set_priority(irq_prio);
115 unsafe { irq.enable() };
93 116
94 irq.unpend(); 117 let g = inst;
95 irq.set_priority(irq_prio); 118 #[cfg(not(feature = "_nrf54l"))]
96 unsafe { irq.enable() }; 119 g.intenset(INTNUM).write(|w| w.set_port(true));
97 120
98 let g = regs(); 121 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
99 g.intenset().write(|w| w.set_port(true)); 122 g.intenset(INTNUM).write(|w| w.set_port0nonsecure(true));
123
124 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
125 g.intenset(INTNUM).write(|w| w.set_port0secure(true));
126 }
100} 127}
101 128
129#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
130const INTNUM: usize = 1;
131
132#[cfg(any(not(feature = "_nrf54l"), feature = "_s"))]
133const INTNUM: usize = 0;
134
102#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))] 135#[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
103#[cfg(feature = "rt")] 136#[cfg(feature = "rt")]
104#[interrupt] 137#[interrupt]
105fn GPIOTE0() { 138fn GPIOTE0() {
106 unsafe { handle_gpiote_interrupt() }; 139 unsafe { handle_gpiote_interrupt(pac::GPIOTE0) };
107} 140}
108 141
109#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))] 142#[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
110#[cfg(feature = "rt")] 143#[cfg(feature = "rt")]
111#[interrupt] 144#[interrupt]
112fn GPIOTE1() { 145fn GPIOTE1() {
113 unsafe { handle_gpiote_interrupt() }; 146 unsafe { handle_gpiote_interrupt(pac::GPIOTE1) };
114} 147}
115 148
116#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))] 149#[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
117#[cfg(feature = "rt")] 150#[cfg(feature = "rt")]
118#[interrupt] 151#[interrupt]
119fn GPIOTE() { 152fn GPIOTE() {
120 unsafe { handle_gpiote_interrupt() }; 153 unsafe { handle_gpiote_interrupt(pac::GPIOTE) };
121} 154}
122 155
123unsafe fn handle_gpiote_interrupt() { 156#[cfg(all(feature = "_nrf54l", feature = "_s"))]
124 let g = regs(); 157#[cfg(feature = "rt")]
158#[interrupt]
159fn GPIOTE20_0() {
160 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
161}
125 162
126 for i in 0..CHANNEL_COUNT { 163#[cfg(all(feature = "_nrf54l", feature = "_s"))]
164#[cfg(feature = "rt")]
165#[interrupt]
166fn GPIOTE30_0() {
167 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
168}
169
170#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
171#[cfg(feature = "rt")]
172#[interrupt]
173fn GPIOTE20_1() {
174 unsafe { handle_gpiote_interrupt(pac::GPIOTE20) };
175}
176
177#[cfg(all(feature = "_nrf54l", feature = "_ns"))]
178#[cfg(feature = "rt")]
179#[interrupt]
180fn GPIOTE30_1() {
181 unsafe { handle_gpiote_interrupt(pac::GPIOTE30) };
182}
183
184unsafe fn handle_gpiote_interrupt(g: pac::gpiote::Gpiote) {
185 for c in 0..CHANNEL_COUNT {
186 let i = c % CHANNELS_PER_PORT;
127 if g.events_in(i).read() != 0 { 187 if g.events_in(i).read() != 0 {
128 g.intenclr().write(|w| w.0 = 1 << i); 188 g.intenclr(INTNUM).write(|w| w.0 = 1 << i);
129 CHANNEL_WAKERS[i].wake(); 189 CHANNEL_WAKERS[c].wake();
130 } 190 }
131 } 191 }
132 192
133 if g.events_port().read() != 0 { 193 #[cfg(not(feature = "_nrf54l"))]
134 g.events_port().write_value(0); 194 let eport = g.events_port(0);
135 195
136 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 196 #[cfg(all(feature = "_nrf54l", feature = "_ns"))]
197 let eport = g.events_port(0).nonsecure();
198
199 #[cfg(all(feature = "_nrf54l", feature = "_s"))]
200 let eport = g.events_port(0).secure();
201
202 if eport.read() != 0 {
203 eport.write_value(0);
204
205 #[cfg(any(
206 feature = "nrf52833",
207 feature = "nrf52840",
208 feature = "_nrf5340",
209 feature = "_nrf54l"
210 ))]
137 let ports = &[pac::P0, pac::P1]; 211 let ports = &[pac::P0, pac::P1];
138 #[cfg(not(any(feature = "_nrf51", feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340")))] 212 #[cfg(not(any(
213 feature = "_nrf51",
214 feature = "nrf52833",
215 feature = "nrf52840",
216 feature = "_nrf5340",
217 feature = "_nrf54l"
218 )))]
139 let ports = &[pac::P0]; 219 let ports = &[pac::P0];
140 #[cfg(feature = "_nrf51")] 220 #[cfg(feature = "_nrf51")]
141 let ports = &[pac::GPIO]; 221 let ports = &[pac::GPIO];
@@ -204,19 +284,43 @@ impl InputChannel<'static> {
204 284
205impl<'d> Drop for InputChannel<'d> { 285impl<'d> Drop for InputChannel<'d> {
206 fn drop(&mut self) { 286 fn drop(&mut self) {
207 let g = regs(); 287 let g = self.ch.regs();
208 let num = self.ch.number(); 288 let num = self.ch.number();
209 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 289 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
210 g.intenclr().write(|w| w.0 = 1 << num); 290 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
211 } 291 }
212} 292}
213 293
214impl<'d> InputChannel<'d> { 294impl<'d> InputChannel<'d> {
215 /// Create a new GPIOTE input channel driver. 295 /// Create a new GPIOTE input channel driver.
216 pub fn new(ch: Peri<'d, impl Channel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self { 296 #[cfg(feature = "_nrf54l")]
217 let g = regs(); 297 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
218 let num = ch.number(); 298 ch: Peri<'d, C>,
299 pin: Peri<'d, T>,
300 pull: Pull,
301 polarity: InputChannelPolarity,
302 ) -> Self {
303 let pin = Input::new(pin, pull);
304 let ch = ch.into();
305 Self::new_inner(ch, pin, polarity)
306 }
219 307
308 /// Create a new GPIOTE output channel driver.
309 #[cfg(not(feature = "_nrf54l"))]
310 pub fn new<C: Channel, T: GpioPin>(
311 ch: Peri<'d, C>,
312 pin: Peri<'d, T>,
313 pull: Pull,
314 polarity: InputChannelPolarity,
315 ) -> Self {
316 let pin = Input::new(pin, pull);
317 let ch = ch.into();
318 Self::new_inner(ch, pin, polarity)
319 }
320
321 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
322 let g = ch.regs();
323 let num = ch.number();
220 g.config(num).write(|w| { 324 g.config(num).write(|w| {
221 w.set_mode(Mode::EVENT); 325 w.set_mode(Mode::EVENT);
222 match polarity { 326 match polarity {
@@ -225,30 +329,37 @@ impl<'d> InputChannel<'d> {
225 InputChannelPolarity::None => w.set_polarity(Polarity::NONE), 329 InputChannelPolarity::None => w.set_polarity(Polarity::NONE),
226 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE), 330 InputChannelPolarity::Toggle => w.set_polarity(Polarity::TOGGLE),
227 }; 331 };
228 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340"))] 332 #[cfg(any(feature = "nrf52833", feature = "nrf52840", feature = "_nrf5340",))]
229 w.set_port(match pin.pin.pin.port() { 333 w.set_port(match pin.pin.pin.port() {
230 crate::gpio::Port::Port0 => false, 334 crate::gpio::Port::Port0 => false,
231 crate::gpio::Port::Port1 => true, 335 crate::gpio::Port::Port1 => true,
232 }); 336 });
337 #[cfg(any(feature = "_nrf54l"))]
338 w.set_port(match pin.pin.pin.port() {
339 crate::gpio::Port::Port0 => 0,
340 crate::gpio::Port::Port1 => 1,
341 crate::gpio::Port::Port2 => 2,
342 });
233 w.set_psel(pin.pin.pin.pin()); 343 w.set_psel(pin.pin.pin.pin());
234 }); 344 });
235 345
236 g.events_in(num).write_value(0); 346 g.events_in(num).write_value(0);
237 347
238 InputChannel { ch: ch.into(), pin } 348 InputChannel { ch, pin }
239 } 349 }
240 350
241 /// Asynchronously wait for an event in this channel. 351 /// Asynchronously wait for an event in this channel.
242 pub async fn wait(&self) { 352 pub async fn wait(&self) {
243 let g = regs(); 353 let g = self.ch.regs();
244 let num = self.ch.number(); 354 let num = self.ch.number();
355 let waker = self.ch.waker();
245 356
246 // Enable interrupt 357 // Enable interrupt
247 g.events_in(num).write_value(0); 358 g.events_in(num).write_value(0);
248 g.intenset().write(|w| w.0 = 1 << num); 359 g.intenset(INTNUM).write(|w| w.0 = 1 << num);
249 360
250 poll_fn(|cx| { 361 poll_fn(|cx| {
251 CHANNEL_WAKERS[num].register(cx.waker()); 362 CHANNEL_WAKERS[waker].register(cx.waker());
252 363
253 if g.events_in(num).read() != 0 { 364 if g.events_in(num).read() != 0 {
254 Poll::Ready(()) 365 Poll::Ready(())
@@ -259,9 +370,14 @@ impl<'d> InputChannel<'d> {
259 .await; 370 .await;
260 } 371 }
261 372
373 /// Get the associated input pin.
374 pub fn pin(&self) -> &Input<'_> {
375 &self.pin
376 }
377
262 /// Returns the IN event, for use with PPI. 378 /// Returns the IN event, for use with PPI.
263 pub fn event_in(&self) -> Event<'d> { 379 pub fn event_in(&self) -> Event<'d> {
264 let g = regs(); 380 let g = self.ch.regs();
265 Event::from_reg(g.events_in(self.ch.number())) 381 Event::from_reg(g.events_in(self.ch.number()))
266 } 382 }
267} 383}
@@ -283,17 +399,44 @@ impl OutputChannel<'static> {
283 399
284impl<'d> Drop for OutputChannel<'d> { 400impl<'d> Drop for OutputChannel<'d> {
285 fn drop(&mut self) { 401 fn drop(&mut self) {
286 let g = regs(); 402 let g = self.ch.regs();
287 let num = self.ch.number(); 403 let num = self.ch.number();
288 g.config(num).write(|w| w.set_mode(Mode::DISABLED)); 404 g.config(num).write(|w| w.set_mode(Mode::DISABLED));
289 g.intenclr().write(|w| w.0 = 1 << num); 405 g.intenclr(INTNUM).write(|w| w.0 = 1 << num);
290 } 406 }
291} 407}
292 408
293impl<'d> OutputChannel<'d> { 409impl<'d> OutputChannel<'d> {
294 /// Create a new GPIOTE output channel driver. 410 /// Create a new GPIOTE output channel driver.
295 pub fn new(ch: Peri<'d, impl Channel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self { 411 #[cfg(feature = "_nrf54l")]
296 let g = regs(); 412 pub fn new<C: Channel, T: GpiotePin<Instance = C::Instance>>(
413 ch: Peri<'d, C>,
414 pin: Peri<'d, T>,
415 initial_output: Level,
416 drive: OutputDrive,
417 polarity: OutputChannelPolarity,
418 ) -> Self {
419 let pin = Output::new(pin, initial_output, drive);
420 let ch = ch.into();
421 Self::new_inner(ch, pin, polarity)
422 }
423
424 /// Create a new GPIOTE output channel driver.
425 #[cfg(not(feature = "_nrf54l"))]
426 pub fn new<C: Channel, T: GpioPin>(
427 ch: Peri<'d, C>,
428 pin: Peri<'d, T>,
429 initial_output: Level,
430 drive: OutputDrive,
431 polarity: OutputChannelPolarity,
432 ) -> Self {
433 let pin = Output::new(pin, initial_output, drive);
434 let ch = ch.into();
435 Self::new_inner(ch, pin, polarity)
436 }
437
438 fn new_inner(ch: Peri<'d, AnyChannel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
439 let g = ch.regs();
297 let num = ch.number(); 440 let num = ch.number();
298 441
299 g.config(num).write(|w| { 442 g.config(num).write(|w| {
@@ -312,52 +455,55 @@ impl<'d> OutputChannel<'d> {
312 crate::gpio::Port::Port0 => false, 455 crate::gpio::Port::Port0 => false,
313 crate::gpio::Port::Port1 => true, 456 crate::gpio::Port::Port1 => true,
314 }); 457 });
458 #[cfg(any(feature = "_nrf54l"))]
459 w.set_port(match pin.pin.pin.port() {
460 crate::gpio::Port::Port0 => 0,
461 crate::gpio::Port::Port1 => 1,
462 crate::gpio::Port::Port2 => 2,
463 });
315 w.set_psel(pin.pin.pin.pin()); 464 w.set_psel(pin.pin.pin.pin());
316 }); 465 });
317 466
318 OutputChannel { 467 OutputChannel { ch, _pin: pin }
319 ch: ch.into(),
320 _pin: pin,
321 }
322 } 468 }
323 469
324 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle). 470 /// Triggers the OUT task (does the action as configured with task_out_polarity, defaults to Toggle).
325 pub fn out(&self) { 471 pub fn out(&self) {
326 let g = regs(); 472 let g = self.ch.regs();
327 g.tasks_out(self.ch.number()).write_value(1); 473 g.tasks_out(self.ch.number()).write_value(1);
328 } 474 }
329 475
330 /// Triggers the SET task (set associated pin high). 476 /// Triggers the SET task (set associated pin high).
331 #[cfg(not(feature = "_nrf51"))] 477 #[cfg(not(feature = "_nrf51"))]
332 pub fn set(&self) { 478 pub fn set(&self) {
333 let g = regs(); 479 let g = self.ch.regs();
334 g.tasks_set(self.ch.number()).write_value(1); 480 g.tasks_set(self.ch.number()).write_value(1);
335 } 481 }
336 482
337 /// Triggers the CLEAR task (set associated pin low). 483 /// Triggers the CLEAR task (set associated pin low).
338 #[cfg(not(feature = "_nrf51"))] 484 #[cfg(not(feature = "_nrf51"))]
339 pub fn clear(&self) { 485 pub fn clear(&self) {
340 let g = regs(); 486 let g = self.ch.regs();
341 g.tasks_clr(self.ch.number()).write_value(1); 487 g.tasks_clr(self.ch.number()).write_value(1);
342 } 488 }
343 489
344 /// Returns the OUT task, for use with PPI. 490 /// Returns the OUT task, for use with PPI.
345 pub fn task_out(&self) -> Task<'d> { 491 pub fn task_out(&self) -> Task<'d> {
346 let g = regs(); 492 let g = self.ch.regs();
347 Task::from_reg(g.tasks_out(self.ch.number())) 493 Task::from_reg(g.tasks_out(self.ch.number()))
348 } 494 }
349 495
350 /// Returns the CLR task, for use with PPI. 496 /// Returns the CLR task, for use with PPI.
351 #[cfg(not(feature = "_nrf51"))] 497 #[cfg(not(feature = "_nrf51"))]
352 pub fn task_clr(&self) -> Task<'d> { 498 pub fn task_clr(&self) -> Task<'d> {
353 let g = regs(); 499 let g = self.ch.regs();
354 Task::from_reg(g.tasks_clr(self.ch.number())) 500 Task::from_reg(g.tasks_clr(self.ch.number()))
355 } 501 }
356 502
357 /// Returns the SET task, for use with PPI. 503 /// Returns the SET task, for use with PPI.
358 #[cfg(not(feature = "_nrf51"))] 504 #[cfg(not(feature = "_nrf51"))]
359 pub fn task_set(&self) -> Task<'d> { 505 pub fn task_set(&self) -> Task<'d> {
360 let g = regs(); 506 let g = self.ch.regs();
361 Task::from_reg(g.tasks_set(self.ch.number())) 507 Task::from_reg(g.tasks_set(self.ch.number()))
362 } 508 }
363} 509}
@@ -459,31 +605,52 @@ impl<'d> Flex<'d> {
459 PortInputFuture::new(self.pin.reborrow()).await 605 PortInputFuture::new(self.pin.reborrow()).await
460 } 606 }
461} 607}
462
463// ======================= 608// =======================
609//
464 610
465trait SealedChannel {} 611trait SealedChannel {
612 fn waker(&self) -> usize;
613 fn regs(&self) -> pac::gpiote::Gpiote;
614}
466 615
467/// GPIOTE channel trait. 616/// GPIOTE channel trait.
468/// 617///
469/// Implemented by all GPIOTE channels. 618/// Implemented by all GPIOTE channels.
470#[allow(private_bounds)] 619#[allow(private_bounds)]
471pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static { 620pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static {
621 #[cfg(feature = "_nrf54l")]
622 /// GPIOTE instance this channel belongs to.
623 type Instance: GpioteInstance;
472 /// Get the channel number. 624 /// Get the channel number.
473 fn number(&self) -> usize; 625 fn number(&self) -> usize;
474} 626}
475 627
476/// Type-erased channel. 628struct AnyChannel {
477///
478/// Obtained by calling `Channel::into()`.
479///
480/// This allows using several channels in situations that might require
481/// them to be the same type, like putting them in an array.
482pub struct AnyChannel {
483 number: u8, 629 number: u8,
630 regs: pac::gpiote::Gpiote,
631 waker: u8,
484} 632}
633
485impl_peripheral!(AnyChannel); 634impl_peripheral!(AnyChannel);
486impl SealedChannel for AnyChannel {} 635
636impl SealedChannel for AnyChannel {
637 fn waker(&self) -> usize {
638 self.waker as usize
639 }
640
641 fn regs(&self) -> pac::gpiote::Gpiote {
642 self.regs
643 }
644}
645
646#[cfg(feature = "_nrf54l")]
647impl AnyChannel {
648 fn number(&self) -> usize {
649 self.number as usize
650 }
651}
652
653#[cfg(not(feature = "_nrf54l"))]
487impl Channel for AnyChannel { 654impl Channel for AnyChannel {
488 fn number(&self) -> usize { 655 fn number(&self) -> usize {
489 self.number as usize 656 self.number as usize
@@ -491,9 +658,19 @@ impl Channel for AnyChannel {
491} 658}
492 659
493macro_rules! impl_channel { 660macro_rules! impl_channel {
494 ($type:ident, $number:expr) => { 661 ($type:ident, $inst:ident, $number:expr, $waker:expr) => {
495 impl SealedChannel for peripherals::$type {} 662 impl SealedChannel for peripherals::$type {
663 fn waker(&self) -> usize {
664 $waker as usize
665 }
666
667 fn regs(&self) -> pac::gpiote::Gpiote {
668 pac::$inst
669 }
670 }
496 impl Channel for peripherals::$type { 671 impl Channel for peripherals::$type {
672 #[cfg(feature = "_nrf54l")]
673 type Instance = peripherals::$inst;
497 fn number(&self) -> usize { 674 fn number(&self) -> usize {
498 $number as usize 675 $number as usize
499 } 676 }
@@ -503,24 +680,95 @@ macro_rules! impl_channel {
503 fn from(val: peripherals::$type) -> Self { 680 fn from(val: peripherals::$type) -> Self {
504 Self { 681 Self {
505 number: val.number() as u8, 682 number: val.number() as u8,
683 waker: val.waker() as u8,
684 regs: val.regs(),
506 } 685 }
507 } 686 }
508 } 687 }
509 }; 688 };
510} 689}
511 690
512impl_channel!(GPIOTE_CH0, 0); 691cfg_if::cfg_if! {
513impl_channel!(GPIOTE_CH1, 1); 692 if #[cfg(feature = "_nrf54l")] {
514impl_channel!(GPIOTE_CH2, 2); 693 trait SealedGpioteInstance {}
515impl_channel!(GPIOTE_CH3, 3); 694 /// Represents a GPIOTE instance.
516#[cfg(not(feature = "_nrf51"))] 695 #[allow(private_bounds)]
517impl_channel!(GPIOTE_CH4, 4); 696 pub trait GpioteInstance: PeripheralType + SealedGpioteInstance + Sized + 'static {}
518#[cfg(not(feature = "_nrf51"))] 697
519impl_channel!(GPIOTE_CH5, 5); 698 macro_rules! impl_gpiote {
520#[cfg(not(feature = "_nrf51"))] 699 ($type:ident) => {
521impl_channel!(GPIOTE_CH6, 6); 700 impl SealedGpioteInstance for peripherals::$type {}
522#[cfg(not(feature = "_nrf51"))] 701 impl GpioteInstance for peripherals::$type {}
523impl_channel!(GPIOTE_CH7, 7); 702 };
703 }
704
705 pub(crate) trait SealedGpiotePin {}
706
707 /// Represents a GPIO pin that can be used with GPIOTE.
708 #[allow(private_bounds)]
709 pub trait GpiotePin: GpioPin + SealedGpiotePin {
710 /// The GPIOTE instance this pin belongs to.
711 type Instance: GpioteInstance;
712 }
713
714 macro_rules! impl_gpiote_pin {
715 ($type:ident, $inst:ident) => {
716 impl crate::gpiote::SealedGpiotePin for peripherals::$type {}
717 impl crate::gpiote::GpiotePin for peripherals::$type {
718 type Instance = peripherals::$inst;
719 }
720 };
721 }
722
723 impl_gpiote!(GPIOTE20);
724 impl_gpiote!(GPIOTE30);
725 impl_channel!(GPIOTE20_CH0, GPIOTE20, 0, 0);
726 impl_channel!(GPIOTE20_CH1, GPIOTE20, 1, 1);
727 impl_channel!(GPIOTE20_CH2, GPIOTE20, 2, 2);
728 impl_channel!(GPIOTE20_CH3, GPIOTE20, 3, 3);
729 impl_channel!(GPIOTE20_CH4, GPIOTE20, 4, 4);
730 impl_channel!(GPIOTE20_CH5, GPIOTE20, 5, 5);
731 impl_channel!(GPIOTE20_CH6, GPIOTE20, 6, 6);
732 impl_channel!(GPIOTE20_CH7, GPIOTE20, 7, 7);
733
734 impl_channel!(GPIOTE30_CH0, GPIOTE30, 0, 8);
735 impl_channel!(GPIOTE30_CH1, GPIOTE30, 1, 9);
736 impl_channel!(GPIOTE30_CH2, GPIOTE30, 2, 10);
737 impl_channel!(GPIOTE30_CH3, GPIOTE30, 3, 11);
738 } else if #[cfg(feature = "_nrf51")] {
739 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
740 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
741 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
742 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
743 } else if #[cfg(all(feature = "_s", any(feature = "_nrf91", feature = "_nrf5340")))] {
744 impl_channel!(GPIOTE_CH0, GPIOTE0, 0, 0);
745 impl_channel!(GPIOTE_CH1, GPIOTE0, 1, 1);
746 impl_channel!(GPIOTE_CH2, GPIOTE0, 2, 2);
747 impl_channel!(GPIOTE_CH3, GPIOTE0, 3, 3);
748 impl_channel!(GPIOTE_CH4, GPIOTE0, 4, 4);
749 impl_channel!(GPIOTE_CH5, GPIOTE0, 5, 5);
750 impl_channel!(GPIOTE_CH6, GPIOTE0, 6, 6);
751 impl_channel!(GPIOTE_CH7, GPIOTE0, 7, 7);
752 } else if #[cfg(all(feature = "_ns", any(feature = "_nrf91", feature = "_nrf5340")))] {
753 impl_channel!(GPIOTE_CH0, GPIOTE1, 0, 0);
754 impl_channel!(GPIOTE_CH1, GPIOTE1, 1, 1);
755 impl_channel!(GPIOTE_CH2, GPIOTE1, 2, 2);
756 impl_channel!(GPIOTE_CH3, GPIOTE1, 3, 3);
757 impl_channel!(GPIOTE_CH4, GPIOTE1, 4, 4);
758 impl_channel!(GPIOTE_CH5, GPIOTE1, 5, 5);
759 impl_channel!(GPIOTE_CH6, GPIOTE1, 6, 6);
760 impl_channel!(GPIOTE_CH7, GPIOTE1, 7, 7);
761 } else {
762 impl_channel!(GPIOTE_CH0, GPIOTE, 0, 0);
763 impl_channel!(GPIOTE_CH1, GPIOTE, 1, 1);
764 impl_channel!(GPIOTE_CH2, GPIOTE, 2, 2);
765 impl_channel!(GPIOTE_CH3, GPIOTE, 3, 3);
766 impl_channel!(GPIOTE_CH4, GPIOTE, 4, 4);
767 impl_channel!(GPIOTE_CH5, GPIOTE, 5, 5);
768 impl_channel!(GPIOTE_CH6, GPIOTE, 6, 6);
769 impl_channel!(GPIOTE_CH7, GPIOTE, 7, 7);
770 }
771}
524 772
525// ==================== 773// ====================
526 774
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 1b7fb7e7f..2f5ad352f 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -76,14 +76,12 @@ pub(crate) mod util;
76#[cfg(feature = "_time-driver")] 76#[cfg(feature = "_time-driver")]
77mod time_driver; 77mod time_driver;
78 78
79#[cfg(not(feature = "_nrf54l"))] // TODO
80#[cfg(not(feature = "_nrf51"))] 79#[cfg(not(feature = "_nrf51"))]
81pub mod buffered_uarte; 80pub mod buffered_uarte;
82#[cfg(not(feature = "_nrf54l"))] // TODO 81#[cfg(not(feature = "_nrf54l"))] // TODO
83#[cfg(not(feature = "_nrf51"))] 82#[cfg(not(feature = "_nrf51"))]
84pub mod egu; 83pub mod egu;
85pub mod gpio; 84pub mod gpio;
86#[cfg(not(feature = "_nrf54l"))] // TODO
87#[cfg(feature = "gpiote")] 85#[cfg(feature = "gpiote")]
88pub mod gpiote; 86pub mod gpiote;
89#[cfg(not(feature = "_nrf54l"))] // TODO 87#[cfg(not(feature = "_nrf54l"))] // TODO
@@ -119,9 +117,7 @@ pub mod pdm;
119#[cfg(not(feature = "_nrf54l"))] // TODO 117#[cfg(not(feature = "_nrf54l"))] // TODO
120#[cfg(any(feature = "nrf52840", feature = "nrf9160-s", feature = "nrf9160-ns"))] 118#[cfg(any(feature = "nrf52840", feature = "nrf9160-s", feature = "nrf9160-ns"))]
121pub mod power; 119pub mod power;
122#[cfg(not(feature = "_nrf54l"))] // TODO
123pub mod ppi; 120pub mod ppi;
124#[cfg(not(feature = "_nrf54l"))] // TODO
125#[cfg(not(any( 121#[cfg(not(any(
126 feature = "_nrf51", 122 feature = "_nrf51",
127 feature = "nrf52805", 123 feature = "nrf52805",
@@ -149,34 +145,28 @@ pub mod radio;
149#[cfg(feature = "_net-driver")] 145#[cfg(feature = "_net-driver")]
150pub mod embassy_net_802154_driver; 146pub mod embassy_net_802154_driver;
151 147
148#[cfg(all(feature = "_nrf54l", feature = "_s"))]
149pub mod cracen;
152#[cfg(not(feature = "_nrf54l"))] // TODO 150#[cfg(not(feature = "_nrf54l"))] // TODO
153#[cfg(feature = "_nrf5340")] 151#[cfg(feature = "_nrf5340")]
154pub mod reset; 152pub mod reset;
155#[cfg(not(feature = "_nrf54l"))] // TODO 153#[cfg(not(feature = "_nrf54l"))]
156#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 154#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
157pub mod rng; 155pub mod rng;
158#[cfg(not(feature = "_nrf54l"))] // TODO
159pub mod rtc; 156pub mod rtc;
160#[cfg(not(feature = "_nrf54l"))] // TODO
161#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))] 157#[cfg(not(any(feature = "_nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
162pub mod saadc; 158pub mod saadc;
163#[cfg(not(feature = "_nrf54l"))] // TODO
164#[cfg(not(feature = "_nrf51"))] 159#[cfg(not(feature = "_nrf51"))]
165pub mod spim; 160pub mod spim;
166#[cfg(not(feature = "_nrf54l"))] // TODO
167#[cfg(not(feature = "_nrf51"))] 161#[cfg(not(feature = "_nrf51"))]
168pub mod spis; 162pub mod spis;
169#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] 163#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))]
170pub mod temp; 164pub mod temp;
171#[cfg(not(feature = "_nrf54l"))] // TODO
172pub mod timer; 165pub mod timer;
173#[cfg(not(feature = "_nrf54l"))] // TODO
174#[cfg(not(feature = "_nrf51"))] 166#[cfg(not(feature = "_nrf51"))]
175pub mod twim; 167pub mod twim;
176#[cfg(not(feature = "_nrf54l"))] // TODO
177#[cfg(not(feature = "_nrf51"))] 168#[cfg(not(feature = "_nrf51"))]
178pub mod twis; 169pub mod twis;
179#[cfg(not(feature = "_nrf54l"))] // TODO
180#[cfg(not(feature = "_nrf51"))] 170#[cfg(not(feature = "_nrf51"))]
181pub mod uarte; 171pub mod uarte;
182#[cfg(not(feature = "_nrf54l"))] // TODO 172#[cfg(not(feature = "_nrf54l"))] // TODO
@@ -295,6 +285,15 @@ pub use crate::pac::NVIC_PRIO_BITS;
295pub mod config { 285pub mod config {
296 //! Configuration options used when initializing the HAL. 286 //! Configuration options used when initializing the HAL.
297 287
288 /// Clock speed
289 #[cfg(feature = "_nrf54l")]
290 pub enum ClockSpeed {
291 /// Run at 128 MHz.
292 CK128,
293 /// Run at 64 MHz.
294 CK64,
295 }
296
298 /// High frequency clock source. 297 /// High frequency clock source.
299 pub enum HfclkSource { 298 pub enum HfclkSource {
300 /// Internal source 299 /// Internal source
@@ -564,6 +563,9 @@ pub mod config {
564 pub time_interrupt_priority: crate::interrupt::Priority, 563 pub time_interrupt_priority: crate::interrupt::Priority,
565 /// Enable or disable the debug port. 564 /// Enable or disable the debug port.
566 pub debug: Debug, 565 pub debug: Debug,
566 /// Clock speed configuration.
567 #[cfg(feature = "_nrf54l")]
568 pub clock_speed: ClockSpeed,
567 } 569 }
568 570
569 impl Default for Config { 571 impl Default for Config {
@@ -604,6 +606,8 @@ pub mod config {
604 debug: Debug::NotConfigured, 606 debug: Debug::NotConfigured,
605 #[cfg(not(feature = "_ns"))] 607 #[cfg(not(feature = "_ns"))]
606 debug: Debug::Allowed, 608 debug: Debug::Allowed,
609 #[cfg(feature = "_nrf54l")]
610 clock_speed: ClockSpeed::CK64,
607 } 611 }
608 } 612 }
609 } 613 }
@@ -710,6 +714,23 @@ pub fn init(config: config::Config) -> Peripherals {
710 #[allow(unused_mut)] 714 #[allow(unused_mut)]
711 let mut needs_reset = false; 715 let mut needs_reset = false;
712 716
717 // set clock speed
718 #[cfg(feature = "_nrf54l")]
719 {
720 #[cfg(feature = "_s")]
721 let regs = pac::OSCILLATORS_S;
722 #[cfg(feature = "_ns")]
723 let regs = pac::OSCILLATORS_NS;
724
725 use pac::oscillators::vals::Freq;
726 regs.pll().freq().write(|w| {
727 w.set_freq(match config.clock_speed {
728 config::ClockSpeed::CK64 => Freq::CK64M,
729 config::ClockSpeed::CK128 => Freq::CK128M,
730 });
731 });
732 }
733
713 // Workaround used in the nrf mdk: file system_nrf91.c , function SystemInit(), after `#if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND)` 734 // Workaround used in the nrf mdk: file system_nrf91.c , function SystemInit(), after `#if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND)`
714 #[cfg(all(feature = "_nrf91", feature = "_s"))] 735 #[cfg(all(feature = "_nrf91", feature = "_s"))]
715 { 736 {
@@ -934,7 +955,7 @@ pub fn init(config: config::Config) -> Peripherals {
934 } 955 }
935 } 956 }
936 957
937 #[cfg(any(feature = "_nrf52", feature = "_nrf5340-app"))] 958 #[cfg(any(feature = "_nrf52", all(feature = "_nrf5340-app", feature = "_s")))]
938 unsafe { 959 unsafe {
939 let value = if cfg!(feature = "nfc-pins-as-gpio") { 0 } else { 1 }; 960 let value = if cfg!(feature = "nfc-pins-as-gpio") { 0 } else { 1 };
940 let res = uicr_write_masked(consts::UICR_NFCPINS, value, 1); 961 let res = uicr_write_masked(consts::UICR_NFCPINS, value, 1);
@@ -1154,7 +1175,6 @@ pub fn init(config: config::Config) -> Peripherals {
1154 } 1175 }
1155 1176
1156 // Init GPIOTE 1177 // Init GPIOTE
1157 #[cfg(not(feature = "_nrf54l"))] // TODO
1158 #[cfg(feature = "gpiote")] 1178 #[cfg(feature = "gpiote")]
1159 gpiote::init(config.gpiote_interrupt_priority); 1179 gpiote::init(config.gpiote_interrupt_priority);
1160 1180
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs
index 168647be3..d43a25c4e 100644
--- a/embassy-nrf/src/ppi/dppi.rs
+++ b/embassy-nrf/src/ppi/dppi.rs
@@ -1,11 +1,12 @@
1use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; 1use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
2use crate::{Peri, pac}; 2use crate::Peri;
3 3
4const DPPI_ENABLE_BIT: u32 = 0x8000_0000; 4const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
5const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; 5const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
6 6
7pub(crate) fn regs() -> pac::dppic::Dppic { 7#[cfg(not(feature = "_nrf54l"))]
8 pac::DPPIC 8pub(crate) fn regs() -> crate::pac::dppic::Dppic {
9 crate::pac::DPPIC
9} 10}
10 11
11impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { 12impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
@@ -49,13 +50,13 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Ppi<'d,
49 /// Enables the channel. 50 /// Enables the channel.
50 pub fn enable(&mut self) { 51 pub fn enable(&mut self) {
51 let n = self.ch.number(); 52 let n = self.ch.number();
52 regs().chenset().write(|w| w.0 = 1 << n); 53 self.ch.regs().chenset().write(|w| w.0 = 1 << n);
53 } 54 }
54 55
55 /// Disables the channel. 56 /// Disables the channel.
56 pub fn disable(&mut self) { 57 pub fn disable(&mut self) {
57 let n = self.ch.number(); 58 let n = self.ch.number();
58 regs().chenclr().write(|w| w.0 = 1 << n); 59 self.ch.regs().chenclr().write(|w| w.0 = 1 << n);
59 } 60 }
60} 61}
61 62
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index f30c2218d..a880d3188 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -21,11 +21,13 @@ use core::ptr::NonNull;
21use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral}; 21use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral};
22 22
23use crate::pac::common::{RW, Reg, W}; 23use crate::pac::common::{RW, Reg, W};
24use crate::peripherals; 24use crate::pac::{self};
25 25
26#[cfg_attr(feature = "_dppi", path = "dppi.rs")] 26#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
27#[cfg_attr(feature = "_ppi", path = "ppi.rs")] 27#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
28mod _version; 28mod _version;
29
30#[allow(unused_imports)]
29pub(crate) use _version::*; 31pub(crate) use _version::*;
30 32
31/// PPI channel driver. 33/// PPI channel driver.
@@ -47,7 +49,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
47 /// 49 ///
48 /// The group is initialized as containing no channels. 50 /// The group is initialized as containing no channels.
49 pub fn new(g: Peri<'d, G>) -> Self { 51 pub fn new(g: Peri<'d, G>) -> Self {
50 let r = regs(); 52 let r = g.regs();
51 let n = g.number(); 53 let n = g.number();
52 r.chg(n).write(|_| ()); 54 r.chg(n).write(|_| ());
53 55
@@ -61,7 +63,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
61 &mut self, 63 &mut self,
62 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>, 64 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
63 ) { 65 ) {
64 let r = regs(); 66 let r = self.g.regs();
65 let ng = self.g.number(); 67 let ng = self.g.number();
66 let nc = ch.ch.number(); 68 let nc = ch.ch.number();
67 r.chg(ng).modify(|w| w.set_ch(nc, true)); 69 r.chg(ng).modify(|w| w.set_ch(nc, true));
@@ -74,7 +76,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
74 &mut self, 76 &mut self,
75 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>, 77 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
76 ) { 78 ) {
77 let r = regs(); 79 let r = self.g.regs();
78 let ng = self.g.number(); 80 let ng = self.g.number();
79 let nc = ch.ch.number(); 81 let nc = ch.ch.number();
80 r.chg(ng).modify(|w| w.set_ch(nc, false)); 82 r.chg(ng).modify(|w| w.set_ch(nc, false));
@@ -83,13 +85,13 @@ impl<'d, G: Group> PpiGroup<'d, G> {
83 /// Enable all the channels in this group. 85 /// Enable all the channels in this group.
84 pub fn enable_all(&mut self) { 86 pub fn enable_all(&mut self) {
85 let n = self.g.number(); 87 let n = self.g.number();
86 regs().tasks_chg(n).en().write_value(1); 88 self.g.regs().tasks_chg(n).en().write_value(1);
87 } 89 }
88 90
89 /// Disable all the channels in this group. 91 /// Disable all the channels in this group.
90 pub fn disable_all(&mut self) { 92 pub fn disable_all(&mut self) {
91 let n = self.g.number(); 93 let n = self.g.number();
92 regs().tasks_chg(n).dis().write_value(1); 94 self.g.regs().tasks_chg(n).dis().write_value(1);
93 } 95 }
94 96
95 /// Get a reference to the "enable all" task. 97 /// Get a reference to the "enable all" task.
@@ -97,7 +99,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
97 /// When triggered, it will enable all the channels in this group. 99 /// When triggered, it will enable all the channels in this group.
98 pub fn task_enable_all(&self) -> Task<'d> { 100 pub fn task_enable_all(&self) -> Task<'d> {
99 let n = self.g.number(); 101 let n = self.g.number();
100 Task::from_reg(regs().tasks_chg(n).en()) 102 Task::from_reg(self.g.regs().tasks_chg(n).en())
101 } 103 }
102 104
103 /// Get a reference to the "disable all" task. 105 /// Get a reference to the "disable all" task.
@@ -105,7 +107,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
105 /// When triggered, it will disable all the channels in this group. 107 /// When triggered, it will disable all the channels in this group.
106 pub fn task_disable_all(&self) -> Task<'d> { 108 pub fn task_disable_all(&self) -> Task<'d> {
107 let n = self.g.number(); 109 let n = self.g.number();
108 Task::from_reg(regs().tasks_chg(n).dis()) 110 Task::from_reg(self.g.regs().tasks_chg(n).dis())
109 } 111 }
110} 112}
111impl<G: Group> PpiGroup<'static, G> { 113impl<G: Group> PpiGroup<'static, G> {
@@ -119,7 +121,7 @@ impl<G: Group> PpiGroup<'static, G> {
119 121
120impl<'d, G: Group> Drop for PpiGroup<'d, G> { 122impl<'d, G: Group> Drop for PpiGroup<'d, G> {
121 fn drop(&mut self) { 123 fn drop(&mut self) {
122 let r = regs(); 124 let r = self.g.regs();
123 let n = self.g.number(); 125 let n = self.g.number();
124 r.chg(n).write(|_| ()); 126 r.chg(n).write(|_| ());
125 } 127 }
@@ -211,8 +213,16 @@ unsafe impl Send for Event<'_> {}
211// ====================== 213// ======================
212// traits 214// traits
213 215
214pub(crate) trait SealedChannel {} 216pub(crate) trait SealedChannel {
215pub(crate) trait SealedGroup {} 217 #[cfg(feature = "_dppi")]
218 fn regs(&self) -> pac::dppic::Dppic;
219}
220pub(crate) trait SealedGroup {
221 #[cfg(feature = "_dppi")]
222 fn regs(&self) -> pac::dppic::Dppic;
223 #[cfg(not(feature = "_dppi"))]
224 fn regs(&self) -> pac::ppi::Ppi;
225}
216 226
217/// Interface for PPI channels. 227/// Interface for PPI channels.
218#[allow(private_bounds)] 228#[allow(private_bounds)]
@@ -241,9 +251,16 @@ pub trait Group: SealedGroup + PeripheralType + Into<AnyGroup> + Sized + 'static
241/// This can be used to have fewer generic parameters in some places. 251/// This can be used to have fewer generic parameters in some places.
242pub struct AnyStaticChannel { 252pub struct AnyStaticChannel {
243 pub(crate) number: u8, 253 pub(crate) number: u8,
254 #[cfg(feature = "_dppi")]
255 pub(crate) regs: pac::dppic::Dppic,
244} 256}
245impl_peripheral!(AnyStaticChannel); 257impl_peripheral!(AnyStaticChannel);
246impl SealedChannel for AnyStaticChannel {} 258impl SealedChannel for AnyStaticChannel {
259 #[cfg(feature = "_dppi")]
260 fn regs(&self) -> pac::dppic::Dppic {
261 self.regs
262 }
263}
247impl Channel for AnyStaticChannel { 264impl Channel for AnyStaticChannel {
248 fn number(&self) -> usize { 265 fn number(&self) -> usize {
249 self.number as usize 266 self.number as usize
@@ -255,9 +272,16 @@ impl StaticChannel for AnyStaticChannel {}
255/// This can be used to have fewer generic parameters in some places. 272/// This can be used to have fewer generic parameters in some places.
256pub struct AnyConfigurableChannel { 273pub struct AnyConfigurableChannel {
257 pub(crate) number: u8, 274 pub(crate) number: u8,
275 #[cfg(feature = "_dppi")]
276 pub(crate) regs: pac::dppic::Dppic,
258} 277}
259impl_peripheral!(AnyConfigurableChannel); 278impl_peripheral!(AnyConfigurableChannel);
260impl SealedChannel for AnyConfigurableChannel {} 279impl SealedChannel for AnyConfigurableChannel {
280 #[cfg(feature = "_dppi")]
281 fn regs(&self) -> pac::dppic::Dppic {
282 self.regs
283 }
284}
261impl Channel for AnyConfigurableChannel { 285impl Channel for AnyConfigurableChannel {
262 fn number(&self) -> usize { 286 fn number(&self) -> usize {
263 self.number as usize 287 self.number as usize
@@ -267,32 +291,41 @@ impl ConfigurableChannel for AnyConfigurableChannel {}
267 291
268#[cfg(not(feature = "_nrf51"))] 292#[cfg(not(feature = "_nrf51"))]
269macro_rules! impl_ppi_channel { 293macro_rules! impl_ppi_channel {
270 ($type:ident, $number:expr) => { 294 ($type:ident, $inst:ident, $number:expr) => {
271 impl crate::ppi::SealedChannel for peripherals::$type {} 295 impl crate::ppi::SealedChannel for peripherals::$type {
296 #[cfg(feature = "_dppi")]
297 fn regs(&self) -> pac::dppic::Dppic {
298 pac::$inst
299 }
300 }
272 impl crate::ppi::Channel for peripherals::$type { 301 impl crate::ppi::Channel for peripherals::$type {
273 fn number(&self) -> usize { 302 fn number(&self) -> usize {
274 $number 303 $number
275 } 304 }
276 } 305 }
277 }; 306 };
278 ($type:ident, $number:expr => static) => { 307 ($type:ident, $inst:ident, $number:expr => static) => {
279 impl_ppi_channel!($type, $number); 308 impl_ppi_channel!($type, $inst, $number);
280 impl crate::ppi::StaticChannel for peripherals::$type {} 309 impl crate::ppi::StaticChannel for peripherals::$type {}
281 impl From<peripherals::$type> for crate::ppi::AnyStaticChannel { 310 impl From<peripherals::$type> for crate::ppi::AnyStaticChannel {
282 fn from(val: peripherals::$type) -> Self { 311 fn from(val: peripherals::$type) -> Self {
283 Self { 312 Self {
284 number: crate::ppi::Channel::number(&val) as u8, 313 number: crate::ppi::Channel::number(&val) as u8,
314 #[cfg(feature = "_dppi")]
315 regs: pac::$inst,
285 } 316 }
286 } 317 }
287 } 318 }
288 }; 319 };
289 ($type:ident, $number:expr => configurable) => { 320 ($type:ident, $inst:ident, $number:expr => configurable) => {
290 impl_ppi_channel!($type, $number); 321 impl_ppi_channel!($type, $inst, $number);
291 impl crate::ppi::ConfigurableChannel for peripherals::$type {} 322 impl crate::ppi::ConfigurableChannel for peripherals::$type {}
292 impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel { 323 impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel {
293 fn from(val: peripherals::$type) -> Self { 324 fn from(val: peripherals::$type) -> Self {
294 Self { 325 Self {
295 number: crate::ppi::Channel::number(&val) as u8, 326 number: crate::ppi::Channel::number(&val) as u8,
327 #[cfg(feature = "_dppi")]
328 regs: pac::$inst,
296 } 329 }
297 } 330 }
298 } 331 }
@@ -304,40 +337,54 @@ macro_rules! impl_ppi_channel {
304 337
305/// A type erased PPI group. 338/// A type erased PPI group.
306pub struct AnyGroup { 339pub struct AnyGroup {
307 number: u8, 340 pub(crate) number: u8,
341 #[cfg(feature = "_dppi")]
342 pub(crate) regs: pac::dppic::Dppic,
343 #[cfg(not(feature = "_dppi"))]
344 pub(crate) regs: pac::ppi::Ppi,
308} 345}
309impl_peripheral!(AnyGroup); 346impl_peripheral!(AnyGroup);
310impl SealedGroup for AnyGroup {} 347impl SealedGroup for AnyGroup {
348 #[cfg(feature = "_dppi")]
349 fn regs(&self) -> pac::dppic::Dppic {
350 self.regs
351 }
352 #[cfg(not(feature = "_dppi"))]
353 fn regs(&self) -> pac::ppi::Ppi {
354 self.regs
355 }
356}
311impl Group for AnyGroup { 357impl Group for AnyGroup {
312 fn number(&self) -> usize { 358 fn number(&self) -> usize {
313 self.number as usize 359 self.number as usize
314 } 360 }
315} 361}
316 362
317macro_rules! impl_group { 363macro_rules! impl_ppi_group {
318 ($type:ident, $number:expr) => { 364 ($type:ident, $inst:ident, $number:expr) => {
319 impl SealedGroup for peripherals::$type {} 365 impl crate::ppi::SealedGroup for crate::peripherals::$type {
320 impl Group for peripherals::$type { 366 #[cfg(feature = "_dppi")]
367 fn regs(&self) -> pac::dppic::Dppic {
368 pac::$inst
369 }
370 #[cfg(not(feature = "_dppi"))]
371 fn regs(&self) -> pac::ppi::Ppi {
372 pac::$inst
373 }
374 }
375 impl crate::ppi::Group for crate::peripherals::$type {
321 fn number(&self) -> usize { 376 fn number(&self) -> usize {
322 $number 377 $number
323 } 378 }
324 } 379 }
325 380
326 impl From<peripherals::$type> for crate::ppi::AnyGroup { 381 impl From<crate::peripherals::$type> for crate::ppi::AnyGroup {
327 fn from(val: peripherals::$type) -> Self { 382 fn from(val: crate::peripherals::$type) -> Self {
328 Self { 383 Self {
329 number: crate::ppi::Group::number(&val) as u8, 384 number: crate::ppi::Group::number(&val) as u8,
385 regs: pac::$inst,
330 } 386 }
331 } 387 }
332 } 388 }
333 }; 389 };
334} 390}
335
336impl_group!(PPI_GROUP0, 0);
337impl_group!(PPI_GROUP1, 1);
338impl_group!(PPI_GROUP2, 2);
339impl_group!(PPI_GROUP3, 3);
340#[cfg(not(feature = "_nrf51"))]
341impl_group!(PPI_GROUP4, 4);
342#[cfg(not(feature = "_nrf51"))]
343impl_group!(PPI_GROUP5, 5);
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index e038f44b8..04eb14a77 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -6,7 +6,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
6 6
7use embassy_hal_internal::{Peri, PeripheralType}; 7use embassy_hal_internal::{Peri, PeripheralType};
8 8
9use crate::gpio::{AnyPin, DISCONNECTED, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive}; 9use crate::gpio::{AnyPin, DISCONNECTED, Level, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
10use crate::pac::gpio::vals as gpiovals; 10use crate::pac::gpio::vals as gpiovals;
11use crate::pac::pwm::vals; 11use crate::pac::pwm::vals;
12use crate::ppi::{Event, Task}; 12use crate::ppi::{Event, Task};
@@ -17,7 +17,7 @@ use crate::{interrupt, pac};
17/// to simply set a duty cycle across up to four channels. 17/// to simply set a duty cycle across up to four channels.
18pub struct SimplePwm<'d> { 18pub struct SimplePwm<'d> {
19 r: pac::pwm::Pwm, 19 r: pac::pwm::Pwm,
20 duty: [u16; 4], 20 duty: [DutyCycle; 4],
21 ch0: Option<Peri<'d, AnyPin>>, 21 ch0: Option<Peri<'d, AnyPin>>,
22 ch1: Option<Peri<'d, AnyPin>>, 22 ch1: Option<Peri<'d, AnyPin>>,
23 ch2: Option<Peri<'d, AnyPin>>, 23 ch2: Option<Peri<'d, AnyPin>>,
@@ -53,13 +53,11 @@ pub const PWM_CLK_HZ: u32 = 16_000_000;
53 53
54impl<'d> SequencePwm<'d> { 54impl<'d> SequencePwm<'d> {
55 /// Create a new 1-channel PWM 55 /// Create a new 1-channel PWM
56 #[allow(unused_unsafe)]
57 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> { 56 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> {
58 Self::new_inner(pwm, Some(ch0.into()), None, None, None, config) 57 Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
59 } 58 }
60 59
61 /// Create a new 2-channel PWM 60 /// Create a new 2-channel PWM
62 #[allow(unused_unsafe)]
63 pub fn new_2ch<T: Instance>( 61 pub fn new_2ch<T: Instance>(
64 pwm: Peri<'d, T>, 62 pwm: Peri<'d, T>,
65 ch0: Peri<'d, impl GpioPin>, 63 ch0: Peri<'d, impl GpioPin>,
@@ -70,7 +68,6 @@ impl<'d> SequencePwm<'d> {
70 } 68 }
71 69
72 /// Create a new 3-channel PWM 70 /// Create a new 3-channel PWM
73 #[allow(unused_unsafe)]
74 pub fn new_3ch<T: Instance>( 71 pub fn new_3ch<T: Instance>(
75 pwm: Peri<'d, T>, 72 pwm: Peri<'d, T>,
76 ch0: Peri<'d, impl GpioPin>, 73 ch0: Peri<'d, impl GpioPin>,
@@ -82,7 +79,6 @@ impl<'d> SequencePwm<'d> {
82 } 79 }
83 80
84 /// Create a new 4-channel PWM 81 /// Create a new 4-channel PWM
85 #[allow(unused_unsafe)]
86 pub fn new_4ch<T: Instance>( 82 pub fn new_4ch<T: Instance>(
87 pwm: Peri<'d, T>, 83 pwm: Peri<'d, T>,
88 ch0: Peri<'d, impl GpioPin>, 84 ch0: Peri<'d, impl GpioPin>,
@@ -111,44 +107,27 @@ impl<'d> SequencePwm<'d> {
111 ) -> Result<Self, Error> { 107 ) -> Result<Self, Error> {
112 let r = T::regs(); 108 let r = T::regs();
113 109
114 if let Some(pin) = &ch0 { 110 let channels = [
115 pin.set_low(); 111 (&ch0, config.ch0_drive, config.ch0_idle_level),
116 pin.conf().write(|w| { 112 (&ch1, config.ch1_drive, config.ch1_idle_level),
117 w.set_dir(gpiovals::Dir::OUTPUT); 113 (&ch2, config.ch2_drive, config.ch2_idle_level),
118 w.set_input(gpiovals::Input::DISCONNECT); 114 (&ch3, config.ch3_drive, config.ch3_idle_level),
119 convert_drive(w, config.ch0_drive); 115 ];
120 }); 116 for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() {
121 } 117 if let Some(pin) = pin {
122 if let Some(pin) = &ch1 { 118 match idle_level {
123 pin.set_low(); 119 Level::Low => pin.set_low(),
124 pin.conf().write(|w| { 120 Level::High => pin.set_high(),
125 w.set_dir(gpiovals::Dir::OUTPUT); 121 }
126 w.set_input(gpiovals::Input::DISCONNECT); 122 pin.conf().write(|w| {
127 convert_drive(w, config.ch1_drive); 123 w.set_dir(gpiovals::Dir::OUTPUT);
128 }); 124 w.set_input(gpiovals::Input::DISCONNECT);
129 } 125 convert_drive(w, drive);
130 if let Some(pin) = &ch2 { 126 });
131 pin.set_low(); 127 }
132 pin.conf().write(|w| { 128 r.psel().out(i).write_value(pin.psel_bits());
133 w.set_dir(gpiovals::Dir::OUTPUT);
134 w.set_input(gpiovals::Input::DISCONNECT);
135 convert_drive(w, config.ch2_drive);
136 });
137 }
138 if let Some(pin) = &ch3 {
139 pin.set_low();
140 pin.conf().write(|w| {
141 w.set_dir(gpiovals::Dir::OUTPUT);
142 w.set_input(gpiovals::Input::DISCONNECT);
143 convert_drive(w, config.ch3_drive);
144 });
145 } 129 }
146 130
147 r.psel().out(0).write_value(ch0.psel_bits());
148 r.psel().out(1).write_value(ch1.psel_bits());
149 r.psel().out(2).write_value(ch2.psel_bits());
150 r.psel().out(3).write_value(ch3.psel_bits());
151
152 // Disable all interrupts 131 // Disable all interrupts
153 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF); 132 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
154 r.shorts().write(|_| ()); 133 r.shorts().write(|_| ());
@@ -173,13 +152,7 @@ impl<'d> SequencePwm<'d> {
173 .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8))); 152 .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8)));
174 r.countertop().write(|w| w.set_countertop(config.max_duty)); 153 r.countertop().write(|w| w.set_countertop(config.max_duty));
175 154
176 Ok(Self { 155 Ok(Self { r, ch0, ch1, ch2, ch3 })
177 r: T::regs(),
178 ch0,
179 ch1,
180 ch2,
181 ch3,
182 })
183 } 156 }
184 157
185 /// Returns reference to `Stopped` event endpoint for PPI. 158 /// Returns reference to `Stopped` event endpoint for PPI.
@@ -230,7 +203,7 @@ impl<'d> SequencePwm<'d> {
230 /// Interacting with the sequence while it runs puts it in an unknown state 203 /// Interacting with the sequence while it runs puts it in an unknown state
231 #[inline(always)] 204 #[inline(always)]
232 pub unsafe fn task_start_seq0(&self) -> Task<'d> { 205 pub unsafe fn task_start_seq0(&self) -> Task<'d> {
233 Task::from_reg(self.r.tasks_seqstart(0)) 206 Task::from_reg(self.r.tasks_dma().seq(0).start())
234 } 207 }
235 208
236 /// Returns reference to `Seq1 Started` task endpoint for PPI. 209 /// Returns reference to `Seq1 Started` task endpoint for PPI.
@@ -239,7 +212,7 @@ impl<'d> SequencePwm<'d> {
239 /// Interacting with the sequence while it runs puts it in an unknown state 212 /// Interacting with the sequence while it runs puts it in an unknown state
240 #[inline(always)] 213 #[inline(always)]
241 pub unsafe fn task_start_seq1(&self) -> Task<'d> { 214 pub unsafe fn task_start_seq1(&self) -> Task<'d> {
242 Task::from_reg(self.r.tasks_seqstart(1)) 215 Task::from_reg(self.r.tasks_dma().seq(1).start())
243 } 216 }
244 217
245 /// Returns reference to `NextStep` task endpoint for PPI. 218 /// Returns reference to `NextStep` task endpoint for PPI.
@@ -289,6 +262,8 @@ impl<'a> Drop for SequencePwm<'a> {
289} 262}
290 263
291/// Configuration for the PWM as a whole. 264/// Configuration for the PWM as a whole.
265#[derive(Debug, Clone)]
266#[cfg_attr(feature = "defmt", derive(defmt::Format))]
292#[non_exhaustive] 267#[non_exhaustive]
293pub struct Config { 268pub struct Config {
294 /// Selects up mode or up-and-down mode for the counter 269 /// Selects up mode or up-and-down mode for the counter
@@ -307,11 +282,19 @@ pub struct Config {
307 pub ch2_drive: OutputDrive, 282 pub ch2_drive: OutputDrive,
308 /// Drive strength for the channel 3 line. 283 /// Drive strength for the channel 3 line.
309 pub ch3_drive: OutputDrive, 284 pub ch3_drive: OutputDrive,
285 /// Output level for the channel 0 line when PWM if disabled.
286 pub ch0_idle_level: Level,
287 /// Output level for the channel 1 line when PWM if disabled.
288 pub ch1_idle_level: Level,
289 /// Output level for the channel 2 line when PWM if disabled.
290 pub ch2_idle_level: Level,
291 /// Output level for the channel 3 line when PWM if disabled.
292 pub ch3_idle_level: Level,
310} 293}
311 294
312impl Default for Config { 295impl Default for Config {
313 fn default() -> Config { 296 fn default() -> Self {
314 Config { 297 Self {
315 counter_mode: CounterMode::Up, 298 counter_mode: CounterMode::Up,
316 max_duty: 1000, 299 max_duty: 1000,
317 prescaler: Prescaler::Div16, 300 prescaler: Prescaler::Div16,
@@ -320,13 +303,65 @@ impl Default for Config {
320 ch1_drive: OutputDrive::Standard, 303 ch1_drive: OutputDrive::Standard,
321 ch2_drive: OutputDrive::Standard, 304 ch2_drive: OutputDrive::Standard,
322 ch3_drive: OutputDrive::Standard, 305 ch3_drive: OutputDrive::Standard,
306 ch0_idle_level: Level::Low,
307 ch1_idle_level: Level::Low,
308 ch2_idle_level: Level::Low,
309 ch3_idle_level: Level::Low,
310 }
311 }
312}
313
314/// Configuration for the simple PWM driver.
315#[derive(Debug, Clone)]
316#[cfg_attr(feature = "defmt", derive(defmt::Format))]
317#[non_exhaustive]
318pub struct SimpleConfig {
319 /// Selects up mode or up-and-down mode for the counter
320 pub counter_mode: CounterMode,
321 /// Top value to be compared against buffer values
322 pub max_duty: u16,
323 /// Configuration for PWM_CLK
324 pub prescaler: Prescaler,
325 /// Drive strength for the channel 0 line.
326 pub ch0_drive: OutputDrive,
327 /// Drive strength for the channel 1 line.
328 pub ch1_drive: OutputDrive,
329 /// Drive strength for the channel 2 line.
330 pub ch2_drive: OutputDrive,
331 /// Drive strength for the channel 3 line.
332 pub ch3_drive: OutputDrive,
333 /// Output level for the channel 0 line when PWM if disabled.
334 pub ch0_idle_level: Level,
335 /// Output level for the channel 1 line when PWM if disabled.
336 pub ch1_idle_level: Level,
337 /// Output level for the channel 2 line when PWM if disabled.
338 pub ch2_idle_level: Level,
339 /// Output level for the channel 3 line when PWM if disabled.
340 pub ch3_idle_level: Level,
341}
342
343impl Default for SimpleConfig {
344 fn default() -> Self {
345 Self {
346 counter_mode: CounterMode::Up,
347 max_duty: 1000,
348 prescaler: Prescaler::Div16,
349 ch0_drive: OutputDrive::Standard,
350 ch1_drive: OutputDrive::Standard,
351 ch2_drive: OutputDrive::Standard,
352 ch3_drive: OutputDrive::Standard,
353 ch0_idle_level: Level::Low,
354 ch1_idle_level: Level::Low,
355 ch2_idle_level: Level::Low,
356 ch3_idle_level: Level::Low,
323 } 357 }
324 } 358 }
325} 359}
326 360
327/// Configuration per sequence 361/// Configuration per sequence
328#[non_exhaustive] 362#[non_exhaustive]
329#[derive(Clone)] 363#[derive(Debug, Clone)]
364#[cfg_attr(feature = "defmt", derive(defmt::Format))]
330pub struct SequenceConfig { 365pub struct SequenceConfig {
331 /// Number of PWM periods to delay between each sequence sample 366 /// Number of PWM periods to delay between each sequence sample
332 pub refresh: u32, 367 pub refresh: u32,
@@ -345,6 +380,8 @@ impl Default for SequenceConfig {
345 380
346/// A composition of a sequence buffer and its configuration. 381/// A composition of a sequence buffer and its configuration.
347#[non_exhaustive] 382#[non_exhaustive]
383#[derive(Debug, Clone)]
384#[cfg_attr(feature = "defmt", derive(defmt::Format))]
348pub struct Sequence<'s> { 385pub struct Sequence<'s> {
349 /// The words comprising the sequence. Must not exceed 32767 words. 386 /// The words comprising the sequence. Must not exceed 32767 words.
350 pub words: &'s [u16], 387 pub words: &'s [u16],
@@ -407,6 +444,21 @@ pub struct Sequencer<'d, 's> {
407 sequence1: Option<Sequence<'s>>, 444 sequence1: Option<Sequence<'s>>,
408} 445}
409 446
447#[cfg(feature = "_nrf54l")]
448fn pwmseq(r: pac::pwm::Pwm, n: usize) -> pac::pwm::PwmSeq {
449 r.seq(n)
450}
451
452#[cfg(not(feature = "_nrf54l"))]
453fn pwmseq(r: pac::pwm::Pwm, n: usize) -> pac::pwm::DmaSeq {
454 r.dma().seq(n)
455}
456
457#[cfg(feature = "_nrf54l")]
458const CNT_UNIT: u32 = 2;
459#[cfg(not(feature = "_nrf54l"))]
460const CNT_UNIT: u32 = 1;
461
410impl<'d, 's> Sequencer<'d, 's> { 462impl<'d, 's> Sequencer<'d, 's> {
411 /// Create a new double sequence. In the absence of sequence 1, sequence 0 463 /// Create a new double sequence. In the absence of sequence 1, sequence 0
412 /// will be used twice in the one loop. 464 /// will be used twice in the one loop.
@@ -439,15 +491,21 @@ impl<'d, 's> Sequencer<'d, 's> {
439 491
440 let r = self._pwm.r; 492 let r = self._pwm.r;
441 493
442 r.seq(0).refresh().write(|w| w.0 = sequence0.config.refresh); 494 pwmseq(r, 0).refresh().write(|w| w.0 = sequence0.config.refresh);
443 r.seq(0).enddelay().write(|w| w.0 = sequence0.config.end_delay); 495 pwmseq(r, 0).enddelay().write(|w| w.0 = sequence0.config.end_delay);
444 r.seq(0).ptr().write_value(sequence0.words.as_ptr() as u32); 496 r.dma().seq(0).ptr().write_value(sequence0.words.as_ptr() as u32);
445 r.seq(0).cnt().write(|w| w.0 = sequence0.words.len() as u32); 497 r.dma()
446 498 .seq(0)
447 r.seq(1).refresh().write(|w| w.0 = alt_sequence.config.refresh); 499 .maxcnt()
448 r.seq(1).enddelay().write(|w| w.0 = alt_sequence.config.end_delay); 500 .write(|w| w.0 = sequence0.words.len() as u32 * CNT_UNIT);
449 r.seq(1).ptr().write_value(alt_sequence.words.as_ptr() as u32); 501
450 r.seq(1).cnt().write(|w| w.0 = alt_sequence.words.len() as u32); 502 pwmseq(r, 1).refresh().write(|w| w.0 = alt_sequence.config.refresh);
503 pwmseq(r, 1).enddelay().write(|w| w.0 = alt_sequence.config.end_delay);
504 r.dma().seq(1).ptr().write_value(alt_sequence.words.as_ptr() as u32);
505 r.dma()
506 .seq(1)
507 .maxcnt()
508 .write(|w| w.0 = alt_sequence.words.len() as u32 * CNT_UNIT);
451 509
452 r.enable().write(|w| w.set_enable(true)); 510 r.enable().write(|w| w.set_enable(true));
453 511
@@ -463,11 +521,11 @@ impl<'d, 's> Sequencer<'d, 's> {
463 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again 521 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again
464 SequenceMode::Infinite => { 522 SequenceMode::Infinite => {
465 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(1))); 523 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::from_bits(1)));
466 r.shorts().write(|w| w.set_loopsdone_seqstart0(true)); 524 r.shorts().write(|w| w.set_loopsdone_dma_seq0_start(true));
467 } 525 }
468 } 526 }
469 527
470 r.tasks_seqstart(seqstart_index).write_value(1); 528 r.tasks_dma().seq(seqstart_index).start().write_value(1);
471 529
472 Ok(()) 530 Ok(())
473 } 531 }
@@ -496,6 +554,7 @@ impl<'d, 's> Drop for Sequencer<'d, 's> {
496 554
497/// How many times to run a single sequence 555/// How many times to run a single sequence
498#[derive(Debug, Eq, PartialEq, Clone, Copy)] 556#[derive(Debug, Eq, PartialEq, Clone, Copy)]
557#[cfg_attr(feature = "defmt", derive(defmt::Format))]
499pub enum SingleSequenceMode { 558pub enum SingleSequenceMode {
500 /// Run a single sequence n Times total. 559 /// Run a single sequence n Times total.
501 Times(u16), 560 Times(u16),
@@ -505,6 +564,7 @@ pub enum SingleSequenceMode {
505 564
506/// Which sequence to start a loop with 565/// Which sequence to start a loop with
507#[derive(Debug, Eq, PartialEq, Clone, Copy)] 566#[derive(Debug, Eq, PartialEq, Clone, Copy)]
567#[cfg_attr(feature = "defmt", derive(defmt::Format))]
508pub enum StartSequence { 568pub enum StartSequence {
509 /// Start with Sequence 0 569 /// Start with Sequence 0
510 Zero, 570 Zero,
@@ -514,6 +574,7 @@ pub enum StartSequence {
514 574
515/// How many loops to run two sequences 575/// How many loops to run two sequences
516#[derive(Debug, Eq, PartialEq, Clone, Copy)] 576#[derive(Debug, Eq, PartialEq, Clone, Copy)]
577#[cfg_attr(feature = "defmt", derive(defmt::Format))]
517pub enum SequenceMode { 578pub enum SequenceMode {
518 /// Run two sequences n loops i.e. (n * (seq0 + seq1.unwrap_or(seq0))) 579 /// Run two sequences n loops i.e. (n * (seq0 + seq1.unwrap_or(seq0)))
519 Loop(u16), 580 Loop(u16),
@@ -523,6 +584,7 @@ pub enum SequenceMode {
523 584
524/// PWM Base clock is system clock (16MHz) divided by prescaler 585/// PWM Base clock is system clock (16MHz) divided by prescaler
525#[derive(Debug, Eq, PartialEq, Clone, Copy)] 586#[derive(Debug, Eq, PartialEq, Clone, Copy)]
587#[cfg_attr(feature = "defmt", derive(defmt::Format))]
526pub enum Prescaler { 588pub enum Prescaler {
527 /// Divide by 1 589 /// Divide by 1
528 Div1, 590 Div1,
@@ -544,6 +606,7 @@ pub enum Prescaler {
544 606
545/// How the sequence values are distributed across the channels 607/// How the sequence values are distributed across the channels
546#[derive(Debug, Eq, PartialEq, Clone, Copy)] 608#[derive(Debug, Eq, PartialEq, Clone, Copy)]
609#[cfg_attr(feature = "defmt", derive(defmt::Format))]
547pub enum SequenceLoad { 610pub enum SequenceLoad {
548 /// Provided sequence will be used across all channels 611 /// Provided sequence will be used across all channels
549 Common, 612 Common,
@@ -560,6 +623,7 @@ pub enum SequenceLoad {
560 623
561/// Selects up mode or up-and-down mode for the counter 624/// Selects up mode or up-and-down mode for the counter
562#[derive(Debug, Eq, PartialEq, Clone, Copy)] 625#[derive(Debug, Eq, PartialEq, Clone, Copy)]
626#[cfg_attr(feature = "defmt", derive(defmt::Format))]
563pub enum CounterMode { 627pub enum CounterMode {
564 /// Up counter (edge-aligned PWM duty cycle) 628 /// Up counter (edge-aligned PWM duty cycle)
565 Up, 629 Up,
@@ -567,48 +631,128 @@ pub enum CounterMode {
567 UpAndDown, 631 UpAndDown,
568} 632}
569 633
634/// Duty value and polarity for a single channel.
635///
636/// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value.
637#[repr(transparent)]
638#[derive(Eq, PartialEq, Clone, Copy)]
639pub struct DutyCycle {
640 /// The raw duty cycle valuea.
641 ///
642 /// This has the duty cycle in the lower 15 bits.
643 /// The highest bit indicates that the duty cycle has inverted polarity.
644 raw: u16,
645}
646
647impl DutyCycle {
648 /// Make a new duty value with normal polarity.
649 ///
650 /// The value is truncated to 15 bits.
651 ///
652 /// The output is set high if the counter is at or above the duty value.
653 pub const fn normal(value: u16) -> Self {
654 let raw = value & 0x7FFF;
655 Self { raw }
656 }
657
658 /// Make a new duty cycle with inverted polarity.
659 ///
660 /// The value is truncated to 15 bits.
661 ///
662 /// The output is set high if the counter is below the duty value.
663 pub const fn inverted(value: u16) -> Self {
664 let raw = value | 0x8000;
665 Self { raw }
666 }
667
668 /// Adjust the polarity of the duty cycle (returns a new object).
669 #[must_use = "this function return a new object, it does not modify self"]
670 pub const fn with_inverted(self, inverted_polarity: bool) -> Self {
671 if inverted_polarity {
672 Self::inverted(self.value())
673 } else {
674 Self::normal(self.value())
675 }
676 }
677
678 /// Gets the 15-bit value of the duty cycle.
679 pub const fn value(&self) -> u16 {
680 self.raw & 0x7FFF
681 }
682
683 /// Checks if the duty period has inverted polarity.
684 ///
685 /// If the channel has inverted polarity, the output is set high as long as the counter is below the duty value.
686 pub const fn is_inverted(&self) -> bool {
687 self.raw & 0x8000 != 0
688 }
689}
690
691impl core::fmt::Debug for DutyCycle {
692 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
693 f.debug_struct("DutyCycle")
694 .field("value", &self.value())
695 .field("inverted", &self.is_inverted())
696 .finish()
697 }
698}
699
700#[cfg(feature = "defmt")]
701impl defmt::Format for DutyCycle {
702 fn format(&self, f: defmt::Formatter) {
703 defmt::write!(
704 f,
705 "DutyCycle {{ value: {=u16}, inverted: {=bool} }}",
706 self.value(),
707 self.is_inverted(),
708 );
709 }
710}
711
570impl<'d> SimplePwm<'d> { 712impl<'d> SimplePwm<'d> {
571 /// Create a new 1-channel PWM 713 /// Create a new 1-channel PWM
572 #[allow(unused_unsafe)] 714 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: &SimpleConfig) -> Self {
573 pub fn new_1ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>) -> Self { 715 Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
574 unsafe { Self::new_inner(pwm, Some(ch0.into()), None, None, None) }
575 } 716 }
576 717
577 /// Create a new 2-channel PWM 718 /// Create a new 2-channel PWM
578 #[allow(unused_unsafe)] 719 pub fn new_2ch<T: Instance>(
579 pub fn new_2ch<T: Instance>(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>) -> Self { 720 pwm: Peri<'d, T>,
580 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None) 721 ch0: Peri<'d, impl GpioPin>,
722 ch1: Peri<'d, impl GpioPin>,
723 config: &SimpleConfig,
724 ) -> Self {
725 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None, config)
581 } 726 }
582 727
583 /// Create a new 3-channel PWM 728 /// Create a new 3-channel PWM
584 #[allow(unused_unsafe)]
585 pub fn new_3ch<T: Instance>( 729 pub fn new_3ch<T: Instance>(
586 pwm: Peri<'d, T>, 730 pwm: Peri<'d, T>,
587 ch0: Peri<'d, impl GpioPin>, 731 ch0: Peri<'d, impl GpioPin>,
588 ch1: Peri<'d, impl GpioPin>, 732 ch1: Peri<'d, impl GpioPin>,
589 ch2: Peri<'d, impl GpioPin>, 733 ch2: Peri<'d, impl GpioPin>,
734 config: &SimpleConfig,
590 ) -> Self { 735 ) -> Self {
591 unsafe { Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None) } 736 Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None, config)
592 } 737 }
593 738
594 /// Create a new 4-channel PWM 739 /// Create a new 4-channel PWM
595 #[allow(unused_unsafe)]
596 pub fn new_4ch<T: Instance>( 740 pub fn new_4ch<T: Instance>(
597 pwm: Peri<'d, T>, 741 pwm: Peri<'d, T>,
598 ch0: Peri<'d, impl GpioPin>, 742 ch0: Peri<'d, impl GpioPin>,
599 ch1: Peri<'d, impl GpioPin>, 743 ch1: Peri<'d, impl GpioPin>,
600 ch2: Peri<'d, impl GpioPin>, 744 ch2: Peri<'d, impl GpioPin>,
601 ch3: Peri<'d, impl GpioPin>, 745 ch3: Peri<'d, impl GpioPin>,
746 config: &SimpleConfig,
602 ) -> Self { 747 ) -> Self {
603 unsafe { 748 Self::new_inner(
604 Self::new_inner( 749 pwm,
605 pwm, 750 Some(ch0.into()),
606 Some(ch0.into()), 751 Some(ch1.into()),
607 Some(ch1.into()), 752 Some(ch2.into()),
608 Some(ch2.into()), 753 Some(ch3.into()),
609 Some(ch3.into()), 754 config,
610 ) 755 )
611 }
612 } 756 }
613 757
614 fn new_inner<T: Instance>( 758 fn new_inner<T: Instance>(
@@ -617,29 +761,38 @@ impl<'d> SimplePwm<'d> {
617 ch1: Option<Peri<'d, AnyPin>>, 761 ch1: Option<Peri<'d, AnyPin>>,
618 ch2: Option<Peri<'d, AnyPin>>, 762 ch2: Option<Peri<'d, AnyPin>>,
619 ch3: Option<Peri<'d, AnyPin>>, 763 ch3: Option<Peri<'d, AnyPin>>,
764 config: &SimpleConfig,
620 ) -> Self { 765 ) -> Self {
621 let r = T::regs(); 766 let r = T::regs();
622 767
623 for (i, ch) in [&ch0, &ch1, &ch2, &ch3].into_iter().enumerate() { 768 let channels = [
624 if let Some(pin) = ch { 769 (&ch0, config.ch0_drive, config.ch0_idle_level),
625 pin.set_low(); 770 (&ch1, config.ch1_drive, config.ch1_idle_level),
626 771 (&ch2, config.ch2_drive, config.ch2_idle_level),
772 (&ch3, config.ch3_drive, config.ch3_idle_level),
773 ];
774 for (i, (pin, drive, idle_level)) in channels.into_iter().enumerate() {
775 if let Some(pin) = pin {
776 match idle_level {
777 Level::Low => pin.set_low(),
778 Level::High => pin.set_high(),
779 }
627 pin.conf().write(|w| { 780 pin.conf().write(|w| {
628 w.set_dir(gpiovals::Dir::OUTPUT); 781 w.set_dir(gpiovals::Dir::OUTPUT);
629 w.set_input(gpiovals::Input::DISCONNECT); 782 w.set_input(gpiovals::Input::DISCONNECT);
630 w.set_drive(gpiovals::Drive::S0S1); 783 convert_drive(w, drive);
631 }); 784 });
632 } 785 }
633 r.psel().out(i).write_value(ch.psel_bits()); 786 r.psel().out(i).write_value(pin.psel_bits());
634 } 787 }
635 788
636 let pwm = Self { 789 let pwm = Self {
637 r: T::regs(), 790 r,
638 ch0, 791 ch0,
639 ch1, 792 ch1,
640 ch2, 793 ch2,
641 ch3, 794 ch3,
642 duty: [0; 4], 795 duty: [const { DutyCycle::normal(0) }; 4],
643 }; 796 };
644 797
645 // Disable all interrupts 798 // Disable all interrupts
@@ -649,18 +802,22 @@ impl<'d> SimplePwm<'d> {
649 // Enable 802 // Enable
650 r.enable().write(|w| w.set_enable(true)); 803 r.enable().write(|w| w.set_enable(true));
651 804
652 r.seq(0).ptr().write_value((pwm.duty).as_ptr() as u32); 805 r.dma().seq(0).ptr().write_value((pwm.duty).as_ptr() as u32);
653 r.seq(0).cnt().write(|w| w.0 = 4); 806 r.dma().seq(0).maxcnt().write(|w| w.0 = 4 * CNT_UNIT);
654 r.seq(0).refresh().write(|w| w.0 = 0); 807 pwmseq(r, 0).refresh().write(|w| w.0 = 0);
655 r.seq(0).enddelay().write(|w| w.0 = 0); 808 pwmseq(r, 0).enddelay().write(|w| w.0 = 0);
656 809
657 r.decoder().write(|w| { 810 r.decoder().write(|w| {
658 w.set_load(vals::Load::INDIVIDUAL); 811 w.set_load(vals::Load::INDIVIDUAL);
659 w.set_mode(vals::Mode::REFRESH_COUNT); 812 w.set_mode(vals::Mode::REFRESH_COUNT);
660 }); 813 });
661 r.mode().write(|w| w.set_updown(vals::Updown::UP)); 814 r.mode().write(|w| match config.counter_mode {
662 r.prescaler().write(|w| w.set_prescaler(vals::Prescaler::DIV_16)); 815 CounterMode::UpAndDown => w.set_updown(vals::Updown::UP_AND_DOWN),
663 r.countertop().write(|w| w.set_countertop(1000)); 816 CounterMode::Up => w.set_updown(vals::Updown::UP),
817 });
818 r.prescaler()
819 .write(|w| w.set_prescaler(vals::Prescaler::from_bits(config.prescaler as u8)));
820 r.countertop().write(|w| w.set_countertop(config.max_duty));
664 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED)); 821 r.loop_().write(|w| w.set_cnt(vals::LoopCnt::DISABLED));
665 822
666 pwm 823 pwm
@@ -684,17 +841,33 @@ impl<'d> SimplePwm<'d> {
684 self.r.enable().write(|w| w.set_enable(false)); 841 self.r.enable().write(|w| w.set_enable(false));
685 } 842 }
686 843
687 /// Returns the current duty of the channel 844 /// Returns the current duty of the channel.
688 pub fn duty(&self, channel: usize) -> u16 { 845 pub fn duty(&self, channel: usize) -> DutyCycle {
689 self.duty[channel] 846 self.duty[channel]
690 } 847 }
691 848
692 /// Sets duty cycle (15 bit) for a PWM channel. 849 /// Sets duty cycle (15 bit) and polarity for a PWM channel.
693 pub fn set_duty(&mut self, channel: usize, duty: u16) { 850 pub fn set_duty(&mut self, channel: usize, duty: DutyCycle) {
694 self.duty[channel] = duty & 0x7FFF; 851 self.duty[channel] = duty;
852 self.sync_duty_cyles_to_peripheral();
853 }
854
855 /// Sets the duty cycle (15 bit) and polarity for all PWM channels.
856 ///
857 /// You can safely set the duty cycle of disabled PWM channels.
858 ///
859 /// When using this function, a single DMA transfer sets all the duty cycles.
860 /// If you call [`Self::set_duty()`] multiple times,
861 /// each duty cycle will be set by a separate DMA transfer.
862 pub fn set_all_duties(&mut self, duty: [DutyCycle; 4]) {
863 self.duty = duty;
864 self.sync_duty_cyles_to_peripheral();
865 }
695 866
867 /// Transfer the duty cycles from `self` to the peripheral.
868 fn sync_duty_cyles_to_peripheral(&self) {
696 // reload ptr in case self was moved 869 // reload ptr in case self was moved
697 self.r.seq(0).ptr().write_value((self.duty).as_ptr() as u32); 870 self.r.dma().seq(0).ptr().write_value((self.duty).as_ptr() as u32);
698 871
699 // defensive before seqstart 872 // defensive before seqstart
700 compiler_fence(Ordering::SeqCst); 873 compiler_fence(Ordering::SeqCst);
@@ -702,7 +875,7 @@ impl<'d> SimplePwm<'d> {
702 self.r.events_seqend(0).write_value(0); 875 self.r.events_seqend(0).write_value(0);
703 876
704 // tasks_seqstart() doesn't exist in all svds so write its bit instead 877 // tasks_seqstart() doesn't exist in all svds so write its bit instead
705 self.r.tasks_seqstart(0).write_value(1); 878 self.r.tasks_dma().seq(0).start().write_value(1);
706 879
707 // defensive wait until waveform is loaded after seqstart so set_duty 880 // defensive wait until waveform is loaded after seqstart so set_duty
708 // can't be called again while dma is still reading 881 // can't be called again while dma is still reading
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index a199c1c4d..ca8cbd73e 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -10,6 +10,7 @@ use core::task::Poll;
10use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, impl_peripheral}; 11use embassy_hal_internal::{Peri, impl_peripheral};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(not(feature = "_nrf54l"))]
13pub(crate) use vals::Psel as InputChannel; 14pub(crate) use vals::Psel as InputChannel;
14 15
15use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
@@ -84,6 +85,7 @@ pub struct ChannelConfig<'d> {
84 /// Gain used to control the effective input range of the SAADC. 85 /// Gain used to control the effective input range of the SAADC.
85 pub gain: Gain, 86 pub gain: Gain,
86 /// Positive channel resistor control. 87 /// Positive channel resistor control.
88 #[cfg(not(feature = "_nrf54l"))]
87 pub resistor: Resistor, 89 pub resistor: Resistor,
88 /// Acquisition time in microseconds. 90 /// Acquisition time in microseconds.
89 pub time: Time, 91 pub time: Time,
@@ -98,7 +100,11 @@ impl<'d> ChannelConfig<'d> {
98 pub fn single_ended(input: impl Input + 'd) -> Self { 100 pub fn single_ended(input: impl Input + 'd) -> Self {
99 Self { 101 Self {
100 reference: Reference::INTERNAL, 102 reference: Reference::INTERNAL,
103 #[cfg(not(feature = "_nrf54l"))]
101 gain: Gain::GAIN1_6, 104 gain: Gain::GAIN1_6,
105 #[cfg(feature = "_nrf54l")]
106 gain: Gain::GAIN2_8,
107 #[cfg(not(feature = "_nrf54l"))]
102 resistor: Resistor::BYPASS, 108 resistor: Resistor::BYPASS,
103 time: Time::_10US, 109 time: Time::_10US,
104 p_channel: input.degrade_saadc(), 110 p_channel: input.degrade_saadc(),
@@ -109,7 +115,11 @@ impl<'d> ChannelConfig<'d> {
109 pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self { 115 pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self {
110 Self { 116 Self {
111 reference: Reference::INTERNAL, 117 reference: Reference::INTERNAL,
118 #[cfg(not(feature = "_nrf54l"))]
112 gain: Gain::GAIN1_6, 119 gain: Gain::GAIN1_6,
120 #[cfg(feature = "_nrf54l")]
121 gain: Gain::GAIN2_8,
122 #[cfg(not(feature = "_nrf54l"))]
113 resistor: Resistor::BYPASS, 123 resistor: Resistor::BYPASS,
114 time: Time::_10US, 124 time: Time::_10US,
115 p_channel: p_input.degrade_saadc(), 125 p_channel: p_input.degrade_saadc(),
@@ -118,6 +128,8 @@ impl<'d> ChannelConfig<'d> {
118 } 128 }
119} 129}
120 130
131const CNT_UNIT: usize = if cfg!(feature = "_nrf54l") { 2 } else { 1 };
132
121/// Value returned by the SAADC callback, deciding what happens next. 133/// Value returned by the SAADC callback, deciding what happens next.
122#[derive(PartialEq)] 134#[derive(PartialEq)]
123pub enum CallbackResult { 135pub enum CallbackResult {
@@ -150,19 +162,38 @@ impl<'d, const N: usize> Saadc<'d, N> {
150 r.oversample().write(|w| w.set_oversample(oversample.into())); 162 r.oversample().write(|w| w.set_oversample(oversample.into()));
151 163
152 for (i, cc) in channel_configs.iter().enumerate() { 164 for (i, cc) in channel_configs.iter().enumerate() {
165 #[cfg(not(feature = "_nrf54l"))]
153 r.ch(i).pselp().write(|w| w.set_pselp(cc.p_channel.channel())); 166 r.ch(i).pselp().write(|w| w.set_pselp(cc.p_channel.channel()));
167 #[cfg(feature = "_nrf54l")]
168 r.ch(i).pselp().write(|w| {
169 w.set_port(cc.p_channel.port());
170 w.set_pin(cc.p_channel.pin());
171 w.set_internal(cc.p_channel.internal());
172 w.set_connect(cc.p_channel.connect());
173 });
154 if let Some(n_channel) = &cc.n_channel { 174 if let Some(n_channel) = &cc.n_channel {
175 #[cfg(not(feature = "_nrf54l"))]
155 r.ch(i).pseln().write(|w| w.set_pseln(n_channel.channel())); 176 r.ch(i).pseln().write(|w| w.set_pseln(n_channel.channel()));
177 #[cfg(feature = "_nrf54l")]
178 r.ch(i).pseln().write(|w| {
179 w.set_port(n_channel.port());
180 w.set_pin(n_channel.pin());
181 w.set_connect(n_channel.connect().to_bits().into());
182 });
156 } 183 }
157 r.ch(i).config().write(|w| { 184 r.ch(i).config().write(|w| {
158 w.set_refsel(cc.reference.into()); 185 w.set_refsel(cc.reference.into());
159 w.set_gain(cc.gain.into()); 186 w.set_gain(cc.gain.into());
160 w.set_tacq(cc.time.into()); 187 w.set_tacq(cc.time.into());
188 #[cfg(feature = "_nrf54l")]
189 w.set_tconv(7); // 7 is the default from the Nordic C driver
161 w.set_mode(match cc.n_channel { 190 w.set_mode(match cc.n_channel {
162 None => vals::ConfigMode::SE, 191 None => vals::ConfigMode::SE,
163 Some(_) => vals::ConfigMode::DIFF, 192 Some(_) => vals::ConfigMode::DIFF,
164 }); 193 });
194 #[cfg(not(feature = "_nrf54l"))]
165 w.set_resp(cc.resistor.into()); 195 w.set_resp(cc.resistor.into());
196 #[cfg(not(feature = "_nrf54l"))]
166 w.set_resn(vals::Resn::BYPASS); 197 w.set_resn(vals::Resn::BYPASS);
167 w.set_burst(!matches!(oversample, Oversample::BYPASS)); 198 w.set_burst(!matches!(oversample, Oversample::BYPASS));
168 }); 199 });
@@ -222,7 +253,7 @@ impl<'d, const N: usize> Saadc<'d, N> {
222 253
223 // Set up the DMA 254 // Set up the DMA
224 r.result().ptr().write_value(buf.as_mut_ptr() as u32); 255 r.result().ptr().write_value(buf.as_mut_ptr() as u32);
225 r.result().maxcnt().write(|w| w.set_maxcnt(N as _)); 256 r.result().maxcnt().write(|w| w.set_maxcnt((N * CNT_UNIT) as _));
226 257
227 // Reset and enable the end event 258 // Reset and enable the end event
228 r.events_end().write_value(0); 259 r.events_end().write_value(0);
@@ -354,7 +385,7 @@ impl<'d, const N: usize> Saadc<'d, N> {
354 385
355 // Set up the initial DMA 386 // Set up the initial DMA
356 r.result().ptr().write_value(bufs[0].as_mut_ptr() as u32); 387 r.result().ptr().write_value(bufs[0].as_mut_ptr() as u32);
357 r.result().maxcnt().write(|w| w.set_maxcnt((N0 * N) as _)); 388 r.result().maxcnt().write(|w| w.set_maxcnt((N0 * N * CNT_UNIT) as _));
358 389
359 // Reset and enable the events 390 // Reset and enable the events
360 r.events_end().write_value(0); 391 r.events_end().write_value(0);
@@ -473,12 +504,21 @@ impl<'d, const N: usize> Drop for Saadc<'d, N> {
473 let r = Self::regs(); 504 let r = Self::regs();
474 r.enable().write(|w| w.set_enable(false)); 505 r.enable().write(|w| w.set_enable(false));
475 for i in 0..N { 506 for i in 0..N {
476 r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC)); 507 #[cfg(not(feature = "_nrf54l"))]
477 r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC)); 508 {
509 r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC));
510 r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC));
511 }
512 #[cfg(feature = "_nrf54l")]
513 {
514 r.ch(i).pselp().write(|w| w.set_connect(vals::PselpConnect::NC));
515 r.ch(i).pseln().write(|w| w.set_connect(vals::PselnConnect::NC));
516 }
478 } 517 }
479 } 518 }
480} 519}
481 520
521#[cfg(not(feature = "_nrf54l"))]
482impl From<Gain> for vals::Gain { 522impl From<Gain> for vals::Gain {
483 fn from(gain: Gain) -> Self { 523 fn from(gain: Gain) -> Self {
484 match gain { 524 match gain {
@@ -494,7 +534,24 @@ impl From<Gain> for vals::Gain {
494 } 534 }
495} 535}
496 536
537#[cfg(feature = "_nrf54l")]
538impl From<Gain> for vals::Gain {
539 fn from(gain: Gain) -> Self {
540 match gain {
541 Gain::GAIN2_8 => vals::Gain::GAIN2_8,
542 Gain::GAIN2_7 => vals::Gain::GAIN2_7,
543 Gain::GAIN2_6 => vals::Gain::GAIN2_6,
544 Gain::GAIN2_5 => vals::Gain::GAIN2_5,
545 Gain::GAIN2_4 => vals::Gain::GAIN2_4,
546 Gain::GAIN2_3 => vals::Gain::GAIN2_3,
547 Gain::GAIN1 => vals::Gain::GAIN1,
548 Gain::GAIN2 => vals::Gain::GAIN2,
549 }
550 }
551}
552
497/// Gain control 553/// Gain control
554#[cfg(not(feature = "_nrf54l"))]
498#[non_exhaustive] 555#[non_exhaustive]
499#[derive(Clone, Copy)] 556#[derive(Clone, Copy)]
500pub enum Gain { 557pub enum Gain {
@@ -516,11 +573,37 @@ pub enum Gain {
516 GAIN4 = 7, 573 GAIN4 = 7,
517} 574}
518 575
576/// Gain control
577#[cfg(feature = "_nrf54l")]
578#[non_exhaustive]
579#[derive(Clone, Copy)]
580pub enum Gain {
581 /// 2/8
582 GAIN2_8 = 0,
583 /// 2/7
584 GAIN2_7 = 1,
585 /// 2/6
586 GAIN2_6 = 2,
587 /// 2/5
588 GAIN2_5 = 3,
589 /// 2/4
590 GAIN2_4 = 4,
591 /// 2/3
592 GAIN2_3 = 5,
593 /// 1
594 GAIN1 = 6,
595 /// 2
596 GAIN2 = 7,
597}
598
519impl From<Reference> for vals::Refsel { 599impl From<Reference> for vals::Refsel {
520 fn from(reference: Reference) -> Self { 600 fn from(reference: Reference) -> Self {
521 match reference { 601 match reference {
522 Reference::INTERNAL => vals::Refsel::INTERNAL, 602 Reference::INTERNAL => vals::Refsel::INTERNAL,
603 #[cfg(not(feature = "_nrf54l"))]
523 Reference::VDD1_4 => vals::Refsel::VDD1_4, 604 Reference::VDD1_4 => vals::Refsel::VDD1_4,
605 #[cfg(feature = "_nrf54l")]
606 Reference::EXTERNAL => vals::Refsel::EXTERNAL,
524 } 607 }
525 } 608 }
526} 609}
@@ -531,10 +614,15 @@ impl From<Reference> for vals::Refsel {
531pub enum Reference { 614pub enum Reference {
532 /// Internal reference (0.6 V) 615 /// Internal reference (0.6 V)
533 INTERNAL = 0, 616 INTERNAL = 0,
617 #[cfg(not(feature = "_nrf54l"))]
534 /// VDD/4 as reference 618 /// VDD/4 as reference
535 VDD1_4 = 1, 619 VDD1_4 = 1,
620 /// PADC_EXT_REF_1V2 as reference
621 #[cfg(feature = "_nrf54l")]
622 EXTERNAL = 1,
536} 623}
537 624
625#[cfg(not(feature = "_nrf54l"))]
538impl From<Resistor> for vals::Resp { 626impl From<Resistor> for vals::Resp {
539 fn from(resistor: Resistor) -> Self { 627 fn from(resistor: Resistor) -> Self {
540 match resistor { 628 match resistor {
@@ -549,6 +637,7 @@ impl From<Resistor> for vals::Resp {
549/// Positive channel resistor control 637/// Positive channel resistor control
550#[non_exhaustive] 638#[non_exhaustive]
551#[derive(Clone, Copy)] 639#[derive(Clone, Copy)]
640#[cfg(not(feature = "_nrf54l"))]
552pub enum Resistor { 641pub enum Resistor {
553 /// Bypass resistor ladder 642 /// Bypass resistor ladder
554 BYPASS = 0, 643 BYPASS = 0,
@@ -560,6 +649,7 @@ pub enum Resistor {
560 VDD1_2 = 3, 649 VDD1_2 = 3,
561} 650}
562 651
652#[cfg(not(feature = "_nrf54l"))]
563impl From<Time> for vals::Tacq { 653impl From<Time> for vals::Tacq {
564 fn from(time: Time) -> Self { 654 fn from(time: Time) -> Self {
565 match time { 655 match time {
@@ -573,6 +663,20 @@ impl From<Time> for vals::Tacq {
573 } 663 }
574} 664}
575 665
666#[cfg(feature = "_nrf54l")]
667impl From<Time> for u16 {
668 fn from(time: Time) -> Self {
669 match time {
670 Time::_3US => (3000 / 125) - 1,
671 Time::_5US => (5000 / 125) - 1,
672 Time::_10US => (10000 / 125) - 1,
673 Time::_15US => (15000 / 125) - 1,
674 Time::_20US => (20000 / 125) - 1,
675 Time::_40US => (40000 / 125) - 1,
676 }
677 }
678}
679
576/// Acquisition time, the time the SAADC uses to sample the input voltage 680/// Acquisition time, the time the SAADC uses to sample the input voltage
577#[non_exhaustive] 681#[non_exhaustive]
578#[derive(Clone, Copy)] 682#[derive(Clone, Copy)]
@@ -657,7 +761,20 @@ pub enum Resolution {
657} 761}
658 762
659pub(crate) trait SealedInput { 763pub(crate) trait SealedInput {
764 #[cfg(not(feature = "_nrf54l"))]
660 fn channel(&self) -> InputChannel; 765 fn channel(&self) -> InputChannel;
766
767 #[cfg(feature = "_nrf54l")]
768 fn pin(&self) -> u8;
769
770 #[cfg(feature = "_nrf54l")]
771 fn port(&self) -> u8;
772
773 #[cfg(feature = "_nrf54l")]
774 fn internal(&self) -> vals::Internal;
775
776 #[cfg(feature = "_nrf54l")]
777 fn connect(&self) -> vals::PselpConnect;
661} 778}
662 779
663/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal. 780/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal.
@@ -667,6 +784,7 @@ pub trait Input: SealedInput + Sized {
667 /// 784 ///
668 /// This allows using several inputs in situations that might require 785 /// This allows using several inputs in situations that might require
669 /// them to be the same type, like putting them in an array. 786 /// them to be the same type, like putting them in an array.
787 #[cfg(not(feature = "_nrf54l"))]
670 fn degrade_saadc<'a>(self) -> AnyInput<'a> 788 fn degrade_saadc<'a>(self) -> AnyInput<'a>
671 where 789 where
672 Self: 'a, 790 Self: 'a,
@@ -676,17 +794,49 @@ pub trait Input: SealedInput + Sized {
676 _phantom: core::marker::PhantomData, 794 _phantom: core::marker::PhantomData,
677 } 795 }
678 } 796 }
797
798 /// Convert this SAADC input to a type-erased `AnyInput`.
799 ///
800 /// This allows using several inputs in situations that might require
801 /// them to be the same type, like putting them in an array.
802 #[cfg(feature = "_nrf54l")]
803 fn degrade_saadc<'a>(self) -> AnyInput<'a>
804 where
805 Self: 'a,
806 {
807 AnyInput {
808 pin: self.pin(),
809 port: self.port(),
810 internal: self.internal(),
811 connect: self.connect(),
812 _phantom: core::marker::PhantomData,
813 }
814 }
679} 815}
680 816
681/// A type-erased SAADC input. 817/// A type-erased SAADC input.
682/// 818///
683/// This allows using several inputs in situations that might require 819/// This allows using several inputs in situations that might require
684/// them to be the same type, like putting them in an array. 820/// them to be the same type, like putting them in an array.
821#[cfg(not(feature = "_nrf54l"))]
685pub struct AnyInput<'a> { 822pub struct AnyInput<'a> {
686 channel: InputChannel, 823 channel: InputChannel,
687 _phantom: PhantomData<&'a ()>, 824 _phantom: PhantomData<&'a ()>,
688} 825}
689 826
827/// A type-erased SAADC input.
828///
829/// This allows using several inputs in situations that might require
830/// them to be the same type, like putting them in an array.
831#[cfg(feature = "_nrf54l")]
832pub struct AnyInput<'a> {
833 pin: u8,
834 port: u8,
835 internal: vals::Internal,
836 connect: vals::PselpConnect,
837 _phantom: PhantomData<&'a ()>,
838}
839
690impl<'a> AnyInput<'a> { 840impl<'a> AnyInput<'a> {
691 /// Reborrow into a "child" AnyInput. 841 /// Reborrow into a "child" AnyInput.
692 /// 842 ///
@@ -694,21 +844,56 @@ impl<'a> AnyInput<'a> {
694 pub fn reborrow(&mut self) -> AnyInput<'_> { 844 pub fn reborrow(&mut self) -> AnyInput<'_> {
695 // safety: we're returning the clone inside a new Peripheral that borrows 845 // safety: we're returning the clone inside a new Peripheral that borrows
696 // self, so user code can't use both at the same time. 846 // self, so user code can't use both at the same time.
697 Self { 847 #[cfg(not(feature = "_nrf54l"))]
698 channel: self.channel, 848 {
699 _phantom: PhantomData, 849 Self {
850 channel: self.channel,
851 _phantom: PhantomData,
852 }
853 }
854 #[cfg(feature = "_nrf54l")]
855 {
856 Self {
857 pin: self.pin,
858 port: self.port,
859 internal: self.internal,
860 connect: self.connect,
861 _phantom: PhantomData,
862 }
700 } 863 }
701 } 864 }
702} 865}
703 866
704impl SealedInput for AnyInput<'_> { 867impl SealedInput for AnyInput<'_> {
868 #[cfg(not(feature = "_nrf54l"))]
705 fn channel(&self) -> InputChannel { 869 fn channel(&self) -> InputChannel {
706 self.channel 870 self.channel
707 } 871 }
872
873 #[cfg(feature = "_nrf54l")]
874 fn pin(&self) -> u8 {
875 self.pin
876 }
877
878 #[cfg(feature = "_nrf54l")]
879 fn port(&self) -> u8 {
880 self.port
881 }
882
883 #[cfg(feature = "_nrf54l")]
884 fn internal(&self) -> vals::Internal {
885 self.internal
886 }
887
888 #[cfg(feature = "_nrf54l")]
889 fn connect(&self) -> vals::PselpConnect {
890 self.connect
891 }
708} 892}
709 893
710impl Input for AnyInput<'_> {} 894impl Input for AnyInput<'_> {}
711 895
896#[cfg(not(feature = "_nrf54l"))]
712macro_rules! impl_saadc_input { 897macro_rules! impl_saadc_input {
713 ($pin:ident, $ch:ident) => { 898 ($pin:ident, $ch:ident) => {
714 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch); 899 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch);
@@ -723,15 +908,45 @@ macro_rules! impl_saadc_input {
723 }; 908 };
724} 909}
725 910
911#[cfg(feature = "_nrf54l")]
912macro_rules! impl_saadc_input {
913 ($pin:ident, $port:expr, $ain:expr) => {
914 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $port, $ain, AVDD, ANALOG_INPUT);
915 };
916 (@local, $pin:ty, $port:expr, $ain:expr, $internal:ident, $connect:ident) => {
917 impl crate::saadc::SealedInput for $pin {
918 fn pin(&self) -> u8 {
919 $ain
920 }
921
922 fn port(&self) -> u8 {
923 $port
924 }
925
926 fn internal(&self) -> crate::pac::saadc::vals::Internal {
927 crate::pac::saadc::vals::Internal::$internal
928 }
929
930 fn connect(&self) -> crate::pac::saadc::vals::PselpConnect {
931 crate::pac::saadc::vals::PselpConnect::$connect
932 }
933 }
934 impl crate::saadc::Input for $pin {}
935 };
936}
937
726/// A dummy `Input` pin implementation for SAADC peripheral sampling from the 938/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
727/// internal voltage. 939/// internal voltage.
728pub struct VddInput; 940pub struct VddInput;
729 941
730impl_peripheral!(VddInput); 942impl_peripheral!(VddInput);
943#[cfg(not(feature = "_nrf54l"))]
731#[cfg(not(feature = "_nrf91"))] 944#[cfg(not(feature = "_nrf91"))]
732impl_saadc_input!(@local, VddInput, VDD); 945impl_saadc_input!(@local, VddInput, VDD);
733#[cfg(feature = "_nrf91")] 946#[cfg(feature = "_nrf91")]
734impl_saadc_input!(@local, VddInput, VDD_GPIO); 947impl_saadc_input!(@local, VddInput, VDD_GPIO);
948#[cfg(feature = "_nrf54l")]
949impl_saadc_input!(@local, VddInput, 0, 0, VDD, INTERNAL);
735 950
736/// A dummy `Input` pin implementation for SAADC peripheral sampling from the 951/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
737/// VDDH / 5 voltage. 952/// VDDH / 5 voltage.
@@ -743,3 +958,21 @@ impl_peripheral!(VddhDiv5Input);
743 958
744#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))] 959#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))]
745impl_saadc_input!(@local, VddhDiv5Input, VDDHDIV5); 960impl_saadc_input!(@local, VddhDiv5Input, VDDHDIV5);
961
962/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
963/// AVDD internal voltage of the nrf54l chip family.
964#[cfg(feature = "_nrf54l")]
965pub struct AVddInput;
966#[cfg(feature = "_nrf54l")]
967embassy_hal_internal::impl_peripheral!(AVddInput);
968#[cfg(feature = "_nrf54l")]
969impl_saadc_input!(@local, AVddInput, 0, 0, AVDD, INTERNAL);
970
971/// A dummy `Input` pin implementation for SAADC peripheral sampling from the
972/// DVDD internal voltage of the nrf54l chip family.
973#[cfg(feature = "_nrf54l")]
974pub struct DVddInput;
975#[cfg(feature = "_nrf54l")]
976embassy_hal_internal::impl_peripheral!(DVddInput);
977#[cfg(feature = "_nrf54l")]
978impl_saadc_input!(@local, DVddInput, 0, 0, DVDD, INTERNAL);
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index ce994dbc9..34485609b 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -13,7 +13,7 @@ use embassy_embedded_hal::SetConfig;
13use embassy_hal_internal::{Peri, PeripheralType}; 13use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::AtomicWaker; 14use embassy_sync::waitqueue::AtomicWaker;
15pub use embedded_hal_02::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode, Phase, Polarity}; 15pub use embedded_hal_02::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode, Phase, Polarity};
16pub use pac::spim::vals::{Frequency, Order as BitOrder}; 16pub use pac::spim::vals::Order as BitOrder;
17 17
18use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 18use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
19use crate::gpio::{self, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive}; 19use crate::gpio::{self, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
@@ -23,6 +23,110 @@ use crate::pac::spim::vals;
23use crate::util::slice_in_ram_or; 23use crate::util::slice_in_ram_or;
24use crate::{interrupt, pac}; 24use crate::{interrupt, pac};
25 25
26/// SPI frequencies.
27#[repr(transparent)]
28#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
29pub struct Frequency(u32);
30impl Frequency {
31 #[doc = "125 kbps"]
32 pub const K125: Self = Self(0x0200_0000);
33 #[doc = "250 kbps"]
34 pub const K250: Self = Self(0x0400_0000);
35 #[doc = "500 kbps"]
36 pub const K500: Self = Self(0x0800_0000);
37 #[doc = "1 Mbps"]
38 pub const M1: Self = Self(0x1000_0000);
39 #[doc = "2 Mbps"]
40 pub const M2: Self = Self(0x2000_0000);
41 #[doc = "4 Mbps"]
42 pub const M4: Self = Self(0x4000_0000);
43 #[doc = "8 Mbps"]
44 pub const M8: Self = Self(0x8000_0000);
45 #[cfg(not(feature = "_spi-v1"))]
46 #[doc = "16 Mbps"]
47 pub const M16: Self = Self(0x0a00_0000);
48 #[cfg(not(feature = "_spi-v1"))]
49 #[doc = "32 Mbps"]
50 pub const M32: Self = Self(0x1400_0000);
51}
52
53impl Frequency {
54 #[cfg(feature = "_nrf54l")]
55 fn to_divisor(&self, clk: u32) -> u8 {
56 let frequency = match *self {
57 #[cfg(not(feature = "_spi-v1"))]
58 Self::M32 => 32_000_000,
59 #[cfg(not(feature = "_spi-v1"))]
60 Self::M16 => 16_000_000,
61 Self::M8 => 8_000_000,
62 Self::M4 => 4_000_000,
63 Self::M2 => 2_000_000,
64 Self::M1 => 1_000_000,
65 Self::K500 => 500_000,
66 Self::K250 => 250_000,
67 Self::K125 => 125_000,
68 _ => unreachable!(),
69 };
70 let divisor = (clk / frequency) as u8;
71 divisor
72 }
73}
74impl core::fmt::Debug for Frequency {
75 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76 match self.0 {
77 0x0200_0000 => f.write_str("K125"),
78 0x0400_0000 => f.write_str("K250"),
79 0x0800_0000 => f.write_str("K500"),
80 0x0a00_0000 => f.write_str("M16"),
81 0x1000_0000 => f.write_str("M1"),
82 0x1400_0000 => f.write_str("M32"),
83 0x2000_0000 => f.write_str("M2"),
84 0x4000_0000 => f.write_str("M4"),
85 0x8000_0000 => f.write_str("M8"),
86 other => core::write!(f, "0x{:02X}", other),
87 }
88 }
89}
90
91#[cfg(feature = "defmt")]
92impl defmt::Format for Frequency {
93 fn format(&self, f: defmt::Formatter) {
94 match self.0 {
95 0x0200_0000 => defmt::write!(f, "K125"),
96 0x0400_0000 => defmt::write!(f, "K250"),
97 0x0800_0000 => defmt::write!(f, "K500"),
98 0x0a00_0000 => defmt::write!(f, "M16"),
99 0x1000_0000 => defmt::write!(f, "M1"),
100 0x1400_0000 => defmt::write!(f, "M32"),
101 0x2000_0000 => defmt::write!(f, "M2"),
102 0x4000_0000 => defmt::write!(f, "M4"),
103 0x8000_0000 => defmt::write!(f, "M8"),
104 other => defmt::write!(f, "0x{:02X}", other),
105 }
106 }
107}
108
109#[cfg(not(feature = "_nrf54l"))]
110impl Into<pac::spim::vals::Frequency> for Frequency {
111 fn into(self) -> pac::spim::vals::Frequency {
112 use pac::spim::vals::Frequency as Freq;
113 match self {
114 #[cfg(not(feature = "_spi-v1"))]
115 Self::M32 => Freq::M32,
116 #[cfg(not(feature = "_spi-v1"))]
117 Self::M16 => Freq::M16,
118 Self::M8 => Freq::M8,
119 Self::M4 => Freq::M4,
120 Self::M2 => Freq::M2,
121 Self::M1 => Freq::M1,
122 Self::K500 => Freq::K500,
123 Self::K250 => Freq::K250,
124 Self::K125 => Freq::K125,
125 _ => unreachable!(),
126 }
127 }
128}
129
26/// SPIM error 130/// SPIM error
27#[derive(Debug, Clone, Copy, PartialEq, Eq)] 131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))] 132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -103,6 +207,8 @@ pub struct Spim<'d> {
103 r: pac::spim::Spim, 207 r: pac::spim::Spim,
104 irq: interrupt::Interrupt, 208 irq: interrupt::Interrupt,
105 state: &'static State, 209 state: &'static State,
210 #[cfg(feature = "_nrf54l")]
211 clk: u32,
106 _p: PhantomData<&'d ()>, 212 _p: PhantomData<&'d ()>,
107} 213}
108 214
@@ -208,6 +314,8 @@ impl<'d> Spim<'d> {
208 r: T::regs(), 314 r: T::regs(),
209 irq: T::Interrupt::IRQ, 315 irq: T::Interrupt::IRQ,
210 state: T::state(), 316 state: T::state(),
317 #[cfg(feature = "_nrf54l")]
318 clk: T::clk(),
211 _p: PhantomData {}, 319 _p: PhantomData {},
212 }; 320 };
213 321
@@ -238,13 +346,13 @@ impl<'d> Spim<'d> {
238 346
239 // Set up the DMA read. 347 // Set up the DMA read.
240 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length); 348 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length);
241 r.rxd().ptr().write_value(rx_ptr); 349 r.dma().rx().ptr().write_value(rx_ptr);
242 r.rxd().maxcnt().write(|w| w.set_maxcnt(rx_len as _)); 350 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(rx_len as _));
243 351
244 // Set up the DMA write. 352 // Set up the DMA write.
245 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length); 353 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length);
246 r.txd().ptr().write_value(tx_ptr); 354 r.dma().tx().ptr().write_value(tx_ptr);
247 r.txd().maxcnt().write(|w| w.set_maxcnt(tx_len as _)); 355 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(tx_len as _));
248 356
249 /* 357 /*
250 trace!("XFER: offset: {}, length: {}", offset, length); 358 trace!("XFER: offset: {}, length: {}", offset, length);
@@ -259,8 +367,8 @@ impl<'d> Spim<'d> {
259 r.events_started().write_value(0); 367 r.events_started().write_value(0);
260 368
261 // Set rx/tx buffer lengths to 0... 369 // Set rx/tx buffer lengths to 0...
262 r.txd().maxcnt().write(|_| ()); 370 r.dma().tx().maxcnt().write(|_| ());
263 r.rxd().maxcnt().write(|_| ()); 371 r.dma().rx().maxcnt().write(|_| ());
264 372
265 // ...and keep track of original buffer lengths... 373 // ...and keep track of original buffer lengths...
266 s.tx.store(tx_len as _, Ordering::Relaxed); 374 s.tx.store(tx_len as _, Ordering::Relaxed);
@@ -447,8 +555,14 @@ impl<'d> Spim<'d> {
447 r.events_end().write_value(0); 555 r.events_end().write_value(0);
448 556
449 // Update DMA registers with correct rx/tx buffer sizes 557 // Update DMA registers with correct rx/tx buffer sizes
450 r.rxd().maxcnt().write(|w| w.set_maxcnt(s.rx.load(Ordering::Relaxed))); 558 r.dma()
451 r.txd().maxcnt().write(|w| w.set_maxcnt(s.tx.load(Ordering::Relaxed))); 559 .rx()
560 .maxcnt()
561 .write(|w| w.set_maxcnt(s.rx.load(Ordering::Relaxed)));
562 r.dma()
563 .tx()
564 .maxcnt()
565 .write(|w| w.set_maxcnt(s.tx.load(Ordering::Relaxed)));
452 566
453 r.intenset().write(|w| w.set_end(true)); 567 r.intenset().write(|w| w.set_end(true));
454 // ... and start actual, hopefully glitch-free transmission 568 // ... and start actual, hopefully glitch-free transmission
@@ -503,6 +617,8 @@ impl State {
503pub(crate) trait SealedInstance { 617pub(crate) trait SealedInstance {
504 fn regs() -> pac::spim::Spim; 618 fn regs() -> pac::spim::Spim;
505 fn state() -> &'static State; 619 fn state() -> &'static State;
620 #[cfg(feature = "_nrf54l")]
621 fn clk() -> u32;
506} 622}
507 623
508/// SPIM peripheral instance 624/// SPIM peripheral instance
@@ -512,6 +628,28 @@ pub trait Instance: SealedInstance + PeripheralType + 'static {
512 type Interrupt: interrupt::typelevel::Interrupt; 628 type Interrupt: interrupt::typelevel::Interrupt;
513} 629}
514 630
631#[cfg(feature = "_nrf54l")]
632macro_rules! impl_spim {
633 ($type:ident, $pac_type:ident, $irq:ident, $clk:expr) => {
634 impl crate::spim::SealedInstance for peripherals::$type {
635 fn regs() -> pac::spim::Spim {
636 pac::$pac_type
637 }
638 fn state() -> &'static crate::spim::State {
639 static STATE: crate::spim::State = crate::spim::State::new();
640 &STATE
641 }
642 fn clk() -> u32 {
643 $clk
644 }
645 }
646 impl crate::spim::Instance for peripherals::$type {
647 type Interrupt = crate::interrupt::typelevel::$irq;
648 }
649 };
650}
651
652#[cfg(not(feature = "_nrf54l"))]
515macro_rules! impl_spim { 653macro_rules! impl_spim {
516 ($type:ident, $pac_type:ident, $irq:ident) => { 654 ($type:ident, $pac_type:ident, $irq:ident) => {
517 impl crate::spim::SealedInstance for peripherals::$type { 655 impl crate::spim::SealedInstance for peripherals::$type {
@@ -638,7 +776,12 @@ impl<'d> SetConfig for Spim<'d> {
638 776
639 // Configure frequency. 777 // Configure frequency.
640 let frequency = config.frequency; 778 let frequency = config.frequency;
641 r.frequency().write(|w| w.set_frequency(frequency)); 779 #[cfg(not(feature = "_nrf54l"))]
780 r.frequency().write(|w| w.set_frequency(frequency.into()));
781 #[cfg(feature = "_nrf54l")]
782 {
783 r.prescaler().write(|w| w.set_divisor(frequency.to_divisor(self.clk)));
784 }
642 785
643 // Set over-read character 786 // Set over-read character
644 let orc = config.orc; 787 let orc = config.orc;
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index 885821146..96a9c0ae0 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -224,15 +224,15 @@ impl<'d> Spis<'d> {
224 if tx.len() > EASY_DMA_SIZE { 224 if tx.len() > EASY_DMA_SIZE {
225 return Err(Error::TxBufferTooLong); 225 return Err(Error::TxBufferTooLong);
226 } 226 }
227 r.txd().ptr().write_value(tx as *const u8 as _); 227 r.dma().tx().ptr().write_value(tx as *const u8 as _);
228 r.txd().maxcnt().write(|w| w.set_maxcnt(tx.len() as _)); 228 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(tx.len() as _));
229 229
230 // Set up the DMA read. 230 // Set up the DMA read.
231 if rx.len() > EASY_DMA_SIZE { 231 if rx.len() > EASY_DMA_SIZE {
232 return Err(Error::RxBufferTooLong); 232 return Err(Error::RxBufferTooLong);
233 } 233 }
234 r.rxd().ptr().write_value(rx as *mut u8 as _); 234 r.dma().rx().ptr().write_value(rx as *mut u8 as _);
235 r.rxd().maxcnt().write(|w| w.set_maxcnt(rx.len() as _)); 235 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(rx.len() as _));
236 236
237 // Reset end event. 237 // Reset end event.
238 r.events_end().write_value(0); 238 r.events_end().write_value(0);
@@ -260,8 +260,8 @@ impl<'d> Spis<'d> {
260 // Wait for 'end' event. 260 // Wait for 'end' event.
261 while r.events_end().read() == 0 {} 261 while r.events_end().read() == 0 {}
262 262
263 let n_rx = r.rxd().amount().read().0 as usize; 263 let n_rx = r.dma().rx().amount().read().0 as usize;
264 let n_tx = r.txd().amount().read().0 as usize; 264 let n_tx = r.dma().tx().amount().read().0 as usize;
265 265
266 compiler_fence(Ordering::SeqCst); 266 compiler_fence(Ordering::SeqCst);
267 267
@@ -326,8 +326,8 @@ impl<'d> Spis<'d> {
326 }) 326 })
327 .await; 327 .await;
328 328
329 let n_rx = r.rxd().amount().read().0 as usize; 329 let n_rx = r.dma().rx().amount().read().0 as usize;
330 let n_tx = r.txd().amount().read().0 as usize; 330 let n_tx = r.dma().tx().amount().read().0 as usize;
331 331
332 compiler_fence(Ordering::SeqCst); 332 compiler_fence(Ordering::SeqCst);
333 333
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 93255c832..abf9a923f 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -141,10 +141,19 @@ impl<'d> Twim<'d> {
141 sda.conf().write(|w| { 141 sda.conf().write(|w| {
142 w.set_dir(gpiovals::Dir::OUTPUT); 142 w.set_dir(gpiovals::Dir::OUTPUT);
143 w.set_input(gpiovals::Input::CONNECT); 143 w.set_input(gpiovals::Input::CONNECT);
144 #[cfg(not(feature = "_nrf54l"))]
144 w.set_drive(match config.sda_high_drive { 145 w.set_drive(match config.sda_high_drive {
145 true => gpiovals::Drive::H0D1, 146 true => gpiovals::Drive::H0D1,
146 false => gpiovals::Drive::S0D1, 147 false => gpiovals::Drive::S0D1,
147 }); 148 });
149 #[cfg(feature = "_nrf54l")]
150 {
151 w.set_drive0(match config.sda_high_drive {
152 true => gpiovals::Drive::H,
153 false => gpiovals::Drive::S,
154 });
155 w.set_drive1(gpiovals::Drive::D);
156 }
148 if config.sda_pullup { 157 if config.sda_pullup {
149 w.set_pull(gpiovals::Pull::PULLUP); 158 w.set_pull(gpiovals::Pull::PULLUP);
150 } 159 }
@@ -152,10 +161,19 @@ impl<'d> Twim<'d> {
152 scl.conf().write(|w| { 161 scl.conf().write(|w| {
153 w.set_dir(gpiovals::Dir::OUTPUT); 162 w.set_dir(gpiovals::Dir::OUTPUT);
154 w.set_input(gpiovals::Input::CONNECT); 163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
155 w.set_drive(match config.scl_high_drive { 165 w.set_drive(match config.scl_high_drive {
156 true => gpiovals::Drive::H0D1, 166 true => gpiovals::Drive::H0D1,
157 false => gpiovals::Drive::S0D1, 167 false => gpiovals::Drive::S0D1,
158 }); 168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.scl_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
159 if config.sda_pullup { 177 if config.sda_pullup {
160 w.set_pull(gpiovals::Pull::PULLUP); 178 w.set_pull(gpiovals::Pull::PULLUP);
161 } 179 }
@@ -210,8 +228,8 @@ impl<'d> Twim<'d> {
210 // We're giving the register a pointer to the stack. Since we're 228 // We're giving the register a pointer to the stack. Since we're
211 // waiting for the I2C transaction to end before this stack pointer 229 // waiting for the I2C transaction to end before this stack pointer
212 // becomes invalid, there's nothing wrong here. 230 // becomes invalid, there's nothing wrong here.
213 r.txd().ptr().write_value(buffer.as_ptr() as u32); 231 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
214 r.txd().maxcnt().write(|w| 232 r.dma().tx().maxcnt().write(|w|
215 // We're giving it the length of the buffer, so no danger of 233 // We're giving it the length of the buffer, so no danger of
216 // accessing invalid memory. We have verified that the length of the 234 // accessing invalid memory. We have verified that the length of the
217 // buffer fits in an `u8`, so the cast to `u8` is also fine. 235 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -237,8 +255,8 @@ impl<'d> Twim<'d> {
237 // We're giving the register a pointer to the stack. Since we're 255 // We're giving the register a pointer to the stack. Since we're
238 // waiting for the I2C transaction to end before this stack pointer 256 // waiting for the I2C transaction to end before this stack pointer
239 // becomes invalid, there's nothing wrong here. 257 // becomes invalid, there's nothing wrong here.
240 r.rxd().ptr().write_value(buffer.as_mut_ptr() as u32); 258 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
241 r.rxd().maxcnt().write(|w| 259 r.dma().rx().maxcnt().write(|w|
242 // We're giving it the length of the buffer, so no danger of 260 // We're giving it the length of the buffer, so no danger of
243 // accessing invalid memory. We have verified that the length of the 261 // accessing invalid memory. We have verified that the length of the
244 // buffer fits in an `u8`, so the cast to the type of maxcnt 262 // buffer fits in an `u8`, so the cast to the type of maxcnt
@@ -281,7 +299,7 @@ impl<'d> Twim<'d> {
281 299
282 fn check_rx(&self, len: usize) -> Result<(), Error> { 300 fn check_rx(&self, len: usize) -> Result<(), Error> {
283 let r = self.r; 301 let r = self.r;
284 if r.rxd().amount().read().0 != len as u32 { 302 if r.dma().rx().amount().read().0 != len as u32 {
285 Err(Error::Receive) 303 Err(Error::Receive)
286 } else { 304 } else {
287 Ok(()) 305 Ok(())
@@ -290,7 +308,7 @@ impl<'d> Twim<'d> {
290 308
291 fn check_tx(&self, len: usize) -> Result<(), Error> { 309 fn check_tx(&self, len: usize) -> Result<(), Error> {
292 let r = self.r; 310 let r = self.r;
293 if r.txd().amount().read().0 != len as u32 { 311 if r.dma().tx().amount().read().0 != len as u32 {
294 Err(Error::Transmit) 312 Err(Error::Transmit)
295 } else { 313 } else {
296 Ok(()) 314 Ok(())
@@ -412,7 +430,7 @@ impl<'d> Twim<'d> {
412 } 430 }
413 431
414 r.shorts().write(|w| { 432 r.shorts().write(|w| {
415 w.set_lastrx_starttx(true); 433 w.set_lastrx_dma_tx_start(true);
416 if stop { 434 if stop {
417 w.set_lasttx_stop(true); 435 w.set_lasttx_stop(true);
418 } else { 436 } else {
@@ -421,7 +439,7 @@ impl<'d> Twim<'d> {
421 }); 439 });
422 440
423 // Start read+write operation. 441 // Start read+write operation.
424 r.tasks_startrx().write_value(1); 442 r.tasks_dma().rx().start().write_value(1);
425 if last_op.is_some() { 443 if last_op.is_some() {
426 r.tasks_resume().write_value(1); 444 r.tasks_resume().write_value(1);
427 } 445 }
@@ -429,7 +447,7 @@ impl<'d> Twim<'d> {
429 // TODO: Handle empty write buffer 447 // TODO: Handle empty write buffer
430 if rd_buffer.is_empty() { 448 if rd_buffer.is_empty() {
431 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STARTTX ourselves. 449 // With a zero-length buffer, LASTRX doesn't fire (because there's no last byte!), so do the STARTTX ourselves.
432 r.tasks_starttx().write_value(1); 450 r.tasks_dma().tx().start().write_value(1);
433 } 451 }
434 452
435 Ok(2) 453 Ok(2)
@@ -443,7 +461,7 @@ impl<'d> Twim<'d> {
443 r.shorts().write(|w| w.set_lastrx_stop(true)); 461 r.shorts().write(|w| w.set_lastrx_stop(true));
444 462
445 // Start read operation. 463 // Start read operation.
446 r.tasks_startrx().write_value(1); 464 r.tasks_dma().rx().start().write_value(1);
447 if last_op.is_some() { 465 if last_op.is_some() {
448 r.tasks_resume().write_value(1); 466 r.tasks_resume().write_value(1);
449 } 467 }
@@ -466,11 +484,11 @@ impl<'d> Twim<'d> {
466 484
467 // Start write+read operation. 485 // Start write+read operation.
468 r.shorts().write(|w| { 486 r.shorts().write(|w| {
469 w.set_lasttx_startrx(true); 487 w.set_lasttx_dma_rx_start(true);
470 w.set_lastrx_stop(true); 488 w.set_lastrx_stop(true);
471 }); 489 });
472 490
473 r.tasks_starttx().write_value(1); 491 r.tasks_dma().tx().start().write_value(1);
474 if last_op.is_some() { 492 if last_op.is_some() {
475 r.tasks_resume().write_value(1); 493 r.tasks_resume().write_value(1);
476 } 494 }
@@ -494,7 +512,7 @@ impl<'d> Twim<'d> {
494 } 512 }
495 }); 513 });
496 514
497 r.tasks_starttx().write_value(1); 515 r.tasks_dma().tx().start().write_value(1);
498 if last_op.is_some() { 516 if last_op.is_some() {
499 r.tasks_resume().write_value(1); 517 r.tasks_resume().write_value(1);
500 } 518 }
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs
index 2bc0a5c13..b3a699f71 100644
--- a/embassy-nrf/src/twis.rs
+++ b/embassy-nrf/src/twis.rs
@@ -161,10 +161,19 @@ impl<'d> Twis<'d> {
161 sda.conf().write(|w| { 161 sda.conf().write(|w| {
162 w.set_dir(gpiovals::Dir::INPUT); 162 w.set_dir(gpiovals::Dir::INPUT);
163 w.set_input(gpiovals::Input::CONNECT); 163 w.set_input(gpiovals::Input::CONNECT);
164 #[cfg(not(feature = "_nrf54l"))]
164 w.set_drive(match config.sda_high_drive { 165 w.set_drive(match config.sda_high_drive {
165 true => gpiovals::Drive::H0D1, 166 true => gpiovals::Drive::H0D1,
166 false => gpiovals::Drive::S0D1, 167 false => gpiovals::Drive::S0D1,
167 }); 168 });
169 #[cfg(feature = "_nrf54l")]
170 {
171 w.set_drive0(match config.sda_high_drive {
172 true => gpiovals::Drive::H,
173 false => gpiovals::Drive::S,
174 });
175 w.set_drive1(gpiovals::Drive::D);
176 }
168 if config.sda_pullup { 177 if config.sda_pullup {
169 w.set_pull(gpiovals::Pull::PULLUP); 178 w.set_pull(gpiovals::Pull::PULLUP);
170 } 179 }
@@ -172,10 +181,19 @@ impl<'d> Twis<'d> {
172 scl.conf().write(|w| { 181 scl.conf().write(|w| {
173 w.set_dir(gpiovals::Dir::INPUT); 182 w.set_dir(gpiovals::Dir::INPUT);
174 w.set_input(gpiovals::Input::CONNECT); 183 w.set_input(gpiovals::Input::CONNECT);
184 #[cfg(not(feature = "_nrf54l"))]
175 w.set_drive(match config.scl_high_drive { 185 w.set_drive(match config.scl_high_drive {
176 true => gpiovals::Drive::H0D1, 186 true => gpiovals::Drive::H0D1,
177 false => gpiovals::Drive::S0D1, 187 false => gpiovals::Drive::S0D1,
178 }); 188 });
189 #[cfg(feature = "_nrf54l")]
190 {
191 w.set_drive0(match config.scl_high_drive {
192 true => gpiovals::Drive::H,
193 false => gpiovals::Drive::S,
194 });
195 w.set_drive1(gpiovals::Drive::D);
196 }
179 if config.sda_pullup { 197 if config.sda_pullup {
180 w.set_pull(gpiovals::Pull::PULLUP); 198 w.set_pull(gpiovals::Pull::PULLUP);
181 } 199 }
@@ -228,8 +246,8 @@ impl<'d> Twis<'d> {
228 // We're giving the register a pointer to the stack. Since we're 246 // We're giving the register a pointer to the stack. Since we're
229 // waiting for the I2C transaction to end before this stack pointer 247 // waiting for the I2C transaction to end before this stack pointer
230 // becomes invalid, there's nothing wrong here. 248 // becomes invalid, there's nothing wrong here.
231 r.txd().ptr().write_value(buffer.as_ptr() as u32); 249 r.dma().tx().ptr().write_value(buffer.as_ptr() as u32);
232 r.txd().maxcnt().write(|w| 250 r.dma().tx().maxcnt().write(|w|
233 // We're giving it the length of the buffer, so no danger of 251 // We're giving it the length of the buffer, so no danger of
234 // accessing invalid memory. We have verified that the length of the 252 // accessing invalid memory. We have verified that the length of the
235 // buffer fits in an `u8`, so the cast to `u8` is also fine. 253 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -255,8 +273,8 @@ impl<'d> Twis<'d> {
255 // We're giving the register a pointer to the stack. Since we're 273 // We're giving the register a pointer to the stack. Since we're
256 // waiting for the I2C transaction to end before this stack pointer 274 // waiting for the I2C transaction to end before this stack pointer
257 // becomes invalid, there's nothing wrong here. 275 // becomes invalid, there's nothing wrong here.
258 r.rxd().ptr().write_value(buffer.as_mut_ptr() as u32); 276 r.dma().rx().ptr().write_value(buffer.as_mut_ptr() as u32);
259 r.rxd().maxcnt().write(|w| 277 r.dma().rx().maxcnt().write(|w|
260 // We're giving it the length of the buffer, so no danger of 278 // We're giving it the length of the buffer, so no danger of
261 // accessing invalid memory. We have verified that the length of the 279 // accessing invalid memory. We have verified that the length of the
262 // buffer fits in an `u8`, so the cast to the type of maxcnt 280 // buffer fits in an `u8`, so the cast to the type of maxcnt
@@ -330,13 +348,13 @@ impl<'d> Twis<'d> {
330 return match status { 348 return match status {
331 Status::Read => Ok(Command::Read), 349 Status::Read => Ok(Command::Read),
332 Status::Write => { 350 Status::Write => {
333 let n = r.rxd().amount().read().0 as usize; 351 let n = r.dma().rx().amount().read().0 as usize;
334 Ok(Command::Write(n)) 352 Ok(Command::Write(n))
335 } 353 }
336 }; 354 };
337 } else if r.events_read().read() != 0 { 355 } else if r.events_read().read() != 0 {
338 r.events_read().write_value(0); 356 r.events_read().write_value(0);
339 let n = r.rxd().amount().read().0 as usize; 357 let n = r.dma().rx().amount().read().0 as usize;
340 return Ok(Command::WriteRead(n)); 358 return Ok(Command::WriteRead(n));
341 } 359 }
342 } 360 }
@@ -360,7 +378,7 @@ impl<'d> Twis<'d> {
360 } 378 }
361 } else if r.events_stopped().read() != 0 { 379 } else if r.events_stopped().read() != 0 {
362 r.events_stopped().write_value(0); 380 r.events_stopped().write_value(0);
363 let n = r.txd().amount().read().0 as usize; 381 let n = r.dma().tx().amount().read().0 as usize;
364 return Ok(n); 382 return Ok(n);
365 } 383 }
366 } 384 }
@@ -386,7 +404,7 @@ impl<'d> Twis<'d> {
386 } 404 }
387 } else if r.events_stopped().read() != 0 { 405 } else if r.events_stopped().read() != 0 {
388 r.events_stopped().write_value(0); 406 r.events_stopped().write_value(0);
389 let n = r.txd().amount().read().0 as usize; 407 let n = r.dma().tx().amount().read().0 as usize;
390 return Ok(n); 408 return Ok(n);
391 } else if Instant::now() > deadline { 409 } else if Instant::now() > deadline {
392 r.tasks_stop().write_value(1); 410 r.tasks_stop().write_value(1);
@@ -442,13 +460,13 @@ impl<'d> Twis<'d> {
442 return match status { 460 return match status {
443 Status::Read => Ok(Command::Read), 461 Status::Read => Ok(Command::Read),
444 Status::Write => { 462 Status::Write => {
445 let n = r.rxd().amount().read().0 as usize; 463 let n = r.dma().rx().amount().read().0 as usize;
446 Ok(Command::Write(n)) 464 Ok(Command::Write(n))
447 } 465 }
448 }; 466 };
449 } else if r.events_read().read() != 0 { 467 } else if r.events_read().read() != 0 {
450 r.events_read().write_value(0); 468 r.events_read().write_value(0);
451 let n = r.rxd().amount().read().0 as usize; 469 let n = r.dma().rx().amount().read().0 as usize;
452 return Ok(Command::WriteRead(n)); 470 return Ok(Command::WriteRead(n));
453 } else if Instant::now() > deadline { 471 } else if Instant::now() > deadline {
454 r.tasks_stop().write_value(1); 472 r.tasks_stop().write_value(1);
@@ -478,7 +496,7 @@ impl<'d> Twis<'d> {
478 } 496 }
479 } else if r.events_stopped().read() != 0 { 497 } else if r.events_stopped().read() != 0 {
480 r.events_stopped().write_value(0); 498 r.events_stopped().write_value(0);
481 let n = r.txd().amount().read().0 as usize; 499 let n = r.dma().tx().amount().read().0 as usize;
482 return Poll::Ready(Ok(n)); 500 return Poll::Ready(Ok(n));
483 } 501 }
484 502
@@ -529,13 +547,13 @@ impl<'d> Twis<'d> {
529 return match status { 547 return match status {
530 Status::Read => Poll::Ready(Ok(Command::Read)), 548 Status::Read => Poll::Ready(Ok(Command::Read)),
531 Status::Write => { 549 Status::Write => {
532 let n = r.rxd().amount().read().0 as usize; 550 let n = r.dma().rx().amount().read().0 as usize;
533 Poll::Ready(Ok(Command::Write(n))) 551 Poll::Ready(Ok(Command::Write(n)))
534 } 552 }
535 }; 553 };
536 } else if r.events_read().read() != 0 { 554 } else if r.events_read().read() != 0 {
537 r.events_read().write_value(0); 555 r.events_read().write_value(0);
538 let n = r.rxd().amount().read().0 as usize; 556 let n = r.dma().rx().amount().read().0 as usize;
539 return Poll::Ready(Ok(Command::WriteRead(n))); 557 return Poll::Ready(Ok(Command::WriteRead(n)));
540 } 558 }
541 Poll::Pending 559 Poll::Pending
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 1ee452173..049830aed 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -113,20 +113,20 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
113 let r = T::regs(); 113 let r = T::regs();
114 let s = T::state(); 114 let s = T::state();
115 115
116 let endrx = r.events_endrx().read(); 116 let endrx = r.events_dma().rx().end().read();
117 let error = r.events_error().read(); 117 let error = r.events_error().read();
118 if endrx != 0 || error != 0 { 118 if endrx != 0 || error != 0 {
119 s.rx_waker.wake(); 119 s.rx_waker.wake();
120 if endrx != 0 { 120 if endrx != 0 {
121 r.intenclr().write(|w| w.set_endrx(true)); 121 r.intenclr().write(|w| w.set_dmarxend(true));
122 } 122 }
123 if error != 0 { 123 if error != 0 {
124 r.intenclr().write(|w| w.set_error(true)); 124 r.intenclr().write(|w| w.set_error(true));
125 } 125 }
126 } 126 }
127 if r.events_endtx().read() != 0 { 127 if r.events_dma().tx().end().read() != 0 {
128 s.tx_waker.wake(); 128 s.tx_waker.wake();
129 r.intenclr().write(|w| w.set_endtx(true)); 129 r.intenclr().write(|w| w.set_dmatxend(true));
130 } 130 }
131 } 131 }
132} 132}
@@ -257,7 +257,7 @@ impl<'d> Uarte<'d> {
257 /// Return the endtx event for use with PPI 257 /// Return the endtx event for use with PPI
258 pub fn event_endtx(&self) -> Event<'_> { 258 pub fn event_endtx(&self) -> Event<'_> {
259 let r = self.tx.r; 259 let r = self.tx.r;
260 Event::from_reg(r.events_endtx()) 260 Event::from_reg(r.events_dma().tx().end())
261 } 261 }
262 262
263 /// Read bytes until the buffer is filled. 263 /// Read bytes until the buffer is filled.
@@ -296,7 +296,13 @@ pub(crate) fn configure_tx_pins(r: pac::uarte::Uarte, txd: Peri<'_, AnyPin>, cts
296 txd.conf().write(|w| { 296 txd.conf().write(|w| {
297 w.set_dir(gpiovals::Dir::OUTPUT); 297 w.set_dir(gpiovals::Dir::OUTPUT);
298 w.set_input(gpiovals::Input::DISCONNECT); 298 w.set_input(gpiovals::Input::DISCONNECT);
299 #[cfg(not(feature = "_nrf54l"))]
299 w.set_drive(gpiovals::Drive::H0H1); 300 w.set_drive(gpiovals::Drive::H0H1);
301 #[cfg(feature = "_nrf54l")]
302 {
303 w.set_drive0(gpiovals::Drive::H);
304 w.set_drive1(gpiovals::Drive::H);
305 }
300 }); 306 });
301 r.psel().txd().write_value(txd.psel_bits()); 307 r.psel().txd().write_value(txd.psel_bits());
302 308
@@ -304,7 +310,13 @@ pub(crate) fn configure_tx_pins(r: pac::uarte::Uarte, txd: Peri<'_, AnyPin>, cts
304 pin.conf().write(|w| { 310 pin.conf().write(|w| {
305 w.set_dir(gpiovals::Dir::INPUT); 311 w.set_dir(gpiovals::Dir::INPUT);
306 w.set_input(gpiovals::Input::CONNECT); 312 w.set_input(gpiovals::Input::CONNECT);
313 #[cfg(not(feature = "_nrf54l"))]
307 w.set_drive(gpiovals::Drive::H0H1); 314 w.set_drive(gpiovals::Drive::H0H1);
315 #[cfg(feature = "_nrf54l")]
316 {
317 w.set_drive0(gpiovals::Drive::H);
318 w.set_drive1(gpiovals::Drive::H);
319 }
308 }); 320 });
309 } 321 }
310 r.psel().cts().write_value(cts.psel_bits()); 322 r.psel().cts().write_value(cts.psel_bits());
@@ -314,7 +326,13 @@ pub(crate) fn configure_rx_pins(r: pac::uarte::Uarte, rxd: Peri<'_, AnyPin>, rts
314 rxd.conf().write(|w| { 326 rxd.conf().write(|w| {
315 w.set_dir(gpiovals::Dir::INPUT); 327 w.set_dir(gpiovals::Dir::INPUT);
316 w.set_input(gpiovals::Input::CONNECT); 328 w.set_input(gpiovals::Input::CONNECT);
329 #[cfg(not(feature = "_nrf54l"))]
317 w.set_drive(gpiovals::Drive::H0H1); 330 w.set_drive(gpiovals::Drive::H0H1);
331 #[cfg(feature = "_nrf54l")]
332 {
333 w.set_drive0(gpiovals::Drive::H);
334 w.set_drive1(gpiovals::Drive::H);
335 }
318 }); 336 });
319 r.psel().rxd().write_value(rxd.psel_bits()); 337 r.psel().rxd().write_value(rxd.psel_bits());
320 338
@@ -323,7 +341,13 @@ pub(crate) fn configure_rx_pins(r: pac::uarte::Uarte, rxd: Peri<'_, AnyPin>, rts
323 pin.conf().write(|w| { 341 pin.conf().write(|w| {
324 w.set_dir(gpiovals::Dir::OUTPUT); 342 w.set_dir(gpiovals::Dir::OUTPUT);
325 w.set_input(gpiovals::Input::DISCONNECT); 343 w.set_input(gpiovals::Input::DISCONNECT);
344 #[cfg(not(feature = "_nrf54l"))]
326 w.set_drive(gpiovals::Drive::H0H1); 345 w.set_drive(gpiovals::Drive::H0H1);
346 #[cfg(feature = "_nrf54l")]
347 {
348 w.set_drive0(gpiovals::Drive::H);
349 w.set_drive1(gpiovals::Drive::H);
350 }
327 }); 351 });
328 } 352 }
329 r.psel().rts().write_value(rts.psel_bits()); 353 r.psel().rts().write_value(rts.psel_bits());
@@ -333,6 +357,10 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont
333 r.config().write(|w| { 357 r.config().write(|w| {
334 w.set_hwfc(hardware_flow_control); 358 w.set_hwfc(hardware_flow_control);
335 w.set_parity(config.parity); 359 w.set_parity(config.parity);
360 #[cfg(feature = "_nrf54l")]
361 w.set_framesize(vals::Framesize::_8BIT);
362 #[cfg(feature = "_nrf54l")]
363 w.set_frametimeout(true);
336 }); 364 });
337 r.baudrate().write(|w| w.set_baudrate(config.baudrate)); 365 r.baudrate().write(|w| w.set_baudrate(config.baudrate));
338 366
@@ -341,8 +369,8 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont
341 369
342 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was 370 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was
343 // stopped midway or not. 371 // stopped midway or not.
344 r.events_rxstarted().write_value(0); 372 r.events_dma().rx().ready().write_value(0);
345 r.events_txstarted().write_value(0); 373 r.events_dma().tx().ready().write_value(0);
346 374
347 // reset all pins 375 // reset all pins
348 r.psel().txd().write_value(DISCONNECTED); 376 r.psel().txd().write_value(DISCONNECTED);
@@ -434,29 +462,29 @@ impl<'d> UarteTx<'d> {
434 let drop = OnDrop::new(move || { 462 let drop = OnDrop::new(move || {
435 trace!("write drop: stopping"); 463 trace!("write drop: stopping");
436 464
437 r.intenclr().write(|w| w.set_endtx(true)); 465 r.intenclr().write(|w| w.set_dmatxend(true));
438 r.events_txstopped().write_value(0); 466 r.events_txstopped().write_value(0);
439 r.tasks_stoptx().write_value(1); 467 r.tasks_dma().tx().stop().write_value(1);
440 468
441 // TX is stopped almost instantly, spinning is fine. 469 // TX is stopped almost instantly, spinning is fine.
442 while r.events_endtx().read() == 0 {} 470 while r.events_dma().tx().end().read() == 0 {}
443 trace!("write drop: stopped"); 471 trace!("write drop: stopped");
444 }); 472 });
445 473
446 r.txd().ptr().write_value(ptr as u32); 474 r.dma().tx().ptr().write_value(ptr as u32);
447 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 475 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
448 476
449 r.events_endtx().write_value(0); 477 r.events_dma().tx().end().write_value(0);
450 r.intenset().write(|w| w.set_endtx(true)); 478 r.intenset().write(|w| w.set_dmatxend(true));
451 479
452 compiler_fence(Ordering::SeqCst); 480 compiler_fence(Ordering::SeqCst);
453 481
454 trace!("starttx"); 482 trace!("starttx");
455 r.tasks_starttx().write_value(1); 483 r.tasks_dma().tx().start().write_value(1);
456 484
457 poll_fn(|cx| { 485 poll_fn(|cx| {
458 s.tx_waker.register(cx.waker()); 486 s.tx_waker.register(cx.waker());
459 if r.events_endtx().read() != 0 { 487 if r.events_dma().tx().end().read() != 0 {
460 return Poll::Ready(()); 488 return Poll::Ready(());
461 } 489 }
462 Poll::Pending 490 Poll::Pending
@@ -464,7 +492,7 @@ impl<'d> UarteTx<'d> {
464 .await; 492 .await;
465 493
466 compiler_fence(Ordering::SeqCst); 494 compiler_fence(Ordering::SeqCst);
467 r.events_txstarted().write_value(0); 495 r.events_dma().tx().ready().write_value(0);
468 drop.defuse(); 496 drop.defuse();
469 497
470 Ok(()) 498 Ok(())
@@ -500,21 +528,21 @@ impl<'d> UarteTx<'d> {
500 528
501 let r = self.r; 529 let r = self.r;
502 530
503 r.txd().ptr().write_value(ptr as u32); 531 r.dma().tx().ptr().write_value(ptr as u32);
504 r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); 532 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
505 533
506 r.events_endtx().write_value(0); 534 r.events_dma().tx().end().write_value(0);
507 r.intenclr().write(|w| w.set_endtx(true)); 535 r.intenclr().write(|w| w.set_dmatxend(true));
508 536
509 compiler_fence(Ordering::SeqCst); 537 compiler_fence(Ordering::SeqCst);
510 538
511 trace!("starttx"); 539 trace!("starttx");
512 r.tasks_starttx().write_value(1); 540 r.tasks_dma().tx().start().write_value(1);
513 541
514 while r.events_endtx().read() == 0 {} 542 while r.events_dma().tx().end().read() == 0 {}
515 543
516 compiler_fence(Ordering::SeqCst); 544 compiler_fence(Ordering::SeqCst);
517 r.events_txstarted().write_value(0); 545 r.events_dma().tx().ready().write_value(0);
518 546
519 Ok(()) 547 Ok(())
520 } 548 }
@@ -526,7 +554,7 @@ impl<'a> Drop for UarteTx<'a> {
526 554
527 let r = self.r; 555 let r = self.r;
528 556
529 let did_stoptx = r.events_txstarted().read() != 0; 557 let did_stoptx = r.events_dma().tx().ready().read() != 0;
530 trace!("did_stoptx {}", did_stoptx); 558 trace!("did_stoptx {}", did_stoptx);
531 559
532 // Wait for txstopped, if needed. 560 // Wait for txstopped, if needed.
@@ -629,7 +657,7 @@ impl<'d> UarteRx<'d> {
629 let mut ppi_ch2 = Ppi::new_one_to_one( 657 let mut ppi_ch2 = Ppi::new_one_to_one(
630 ppi_ch2.into(), 658 ppi_ch2.into(),
631 timer.cc(0).event_compare(), 659 timer.cc(0).event_compare(),
632 Task::from_reg(r.tasks_stoprx()), 660 Task::from_reg(r.tasks_dma().rx().stop()),
633 ); 661 );
634 ppi_ch2.enable(); 662 ppi_ch2.enable();
635 663
@@ -664,41 +692,41 @@ impl<'d> UarteRx<'d> {
664 trace!("read drop: stopping"); 692 trace!("read drop: stopping");
665 693
666 r.intenclr().write(|w| { 694 r.intenclr().write(|w| {
667 w.set_endrx(true); 695 w.set_dmarxend(true);
668 w.set_error(true); 696 w.set_error(true);
669 }); 697 });
670 r.events_rxto().write_value(0); 698 r.events_rxto().write_value(0);
671 r.events_error().write_value(0); 699 r.events_error().write_value(0);
672 r.tasks_stoprx().write_value(1); 700 r.tasks_dma().rx().stop().write_value(1);
673 701
674 while r.events_endrx().read() == 0 {} 702 while r.events_dma().rx().end().read() == 0 {}
675 703
676 trace!("read drop: stopped"); 704 trace!("read drop: stopped");
677 }); 705 });
678 706
679 r.rxd().ptr().write_value(ptr as u32); 707 r.dma().rx().ptr().write_value(ptr as u32);
680 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 708 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
681 709
682 r.events_endrx().write_value(0); 710 r.events_dma().rx().end().write_value(0);
683 r.events_error().write_value(0); 711 r.events_error().write_value(0);
684 r.intenset().write(|w| { 712 r.intenset().write(|w| {
685 w.set_endrx(true); 713 w.set_dmarxend(true);
686 w.set_error(true); 714 w.set_error(true);
687 }); 715 });
688 716
689 compiler_fence(Ordering::SeqCst); 717 compiler_fence(Ordering::SeqCst);
690 718
691 trace!("startrx"); 719 trace!("startrx");
692 r.tasks_startrx().write_value(1); 720 r.tasks_dma().rx().start().write_value(1);
693 721
694 let result = poll_fn(|cx| { 722 let result = poll_fn(|cx| {
695 s.rx_waker.register(cx.waker()); 723 s.rx_waker.register(cx.waker());
696 724
697 if let Err(e) = self.check_and_clear_errors() { 725 if let Err(e) = self.check_and_clear_errors() {
698 r.tasks_stoprx().write_value(1); 726 r.tasks_dma().rx().stop().write_value(1);
699 return Poll::Ready(Err(e)); 727 return Poll::Ready(Err(e));
700 } 728 }
701 if r.events_endrx().read() != 0 { 729 if r.events_dma().rx().end().read() != 0 {
702 return Poll::Ready(Ok(())); 730 return Poll::Ready(Ok(()));
703 } 731 }
704 Poll::Pending 732 Poll::Pending
@@ -706,7 +734,7 @@ impl<'d> UarteRx<'d> {
706 .await; 734 .await;
707 735
708 compiler_fence(Ordering::SeqCst); 736 compiler_fence(Ordering::SeqCst);
709 r.events_rxstarted().write_value(0); 737 r.events_dma().rx().ready().write_value(0);
710 drop.defuse(); 738 drop.defuse();
711 739
712 result 740 result
@@ -726,25 +754,25 @@ impl<'d> UarteRx<'d> {
726 754
727 let r = self.r; 755 let r = self.r;
728 756
729 r.rxd().ptr().write_value(ptr as u32); 757 r.dma().rx().ptr().write_value(ptr as u32);
730 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 758 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
731 759
732 r.events_endrx().write_value(0); 760 r.events_dma().rx().end().write_value(0);
733 r.events_error().write_value(0); 761 r.events_error().write_value(0);
734 r.intenclr().write(|w| { 762 r.intenclr().write(|w| {
735 w.set_endrx(true); 763 w.set_dmarxend(true);
736 w.set_error(true); 764 w.set_error(true);
737 }); 765 });
738 766
739 compiler_fence(Ordering::SeqCst); 767 compiler_fence(Ordering::SeqCst);
740 768
741 trace!("startrx"); 769 trace!("startrx");
742 r.tasks_startrx().write_value(1); 770 r.tasks_dma().rx().start().write_value(1);
743 771
744 while r.events_endrx().read() == 0 && r.events_error().read() == 0 {} 772 while r.events_dma().rx().end().read() == 0 && r.events_error().read() == 0 {}
745 773
746 compiler_fence(Ordering::SeqCst); 774 compiler_fence(Ordering::SeqCst);
747 r.events_rxstarted().write_value(0); 775 r.events_dma().rx().ready().write_value(0);
748 776
749 self.check_and_clear_errors() 777 self.check_and_clear_errors()
750 } 778 }
@@ -756,7 +784,7 @@ impl<'a> Drop for UarteRx<'a> {
756 784
757 let r = self.r; 785 let r = self.r;
758 786
759 let did_stoprx = r.events_rxstarted().read() != 0; 787 let did_stoprx = r.events_dma().rx().ready().read() != 0;
760 trace!("did_stoprx {}", did_stoprx); 788 trace!("did_stoprx {}", did_stoprx);
761 789
762 // Wait for rxto, if needed. 790 // Wait for rxto, if needed.
@@ -816,38 +844,38 @@ impl<'d> UarteRxWithIdle<'d> {
816 self.timer.stop(); 844 self.timer.stop();
817 845
818 r.intenclr().write(|w| { 846 r.intenclr().write(|w| {
819 w.set_endrx(true); 847 w.set_dmarxend(true);
820 w.set_error(true); 848 w.set_error(true);
821 }); 849 });
822 r.events_rxto().write_value(0); 850 r.events_rxto().write_value(0);
823 r.events_error().write_value(0); 851 r.events_error().write_value(0);
824 r.tasks_stoprx().write_value(1); 852 r.tasks_dma().rx().stop().write_value(1);
825 853
826 while r.events_endrx().read() == 0 {} 854 while r.events_dma().rx().end().read() == 0 {}
827 }); 855 });
828 856
829 r.rxd().ptr().write_value(ptr as u32); 857 r.dma().rx().ptr().write_value(ptr as u32);
830 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 858 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
831 859
832 r.events_endrx().write_value(0); 860 r.events_dma().rx().end().write_value(0);
833 r.events_error().write_value(0); 861 r.events_error().write_value(0);
834 r.intenset().write(|w| { 862 r.intenset().write(|w| {
835 w.set_endrx(true); 863 w.set_dmarxend(true);
836 w.set_error(true); 864 w.set_error(true);
837 }); 865 });
838 866
839 compiler_fence(Ordering::SeqCst); 867 compiler_fence(Ordering::SeqCst);
840 868
841 r.tasks_startrx().write_value(1); 869 r.tasks_dma().rx().start().write_value(1);
842 870
843 let result = poll_fn(|cx| { 871 let result = poll_fn(|cx| {
844 s.rx_waker.register(cx.waker()); 872 s.rx_waker.register(cx.waker());
845 873
846 if let Err(e) = self.rx.check_and_clear_errors() { 874 if let Err(e) = self.rx.check_and_clear_errors() {
847 r.tasks_stoprx().write_value(1); 875 r.tasks_dma().rx().stop().write_value(1);
848 return Poll::Ready(Err(e)); 876 return Poll::Ready(Err(e));
849 } 877 }
850 if r.events_endrx().read() != 0 { 878 if r.events_dma().rx().end().read() != 0 {
851 return Poll::Ready(Ok(())); 879 return Poll::Ready(Ok(()));
852 } 880 }
853 881
@@ -856,10 +884,10 @@ impl<'d> UarteRxWithIdle<'d> {
856 .await; 884 .await;
857 885
858 compiler_fence(Ordering::SeqCst); 886 compiler_fence(Ordering::SeqCst);
859 let n = r.rxd().amount().read().0 as usize; 887 let n = r.dma().rx().amount().read().0 as usize;
860 888
861 self.timer.stop(); 889 self.timer.stop();
862 r.events_rxstarted().write_value(0); 890 r.events_dma().rx().ready().write_value(0);
863 891
864 drop.defuse(); 892 drop.defuse();
865 893
@@ -884,27 +912,27 @@ impl<'d> UarteRxWithIdle<'d> {
884 912
885 self.ppi_ch1.enable(); 913 self.ppi_ch1.enable();
886 914
887 r.rxd().ptr().write_value(ptr as u32); 915 r.dma().rx().ptr().write_value(ptr as u32);
888 r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); 916 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(len as _));
889 917
890 r.events_endrx().write_value(0); 918 r.events_dma().rx().end().write_value(0);
891 r.events_error().write_value(0); 919 r.events_error().write_value(0);
892 r.intenclr().write(|w| { 920 r.intenclr().write(|w| {
893 w.set_endrx(true); 921 w.set_dmarxend(true);
894 w.set_error(true); 922 w.set_error(true);
895 }); 923 });
896 924
897 compiler_fence(Ordering::SeqCst); 925 compiler_fence(Ordering::SeqCst);
898 926
899 r.tasks_startrx().write_value(1); 927 r.tasks_dma().rx().start().write_value(1);
900 928
901 while r.events_endrx().read() == 0 && r.events_error().read() == 0 {} 929 while r.events_dma().rx().end().read() == 0 && r.events_error().read() == 0 {}
902 930
903 compiler_fence(Ordering::SeqCst); 931 compiler_fence(Ordering::SeqCst);
904 let n = r.rxd().amount().read().0 as usize; 932 let n = r.dma().rx().amount().read().0 as usize;
905 933
906 self.timer.stop(); 934 self.timer.stop();
907 r.events_rxstarted().write_value(0); 935 r.events_dma().rx().ready().write_value(0);
908 936
909 self.rx.check_and_clear_errors().map(|_| n) 937 self.rx.check_and_clear_errors().map(|_| n)
910 } 938 }
@@ -927,14 +955,14 @@ pub(crate) fn apply_workaround_for_enable_anomaly(r: pac::uarte::Uarte) {
927 // NB Safety: This is taken from Nordic's driver - 955 // NB Safety: This is taken from Nordic's driver -
928 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197 956 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
929 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 { 957 if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
930 r.tasks_stoptx().write_value(1); 958 r.tasks_dma().tx().stop().write_value(1);
931 } 959 }
932 960
933 // NB Safety: This is taken from Nordic's driver - 961 // NB Safety: This is taken from Nordic's driver -
934 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197 962 // https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
935 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 { 963 if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
936 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); 964 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
937 r.tasks_stoprx().write_value(1); 965 r.tasks_dma().rx().stop().write_value(1);
938 966
939 let mut workaround_succeded = false; 967 let mut workaround_succeded = false;
940 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered. 968 // The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
@@ -948,6 +976,14 @@ pub(crate) fn apply_workaround_for_enable_anomaly(r: pac::uarte::Uarte) {
948 break; 976 break;
949 } else { 977 } else {
950 // Need to sleep for 1us here 978 // Need to sleep for 1us here
979
980 // Get the worst case clock speed
981 #[cfg(feature = "_nrf9160")]
982 const CLOCK_SPEED: u32 = 64_000_000;
983 #[cfg(feature = "_nrf5340")]
984 const CLOCK_SPEED: u32 = 128_000_000;
985
986 cortex_m::asm::delay(CLOCK_SPEED / 1_000_000);
951 } 987 }
952 } 988 }
953 989
diff --git a/embassy-nxp/CHANGELOG.md b/embassy-nxp/CHANGELOG.md
index 0fb677cd8..39f5c75bd 100644
--- a/embassy-nxp/CHANGELOG.md
+++ b/embassy-nxp/CHANGELOG.md
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10- LPC55: PWM simple
11- LPC55: Move ALT definitions for USART to TX/RX pin impls.
12- LPC55: Remove internal match_iocon macro
10- LPC55: DMA Controller and asynchronous version of USART 13- LPC55: DMA Controller and asynchronous version of USART
11- Moved NXP LPC55S69 from `lpc55-pac` to `nxp-pac` 14- Moved NXP LPC55S69 from `lpc55-pac` to `nxp-pac`
12- First release with changelog. 15- First release with changelog.
diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml
index 33f0f2dff..f8c63ba29 100644
--- a/embassy-nxp/Cargo.toml
+++ b/embassy-nxp/Cargo.toml
@@ -38,13 +38,13 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut
38embedded-io = "0.6.1" 38embedded-io = "0.6.1"
39embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 39embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
40## Chip dependencies 40## Chip dependencies
41nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538"} 41nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "477dfdbfd5e6c75c0730c56494b601c1b2257263"}
42 42
43imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } 43imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] }
44 44
45[build-dependencies] 45[build-dependencies]
46cfg_aliases = "0.2.1" 46cfg_aliases = "0.2.1"
47nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538", features = ["metadata"], optional = true } 47nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "477dfdbfd5e6c75c0730c56494b601c1b2257263", features = ["metadata"], optional = true }
48proc-macro2 = "1.0.95" 48proc-macro2 = "1.0.95"
49quote = "1.0.15" 49quote = "1.0.15"
50 50
diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs
index 9f4e7269f..e9addddb6 100644
--- a/embassy-nxp/src/chips/lpc55.rs
+++ b/embassy-nxp/src/chips/lpc55.rs
@@ -97,6 +97,18 @@ embassy_hal_internal::peripherals! {
97 DMA_CH21, 97 DMA_CH21,
98 DMA_CH22, 98 DMA_CH22,
99 99
100 // Pulse-Width Modulation Outputs.
101 PWM_OUTPUT0,
102 PWM_OUTPUT1,
103 PWM_OUTPUT2,
104 PWM_OUTPUT3,
105 PWM_OUTPUT4,
106 PWM_OUTPUT5,
107 PWM_OUTPUT6,
108 PWM_OUTPUT7,
109 PWM_OUTPUT8,
110 PWM_OUTPUT9,
111
100 // Universal Synchronous/Asynchronous Receiver/Transmitter (USART) instances. 112 // Universal Synchronous/Asynchronous Receiver/Transmitter (USART) instances.
101 USART0, 113 USART0,
102 USART1, 114 USART1,
diff --git a/embassy-nxp/src/fmt.rs b/embassy-nxp/src/fmt.rs
index 27d41ace6..11275235e 100644
--- a/embassy-nxp/src/fmt.rs
+++ b/embassy-nxp/src/fmt.rs
@@ -1,5 +1,4 @@
1//! Copied from embassy-rp 1//! Copied from embassy-rp
2
3#![macro_use] 2#![macro_use]
4#![allow(unused)] 3#![allow(unused)]
5 4
diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs
index ac8a27d4f..6039d8ca8 100644
--- a/embassy-nxp/src/gpio/lpc55.rs
+++ b/embassy-nxp/src/gpio/lpc55.rs
@@ -1,7 +1,8 @@
1use embassy_hal_internal::{PeripheralType, impl_peripheral}; 1use embassy_hal_internal::{PeripheralType, impl_peripheral};
2 2
3use crate::pac::common::{RW, Reg};
3use crate::pac::iocon::vals::{PioDigimode, PioMode}; 4use crate::pac::iocon::vals::{PioDigimode, PioMode};
4use crate::pac::{GPIO, IOCON, SYSCON}; 5use crate::pac::{GPIO, IOCON, SYSCON, iocon};
5use crate::{Peri, peripherals}; 6use crate::{Peri, peripherals};
6 7
7pub(crate) fn init() { 8pub(crate) fn init() {
@@ -109,13 +110,7 @@ impl<'d> Input<'d> {
109 110
110 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. 111 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
111 pub fn set_pull(&mut self, pull: Pull) { 112 pub fn set_pull(&mut self, pull: Pull) {
112 match_iocon!(register, self.pin.pin_bank(), self.pin.pin_number(), { 113 self.pin.set_pull(pull);
113 register.modify(|w| match pull {
114 Pull::None => w.set_mode(PioMode::INACTIVE),
115 Pull::Up => w.set_mode(PioMode::PULL_UP),
116 Pull::Down => w.set_mode(PioMode::PULL_DOWN),
117 });
118 });
119 } 114 }
120 115
121 /// Get the current input level of the pin. 116 /// Get the current input level of the pin.
@@ -193,11 +188,20 @@ impl<'d> Flex<'d> {
193 1 << self.pin.pin_number() 188 1 << self.pin.pin_number()
194 } 189 }
195 190
191 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
192 pub fn set_pull(&mut self, pull: Pull) {
193 self.pin.pio().modify(|w| match pull {
194 Pull::None => w.set_mode(PioMode::INACTIVE),
195 Pull::Up => w.set_mode(PioMode::PULL_UP),
196 Pull::Down => w.set_mode(PioMode::PULL_DOWN),
197 });
198 }
199
196 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default 200 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default
197 /// setting for pins is (usually) non-digital. 201 /// setting for pins is (usually) non-digital.
198 fn set_as_digital(&mut self) { 202 fn set_as_digital(&mut self) {
199 match_iocon!(register, self.pin_bank(), self.pin_number(), { 203 self.pin.pio().modify(|w| {
200 register.modify(|w| w.set_digimode(PioDigimode::DIGITAL)); 204 w.set_digimode(PioDigimode::DIGITAL);
201 }); 205 });
202 } 206 }
203 207
@@ -220,6 +224,14 @@ impl<'d> Flex<'d> {
220pub(crate) trait SealedPin: Sized { 224pub(crate) trait SealedPin: Sized {
221 fn pin_bank(&self) -> Bank; 225 fn pin_bank(&self) -> Bank;
222 fn pin_number(&self) -> u8; 226 fn pin_number(&self) -> u8;
227
228 #[inline]
229 fn pio(&self) -> Reg<iocon::regs::Pio, RW> {
230 match self.pin_bank() {
231 Bank::Bank0 => IOCON.pio0(self.pin_number() as usize),
232 Bank::Bank1 => IOCON.pio1(self.pin_number() as usize),
233 }
234 }
223} 235}
224 236
225/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an 237/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an
@@ -272,40 +284,6 @@ impl SealedPin for AnyPin {
272 } 284 }
273} 285}
274 286
275/// Match the pin bank and number of a pin to the corresponding IOCON register.
276///
277/// # Example
278/// ```
279/// use embassy_nxp::gpio::Bank;
280/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon};
281///
282/// // Make pin PIO1_6 digital and set it to pull-down mode.
283/// match_iocon!(register, Bank::Bank1, 6, {
284/// register.modify(|w|{
285/// w.set_mode(PioMode::PULL_DOWN);
286/// w.set_digimode(PioDigimode::DIGITAL);
287///
288/// }
289/// });
290/// ```
291macro_rules! match_iocon {
292 ($register:ident, $pin_bank:expr, $pin_number:expr, $action:expr) => {
293 match $pin_bank {
294 Bank::Bank0 => {
295 let $register = IOCON.pio0($pin_number as usize);
296 $action;
297 }
298
299 Bank::Bank1 => {
300 let $register = IOCON.pio1($pin_number as usize);
301 $action;
302 }
303 }
304 };
305}
306
307pub(crate) use match_iocon;
308
309macro_rules! impl_pin { 287macro_rules! impl_pin {
310 ($name:ident, $bank:expr, $pin_num:expr) => { 288 ($name:ident, $bank:expr, $pin_num:expr) => {
311 impl Pin for peripherals::$name {} 289 impl Pin for peripherals::$name {}
diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs
index 9576f02b1..4058881a5 100644
--- a/embassy-nxp/src/lib.rs
+++ b/embassy-nxp/src/lib.rs
@@ -10,6 +10,8 @@ pub mod gpio;
10#[cfg(feature = "lpc55-core0")] 10#[cfg(feature = "lpc55-core0")]
11pub mod pint; 11pub mod pint;
12#[cfg(feature = "lpc55-core0")] 12#[cfg(feature = "lpc55-core0")]
13pub mod pwm;
14#[cfg(feature = "lpc55-core0")]
13pub mod usart; 15pub mod usart;
14 16
15#[cfg(feature = "_time_driver")] 17#[cfg(feature = "_time_driver")]
@@ -154,7 +156,10 @@ pub fn init(_config: config::Config) -> Peripherals {
154 gpio::init(); 156 gpio::init();
155 157
156 #[cfg(feature = "lpc55-core0")] 158 #[cfg(feature = "lpc55-core0")]
157 pint::init(); 159 {
160 pint::init();
161 pwm::Pwm::reset();
162 }
158 163
159 #[cfg(feature = "_time_driver")] 164 #[cfg(feature = "_time_driver")]
160 time_driver::init(); 165 time_driver::init();
diff --git a/embassy-nxp/src/pwm.rs b/embassy-nxp/src/pwm.rs
new file mode 100644
index 000000000..68980924a
--- /dev/null
+++ b/embassy-nxp/src/pwm.rs
@@ -0,0 +1,5 @@
1//! Pulse-Width Modulation (PWM) driver.
2
3#[cfg_attr(feature = "lpc55-core0", path = "./pwm/lpc55.rs")]
4mod inner;
5pub use inner::*;
diff --git a/embassy-nxp/src/pwm/lpc55.rs b/embassy-nxp/src/pwm/lpc55.rs
new file mode 100644
index 000000000..197184ad6
--- /dev/null
+++ b/embassy-nxp/src/pwm/lpc55.rs
@@ -0,0 +1,325 @@
1use core::sync::atomic::{AtomicU8, AtomicU32, Ordering};
2
3use embassy_hal_internal::{Peri, PeripheralType};
4
5use crate::gpio::AnyPin;
6use crate::pac::iocon::vals::{PioDigimode, PioFunc, PioMode, PioOd, PioSlew};
7use crate::pac::sct0::vals;
8use crate::pac::syscon::vals::{SctRst, SctclkselSel};
9use crate::pac::{SCT0, SYSCON};
10
11// Since for now the counter is shared, the TOP value has to be kept.
12static TOP_VALUE: AtomicU32 = AtomicU32::new(0);
13// To check if there are still active instances.
14static REF_COUNT: AtomicU8 = AtomicU8::new(0);
15
16/// The configuration of a PWM output.
17/// Note the period in clock cycles of an output can be computed as:
18/// `(top + 1) * (phase_correct ? 1 : 2) * divider * prescale_factor`
19/// By default, the clock used is 96 MHz.
20#[non_exhaustive]
21#[derive(Clone)]
22pub struct Config {
23 /// Inverts the PWM output signal.
24 pub invert: bool,
25 /// Enables phase-correct mode for PWM operation.
26 /// In phase-correct mode, the PWM signal is generated in such a way that
27 /// the pulse is always centered regardless of the duty cycle.
28 /// The output frequency is halved when phase-correct mode is enabled.
29 pub phase_correct: bool,
30 /// Enables the PWM output, allowing it to generate an output.
31 pub enable: bool,
32 /// A SYSCON clock divider allows precise control over
33 /// the PWM output frequency by gating the PWM counter increment.
34 /// A higher value will result in a slower output frequency.
35 /// The clock is divided by `divider + 1`.
36 pub divider: u8,
37 /// Specifies the factor by which the SCT clock is prescaled to produce the unified
38 /// counter clock. The counter clock is clocked at the rate of the SCT clock divided by
39 /// `PRE + 1`.
40 pub prescale_factor: u8,
41 /// The output goes high when `compare` is higher than the
42 /// counter. A compare of 0 will produce an always low output, while a
43 /// compare of `top` will produce an always high output.
44 pub compare: u32,
45 /// The point at which the counter resets, representing the maximum possible
46 /// period. The counter will either wrap to 0 or reverse depending on the
47 /// setting of `phase_correct`.
48 pub top: u32,
49}
50
51impl Config {
52 pub fn new(compare: u32, top: u32) -> Self {
53 Self {
54 invert: false,
55 phase_correct: false,
56 enable: true,
57 divider: 255,
58 prescale_factor: 255,
59 compare,
60 top,
61 }
62 }
63}
64
65/// PWM driver.
66pub struct Pwm<'d> {
67 _pin: Peri<'d, AnyPin>,
68 output: usize,
69}
70
71impl<'d> Pwm<'d> {
72 pub(crate) fn reset() {
73 // Reset SCTimer => Reset counter and halt it.
74 // It should be done only once during the initialization of the board.
75 SYSCON.presetctrl1().modify(|w| w.set_sct_rst(SctRst::ASSERTED));
76 SYSCON.presetctrl1().modify(|w| w.set_sct_rst(SctRst::RELEASED));
77 }
78 fn new_inner<T: Output>(output: usize, channel: Peri<'d, impl OutputChannelPin<T>>, config: Config) -> Self {
79 // Enable clocks (Syscon is enabled by default)
80 critical_section::with(|_cs| {
81 if !SYSCON.ahbclkctrl0().read().iocon() {
82 SYSCON.ahbclkctrl0().modify(|w| w.set_iocon(true));
83 }
84 if !SYSCON.ahbclkctrl1().read().sct() {
85 SYSCON.ahbclkctrl1().modify(|w| w.set_sct(true));
86 }
87 });
88
89 // Choose the clock for PWM.
90 SYSCON.sctclksel().modify(|w| w.set_sel(SctclkselSel::ENUM_0X3));
91 // For now, 96 MHz.
92
93 // IOCON Setup
94 channel.pio().modify(|w| {
95 w.set_func(channel.pin_func());
96 w.set_digimode(PioDigimode::DIGITAL);
97 w.set_slew(PioSlew::STANDARD);
98 w.set_mode(PioMode::INACTIVE);
99 w.set_od(PioOd::NORMAL);
100 });
101
102 Self::configure(output, &config);
103 REF_COUNT.fetch_add(1, Ordering::Relaxed);
104 Self {
105 _pin: channel.into(),
106 output,
107 }
108 }
109
110 /// Create PWM driver with a single 'a' pin as output.
111 #[inline]
112 pub fn new_output<T: Output>(
113 output: Peri<'d, T>,
114 channel: Peri<'d, impl OutputChannelPin<T>>,
115 config: Config,
116 ) -> Self {
117 Self::new_inner(output.number(), channel, config)
118 }
119
120 /// Set the PWM config.
121 pub fn set_config(&mut self, config: &Config) {
122 Self::configure(self.output, config);
123 }
124
125 fn configure(output_number: usize, config: &Config) {
126 // Stop and reset the counter
127 SCT0.ctrl().modify(|w| {
128 if config.phase_correct {
129 w.set_bidir_l(vals::Bidir::UP_DOWN);
130 } else {
131 w.set_bidir_l(vals::Bidir::UP);
132 }
133 w.set_halt_l(true); // halt the counter to make new changes
134 w.set_clrctr_l(true); // clear the counter
135 });
136 // Divides clock by 1-255
137 SYSCON.sctclkdiv().modify(|w| w.set_div(config.divider));
138
139 SCT0.config().modify(|w| {
140 w.set_unify(vals::Unify::UNIFIED_COUNTER);
141 w.set_clkmode(vals::Clkmode::SYSTEM_CLOCK_MODE);
142 w.set_noreload_l(true);
143 w.set_autolimit_l(true);
144 });
145
146 // Before setting the match registers, we have to make sure that `compare` is lower or equal to `top`,
147 // otherwise the counter will not reach the match and, therefore, no events will happen.
148 assert!(config.compare <= config.top);
149
150 if TOP_VALUE.load(Ordering::Relaxed) == 0 {
151 // Match 0 will reset the timer using TOP value
152 SCT0.match_(0).modify(|w| {
153 w.set_matchn_l((config.top & 0xFFFF) as u16);
154 w.set_matchn_h((config.top >> 16) as u16);
155 });
156 } else {
157 panic!("The top value cannot be changed after the initialization.");
158 }
159 // The actual matches that are used for event logic
160 SCT0.match_(output_number + 1).modify(|w| {
161 w.set_matchn_l((config.compare & 0xFFFF) as u16);
162 w.set_matchn_h((config.compare >> 16) as u16);
163 });
164
165 SCT0.match_(15).modify(|w| {
166 w.set_matchn_l(0);
167 w.set_matchn_h(0);
168 });
169
170 // Event configuration
171 critical_section::with(|_cs| {
172 // If it is already set, don't change
173 if SCT0.ev(0).ev_ctrl().read().matchsel() != 15 {
174 SCT0.ev(0).ev_ctrl().modify(|w| {
175 w.set_matchsel(15);
176 w.set_combmode(vals::Combmode::MATCH);
177 // STATE + statev, where STATE is a on-board variable.
178 w.set_stateld(vals::Stateld::ADD);
179 w.set_statev(0);
180 });
181 }
182 });
183 SCT0.ev(output_number + 1).ev_ctrl().modify(|w| {
184 w.set_matchsel((output_number + 1) as u8);
185 w.set_combmode(vals::Combmode::MATCH);
186 w.set_stateld(vals::Stateld::ADD);
187 // STATE + statev, where STATE is a on-board variable.
188 w.set_statev(0);
189 });
190
191 // Assign events to states
192 SCT0.ev(0).ev_state().modify(|w| w.set_statemskn(1 << 0));
193 SCT0.ev(output_number + 1)
194 .ev_state()
195 .modify(|w| w.set_statemskn(1 << 0));
196 // TODO(frihetselsker): optimize nxp-pac so that `set_clr` and `set_set` are turned into a bit array.
197 if config.invert {
198 // Low when event 0 is active
199 SCT0.out(output_number).out_clr().modify(|w| w.set_clr(1 << 0));
200 // High when event `output_number + 1` is active
201 SCT0.out(output_number)
202 .out_set()
203 .modify(|w| w.set_set(1 << (output_number + 1)));
204 } else {
205 // High when event 0 is active
206 SCT0.out(output_number).out_set().modify(|w| w.set_set(1 << 0));
207 // Low when event `output_number + 1` is active
208 SCT0.out(output_number)
209 .out_clr()
210 .modify(|w| w.set_clr(1 << (output_number + 1)));
211 }
212
213 if config.phase_correct {
214 // Take into account the set matches and reverse their actions while counting back.
215 SCT0.outputdirctrl()
216 .modify(|w| w.set_setclr(output_number, vals::Setclr::L_REVERSED));
217 }
218
219 // State 0 by default
220 SCT0.state().modify(|w| w.set_state_l(0));
221 // Remove halt and start the actual counter
222 SCT0.ctrl().modify(|w| {
223 w.set_halt_l(!config.enable);
224 });
225 }
226
227 /// Read PWM counter.
228 #[inline]
229 pub fn counter(&self) -> u32 {
230 SCT0.count().read().0
231 }
232}
233
234impl<'d> Drop for Pwm<'d> {
235 fn drop(&mut self) {
236 REF_COUNT.fetch_sub(1, Ordering::AcqRel);
237 if REF_COUNT.load(Ordering::Acquire) == 0 {
238 TOP_VALUE.store(0, Ordering::Release);
239 }
240 }
241}
242
243trait SealedOutput {
244 /// Output number.
245 fn number(&self) -> usize;
246}
247
248/// PWM Output.
249#[allow(private_bounds)]
250pub trait Output: PeripheralType + SealedOutput {}
251
252macro_rules! output {
253 ($name:ident, $num:expr) => {
254 impl SealedOutput for crate::peripherals::$name {
255 fn number(&self) -> usize {
256 $num
257 }
258 }
259 impl Output for crate::peripherals::$name {}
260 };
261}
262
263output!(PWM_OUTPUT0, 0);
264output!(PWM_OUTPUT1, 1);
265output!(PWM_OUTPUT2, 2);
266output!(PWM_OUTPUT3, 3);
267output!(PWM_OUTPUT4, 4);
268output!(PWM_OUTPUT5, 5);
269output!(PWM_OUTPUT6, 6);
270output!(PWM_OUTPUT7, 7);
271output!(PWM_OUTPUT8, 8);
272output!(PWM_OUTPUT9, 9);
273
274/// PWM Output Channel.
275pub trait OutputChannelPin<T: Output>: crate::gpio::Pin {
276 fn pin_func(&self) -> PioFunc;
277}
278
279macro_rules! impl_pin {
280 ($pin:ident, $output:ident, $func:ident) => {
281 impl crate::pwm::inner::OutputChannelPin<crate::peripherals::$output> for crate::peripherals::$pin {
282 fn pin_func(&self) -> PioFunc {
283 PioFunc::$func
284 }
285 }
286 };
287}
288
289impl_pin!(PIO0_2, PWM_OUTPUT0, ALT3);
290impl_pin!(PIO0_17, PWM_OUTPUT0, ALT4);
291impl_pin!(PIO1_4, PWM_OUTPUT0, ALT4);
292impl_pin!(PIO1_23, PWM_OUTPUT0, ALT2);
293
294impl_pin!(PIO0_3, PWM_OUTPUT1, ALT3);
295impl_pin!(PIO0_18, PWM_OUTPUT1, ALT4);
296impl_pin!(PIO1_8, PWM_OUTPUT1, ALT4);
297impl_pin!(PIO1_24, PWM_OUTPUT1, ALT2);
298
299impl_pin!(PIO0_10, PWM_OUTPUT2, ALT5);
300impl_pin!(PIO0_15, PWM_OUTPUT2, ALT4);
301impl_pin!(PIO0_19, PWM_OUTPUT2, ALT4);
302impl_pin!(PIO1_9, PWM_OUTPUT2, ALT4);
303impl_pin!(PIO1_25, PWM_OUTPUT2, ALT2);
304
305impl_pin!(PIO0_22, PWM_OUTPUT3, ALT4);
306impl_pin!(PIO0_31, PWM_OUTPUT3, ALT4);
307impl_pin!(PIO1_10, PWM_OUTPUT3, ALT4);
308impl_pin!(PIO1_26, PWM_OUTPUT3, ALT2);
309
310impl_pin!(PIO0_23, PWM_OUTPUT4, ALT4);
311impl_pin!(PIO1_3, PWM_OUTPUT4, ALT4);
312impl_pin!(PIO1_17, PWM_OUTPUT4, ALT4);
313
314impl_pin!(PIO0_26, PWM_OUTPUT5, ALT4);
315impl_pin!(PIO1_18, PWM_OUTPUT5, ALT4);
316
317impl_pin!(PIO0_27, PWM_OUTPUT6, ALT4);
318impl_pin!(PIO1_31, PWM_OUTPUT6, ALT4);
319
320impl_pin!(PIO0_28, PWM_OUTPUT7, ALT4);
321impl_pin!(PIO1_19, PWM_OUTPUT7, ALT2);
322
323impl_pin!(PIO0_29, PWM_OUTPUT8, ALT4);
324
325impl_pin!(PIO0_30, PWM_OUTPUT9, ALT4);
diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs
index 0be5a8ce7..d54927b25 100644
--- a/embassy-nxp/src/usart/lpc55.rs
+++ b/embassy-nxp/src/usart/lpc55.rs
@@ -11,7 +11,7 @@ use embassy_sync::waitqueue::AtomicWaker;
11use embedded_io::{self, ErrorKind}; 11use embedded_io::{self, ErrorKind};
12 12
13use crate::dma::{AnyChannel, Channel}; 13use crate::dma::{AnyChannel, Channel};
14use crate::gpio::{AnyPin, Bank, SealedPin, match_iocon}; 14use crate::gpio::{AnyPin, SealedPin};
15use crate::interrupt::Interrupt; 15use crate::interrupt::Interrupt;
16use crate::interrupt::typelevel::{Binding, Interrupt as _}; 16use crate::interrupt::typelevel::{Binding, Interrupt as _};
17use crate::pac::flexcomm::Flexcomm as FlexcommReg; 17use crate::pac::flexcomm::Flexcomm as FlexcommReg;
@@ -146,7 +146,8 @@ impl<'d, M: Mode> UsartTx<'d, M> {
146 tx_dma: Peri<'d, impl Channel>, 146 tx_dma: Peri<'d, impl Channel>,
147 config: Config, 147 config: Config,
148 ) -> Self { 148 ) -> Self {
149 Usart::<M>::init::<T>(Some(tx.into()), None, config); 149 let tx_func = tx.pin_func();
150 Usart::<M>::init::<T>(Some((tx.into(), tx_func)), None, config);
150 Self::new_inner(T::info(), Some(tx_dma.into())) 151 Self::new_inner(T::info(), Some(tx_dma.into()))
151 } 152 }
152 153
@@ -179,7 +180,8 @@ impl<'d, M: Mode> UsartTx<'d, M> {
179 180
180impl<'d> UsartTx<'d, Blocking> { 181impl<'d> UsartTx<'d, Blocking> {
181 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { 182 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
182 Usart::<Blocking>::init::<T>(Some(tx.into()), None, config); 183 let tx_func = tx.pin_func();
184 Usart::<Blocking>::init::<T>(Some((tx.into(), tx_func)), None, config);
183 Self::new_inner(T::info(), None) 185 Self::new_inner(T::info(), None)
184 } 186 }
185} 187}
@@ -208,7 +210,8 @@ impl<'d, M: Mode> UsartRx<'d, M> {
208 rx_dma: Peri<'d, impl Channel>, 210 rx_dma: Peri<'d, impl Channel>,
209 config: Config, 211 config: Config,
210 ) -> Self { 212 ) -> Self {
211 Usart::<M>::init::<T>(None, Some(rx.into()), config); 213 let rx_func = rx.pin_func();
214 Usart::<M>::init::<T>(None, Some((rx.into(), rx_func)), config);
212 Self::new_inner(T::info(), T::dma_state(), has_irq, Some(rx_dma.into())) 215 Self::new_inner(T::info(), T::dma_state(), has_irq, Some(rx_dma.into()))
213 } 216 }
214 217
@@ -280,7 +283,8 @@ impl<'d, M: Mode> UsartRx<'d, M> {
280 283
281impl<'d> UsartRx<'d, Blocking> { 284impl<'d> UsartRx<'d, Blocking> {
282 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { 285 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
283 Usart::<Blocking>::init::<T>(None, Some(rx.into()), config); 286 let rx_func = rx.pin_func();
287 Usart::<Blocking>::init::<T>(None, Some((rx.into(), rx_func)), config);
284 Self::new_inner(T::info(), T::dma_state(), false, None) 288 Self::new_inner(T::info(), T::dma_state(), false, None)
285 } 289 }
286} 290}
@@ -405,7 +409,10 @@ impl<'d> Usart<'d, Blocking> {
405 rx: Peri<'d, impl RxPin<T>>, 409 rx: Peri<'d, impl RxPin<T>>,
406 config: Config, 410 config: Config,
407 ) -> Self { 411 ) -> Self {
408 Self::new_inner(usart, tx.into(), rx.into(), false, None, None, config) 412 let tx_func = tx.pin_func();
413 let rx_func = rx.pin_func();
414
415 Self::new_inner(usart, tx.into(), tx_func, rx.into(), rx_func, false, None, None, config)
409 } 416 }
410} 417}
411 418
@@ -419,10 +426,15 @@ impl<'d> Usart<'d, Async> {
419 rx_dma: Peri<'d, impl RxChannel<T>>, 426 rx_dma: Peri<'d, impl RxChannel<T>>,
420 config: Config, 427 config: Config,
421 ) -> Self { 428 ) -> Self {
429 let tx_func = tx.pin_func();
430 let rx_func = rx.pin_func();
431
422 Self::new_inner( 432 Self::new_inner(
423 uart, 433 uart,
424 tx.into(), 434 tx.into(),
435 tx_func,
425 rx.into(), 436 rx.into(),
437 rx_func,
426 true, 438 true,
427 Some(tx_dma.into()), 439 Some(tx_dma.into()),
428 Some(rx_dma.into()), 440 Some(rx_dma.into()),
@@ -435,20 +447,26 @@ impl<'d, M: Mode> Usart<'d, M> {
435 fn new_inner<T: Instance>( 447 fn new_inner<T: Instance>(
436 _usart: Peri<'d, T>, 448 _usart: Peri<'d, T>,
437 mut tx: Peri<'d, AnyPin>, 449 mut tx: Peri<'d, AnyPin>,
450 tx_func: PioFunc,
438 mut rx: Peri<'d, AnyPin>, 451 mut rx: Peri<'d, AnyPin>,
452 rx_func: PioFunc,
439 has_irq: bool, 453 has_irq: bool,
440 tx_dma: Option<Peri<'d, AnyChannel>>, 454 tx_dma: Option<Peri<'d, AnyChannel>>,
441 rx_dma: Option<Peri<'d, AnyChannel>>, 455 rx_dma: Option<Peri<'d, AnyChannel>>,
442 config: Config, 456 config: Config,
443 ) -> Self { 457 ) -> Self {
444 Self::init::<T>(Some(tx.reborrow()), Some(rx.reborrow()), config); 458 Self::init::<T>(Some((tx.reborrow(), tx_func)), Some((rx.reborrow(), rx_func)), config);
445 Self { 459 Self {
446 tx: UsartTx::new_inner(T::info(), tx_dma), 460 tx: UsartTx::new_inner(T::info(), tx_dma),
447 rx: UsartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma), 461 rx: UsartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma),
448 } 462 }
449 } 463 }
450 464
451 fn init<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>, config: Config) { 465 fn init<T: Instance>(
466 tx: Option<(Peri<'_, AnyPin>, PioFunc)>,
467 rx: Option<(Peri<'_, AnyPin>, PioFunc)>,
468 config: Config,
469 ) {
452 Self::configure_flexcomm(T::info().fc_reg, T::instance_number()); 470 Self::configure_flexcomm(T::info().fc_reg, T::instance_number());
453 Self::configure_clock::<T>(&config); 471 Self::configure_clock::<T>(&config);
454 Self::pin_config::<T>(tx, rx); 472 Self::pin_config::<T>(tx, rx);
@@ -553,31 +571,27 @@ impl<'d, M: Mode> Usart<'d, M> {
553 .modify(|w| w.set_brgval((brg_value - 1) as u16)); 571 .modify(|w| w.set_brgval((brg_value - 1) as u16));
554 } 572 }
555 573
556 fn pin_config<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>) { 574 fn pin_config<T: Instance>(tx: Option<(Peri<'_, AnyPin>, PioFunc)>, rx: Option<(Peri<'_, AnyPin>, PioFunc)>) {
557 if let Some(tx_pin) = tx { 575 if let Some((tx_pin, func)) = tx {
558 match_iocon!(register, tx_pin.pin_bank(), tx_pin.pin_number(), { 576 tx_pin.pio().modify(|w| {
559 register.modify(|w| { 577 w.set_func(func);
560 w.set_func(T::tx_pin_func()); 578 w.set_mode(iocon::vals::PioMode::INACTIVE);
561 w.set_mode(iocon::vals::PioMode::INACTIVE); 579 w.set_slew(iocon::vals::PioSlew::STANDARD);
562 w.set_slew(iocon::vals::PioSlew::STANDARD); 580 w.set_invert(false);
563 w.set_invert(false); 581 w.set_digimode(iocon::vals::PioDigimode::DIGITAL);
564 w.set_digimode(iocon::vals::PioDigimode::DIGITAL); 582 w.set_od(iocon::vals::PioOd::NORMAL);
565 w.set_od(iocon::vals::PioOd::NORMAL); 583 });
566 });
567 })
568 } 584 }
569 585
570 if let Some(rx_pin) = rx { 586 if let Some((rx_pin, func)) = rx {
571 match_iocon!(register, rx_pin.pin_bank(), rx_pin.pin_number(), { 587 rx_pin.pio().modify(|w| {
572 register.modify(|w| { 588 w.set_func(func);
573 w.set_func(T::rx_pin_func()); 589 w.set_mode(iocon::vals::PioMode::INACTIVE);
574 w.set_mode(iocon::vals::PioMode::INACTIVE); 590 w.set_slew(iocon::vals::PioSlew::STANDARD);
575 w.set_slew(iocon::vals::PioSlew::STANDARD); 591 w.set_invert(false);
576 w.set_invert(false); 592 w.set_digimode(iocon::vals::PioDigimode::DIGITAL);
577 w.set_digimode(iocon::vals::PioDigimode::DIGITAL); 593 w.set_od(iocon::vals::PioOd::NORMAL);
578 w.set_od(iocon::vals::PioOd::NORMAL); 594 });
579 });
580 })
581 }; 595 };
582 } 596 }
583 597
@@ -814,8 +828,6 @@ trait SealedInstance {
814 fn info() -> &'static Info; 828 fn info() -> &'static Info;
815 fn dma_state() -> &'static DmaState; 829 fn dma_state() -> &'static DmaState;
816 fn instance_number() -> usize; 830 fn instance_number() -> usize;
817 fn tx_pin_func() -> PioFunc;
818 fn rx_pin_func() -> PioFunc;
819} 831}
820 832
821/// UART instance. 833/// UART instance.
@@ -826,7 +838,7 @@ pub trait Instance: SealedInstance + PeripheralType {
826} 838}
827 839
828macro_rules! impl_instance { 840macro_rules! impl_instance {
829 ($inst:ident, $fc:ident, $tx_pin:ident, $rx_pin:ident, $fc_num:expr) => { 841 ($inst:ident, $fc:ident, $fc_num:expr) => {
830 impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst { 842 impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst {
831 fn info() -> &'static Info { 843 fn info() -> &'static Info {
832 static INFO: Info = Info { 844 static INFO: Info = Info {
@@ -848,14 +860,6 @@ macro_rules! impl_instance {
848 fn instance_number() -> usize { 860 fn instance_number() -> usize {
849 $fc_num 861 $fc_num
850 } 862 }
851 #[inline]
852 fn tx_pin_func() -> PioFunc {
853 PioFunc::$tx_pin
854 }
855 #[inline]
856 fn rx_pin_func() -> PioFunc {
857 PioFunc::$rx_pin
858 }
859 } 863 }
860 impl $crate::usart::Instance for $crate::peripherals::$inst { 864 impl $crate::usart::Instance for $crate::peripherals::$inst {
861 type Interrupt = crate::interrupt::typelevel::$fc; 865 type Interrupt = crate::interrupt::typelevel::$fc;
@@ -863,45 +867,72 @@ macro_rules! impl_instance {
863 }; 867 };
864} 868}
865 869
866impl_instance!(USART0, FLEXCOMM0, ALT1, ALT1, 0); 870impl_instance!(USART0, FLEXCOMM0, 0);
867impl_instance!(USART1, FLEXCOMM1, ALT2, ALT2, 1); 871impl_instance!(USART1, FLEXCOMM1, 1);
868impl_instance!(USART2, FLEXCOMM2, ALT1, ALT1, 2); 872impl_instance!(USART2, FLEXCOMM2, 2);
869impl_instance!(USART3, FLEXCOMM3, ALT1, ALT1, 3); 873impl_instance!(USART3, FLEXCOMM3, 3);
870impl_instance!(USART4, FLEXCOMM4, ALT1, ALT2, 4); 874impl_instance!(USART4, FLEXCOMM4, 4);
871impl_instance!(USART5, FLEXCOMM5, ALT3, ALT3, 5); 875impl_instance!(USART5, FLEXCOMM5, 5);
872impl_instance!(USART6, FLEXCOMM6, ALT2, ALT2, 6); 876impl_instance!(USART6, FLEXCOMM6, 6);
873impl_instance!(USART7, FLEXCOMM7, ALT7, ALT7, 7); 877impl_instance!(USART7, FLEXCOMM7, 7);
878
879pub(crate) trait SealedTxPin<T: Instance>: crate::gpio::Pin {
880 fn pin_func(&self) -> PioFunc;
881}
882
883pub(crate) trait SealedRxPin<T: Instance>: crate::gpio::Pin {
884 fn pin_func(&self) -> PioFunc;
885}
874 886
875/// Trait for TX pins. 887/// Trait for TX pins.
876pub trait TxPin<T: Instance>: crate::gpio::Pin {} 888#[allow(private_bounds)]
889pub trait TxPin<T: Instance>: SealedTxPin<T> + crate::gpio::Pin {}
890
877/// Trait for RX pins. 891/// Trait for RX pins.
878pub trait RxPin<T: Instance>: crate::gpio::Pin {} 892#[allow(private_bounds)]
893pub trait RxPin<T: Instance>: SealedRxPin<T> + crate::gpio::Pin {}
894
895macro_rules! impl_tx_pin {
896 ($pin:ident, $instance:ident, $func: ident) => {
897 impl SealedTxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
898 fn pin_func(&self) -> PioFunc {
899 PioFunc::$func
900 }
901 }
879 902
880macro_rules! impl_pin {
881 ($pin:ident, $instance:ident, Tx) => {
882 impl TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {} 903 impl TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
883 }; 904 };
884 ($pin:ident, $instance:ident, Rx) => { 905}
906
907macro_rules! impl_rx_pin {
908 ($pin:ident, $instance:ident, $func: ident) => {
909 impl SealedRxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
910 fn pin_func(&self) -> PioFunc {
911 PioFunc::$func
912 }
913 }
914
885 impl RxPin<crate::peripherals::$instance> for crate::peripherals::$pin {} 915 impl RxPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
886 }; 916 };
887} 917}
888 918
889impl_pin!(PIO1_6, USART0, Tx); 919impl_tx_pin!(PIO1_6, USART0, ALT1);
890impl_pin!(PIO1_5, USART0, Rx); 920impl_tx_pin!(PIO1_11, USART1, ALT2);
891impl_pin!(PIO1_11, USART1, Tx); 921impl_tx_pin!(PIO0_27, USART2, ALT1);
892impl_pin!(PIO1_10, USART1, Rx); 922impl_tx_pin!(PIO0_2, USART3, ALT1);
893impl_pin!(PIO0_27, USART2, Tx); 923impl_tx_pin!(PIO0_16, USART4, ALT1);
894impl_pin!(PIO1_24, USART2, Rx); 924impl_tx_pin!(PIO0_9, USART5, ALT3);
895impl_pin!(PIO0_2, USART3, Tx); 925impl_tx_pin!(PIO1_16, USART6, ALT2);
896impl_pin!(PIO0_3, USART3, Rx); 926impl_tx_pin!(PIO0_19, USART7, ALT7);
897impl_pin!(PIO0_16, USART4, Tx); 927
898impl_pin!(PIO0_5, USART4, Rx); 928impl_rx_pin!(PIO1_5, USART0, ALT1);
899impl_pin!(PIO0_9, USART5, Tx); 929impl_rx_pin!(PIO1_10, USART1, ALT2);
900impl_pin!(PIO0_8, USART5, Rx); 930impl_rx_pin!(PIO1_24, USART2, ALT1);
901impl_pin!(PIO1_16, USART6, Tx); 931impl_rx_pin!(PIO0_3, USART3, ALT1);
902impl_pin!(PIO1_13, USART6, Rx); 932impl_rx_pin!(PIO0_5, USART4, ALT2);
903impl_pin!(PIO0_19, USART7, Tx); 933impl_rx_pin!(PIO0_8, USART5, ALT3);
904impl_pin!(PIO0_20, USART7, Rx); 934impl_rx_pin!(PIO1_13, USART6, ALT2);
935impl_rx_pin!(PIO0_20, USART7, ALT7);
905 936
906/// Trait for TX DMA channels. 937/// Trait for TX DMA channels.
907pub trait TxChannel<T: Instance>: crate::dma::Channel {} 938pub trait TxChannel<T: Instance>: crate::dma::Channel {}
diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md
index e932bcaa3..3b3cb5351 100644
--- a/embassy-rp/CHANGELOG.md
+++ b/embassy-rp/CHANGELOG.md
@@ -8,12 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Fix several minor typos in documentation
11- Add PIO SPI 12- Add PIO SPI
12- Add PIO I2S input 13- Add PIO I2S input
13- Add PIO onewire parasite power strong pullup 14- Add PIO onewire parasite power strong pullup
14- add `wait_for_alarm` and `alarm_scheduled` methods to rtc module ([#4216](https://github.com/embassy-rs/embassy/pull/4216)) 15- add `wait_for_alarm` and `alarm_scheduled` methods to rtc module ([#4216](https://github.com/embassy-rs/embassy/pull/4216))
15- rp235x: use msplim for stack guard instead of MPU 16- rp235x: use msplim for stack guard instead of MPU
16- Add reset_to_usb_boot for rp235x ([#4705](https://github.com/embassy-rs/embassy/pull/4705)) 17- Add reset_to_usb_boot for rp235x ([#4705](https://github.com/embassy-rs/embassy/pull/4705))
18- Add fix #4822 in PIO onewire. Change to disable the state machine before setting y register ([#4824](https://github.com/embassy-rs/embassy/pull/4824))
19- Add PIO::Ws2812 color order support
17 20
18## 0.8.0 - 2025-08-26 21## 0.8.0 - 2025-08-26
19 22
diff --git a/embassy-rp/src/block.rs b/embassy-rp/src/block.rs
index a3e1ad925..745883b83 100644
--- a/embassy-rp/src/block.rs
+++ b/embassy-rp/src/block.rs
@@ -240,7 +240,7 @@ impl UnpartitionedSpace {
240 } 240 }
241 } 241 }
242 242
243 /// Create a new unpartition space from run-time values. 243 /// Create a new unpartitioned space from run-time values.
244 /// 244 ///
245 /// Get these from the ROM function `get_partition_table_info` with an argument of `PT_INFO`. 245 /// Get these from the ROM function `get_partition_table_info` with an argument of `PT_INFO`.
246 pub const fn from_raw(permissions_and_location: u32, permissions_and_flags: u32) -> Self { 246 pub const fn from_raw(permissions_and_location: u32, permissions_and_flags: u32) -> Self {
@@ -714,7 +714,7 @@ impl PartitionTableBlock {
714 new_table 714 new_table
715 } 715 }
716 716
717 /// Add a a SHA256 hash of the Block 717 /// Add a SHA256 hash of the Block
718 /// 718 ///
719 /// Adds a `HASH_DEF` covering all the previous items in the Block, and a 719 /// Adds a `HASH_DEF` covering all the previous items in the Block, and a
720 /// `HASH_VALUE` with a SHA-256 hash of them. 720 /// `HASH_VALUE` with a SHA-256 hash of them.
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 56892d7a2..8bfb5129a 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -267,7 +267,7 @@ impl CoreVoltage {
267 } 267 }
268} 268}
269 269
270/// CLock configuration. 270/// Clock configuration.
271#[non_exhaustive] 271#[non_exhaustive]
272pub struct ClockConfig { 272pub struct ClockConfig {
273 /// Ring oscillator configuration. 273 /// Ring oscillator configuration.
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index c15e0e41b..154fc1585 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -300,7 +300,7 @@ impl<'d> InputFuture<'d> {
300 300
301 // Each INTR register is divided into 8 groups, one group for each 301 // Each INTR register is divided into 8 groups, one group for each
302 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, 302 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,
303 // and EGDE_HIGH. 303 // and EDGE_HIGH.
304 pin.int_proc() 304 pin.int_proc()
305 .inte((pin.pin() / 8) as usize) 305 .inte((pin.pin() / 8) as usize)
306 .write_set(|w| match level { 306 .write_set(|w| match level {
diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs
index 770087bc8..0853709df 100644
--- a/embassy-rp/src/i2c_slave.rs
+++ b/embassy-rp/src/i2c_slave.rs
@@ -52,7 +52,7 @@ pub enum ReadStatus {
52 Done, 52 Done,
53 /// Transaction Incomplete, controller trying to read more bytes than were provided 53 /// Transaction Incomplete, controller trying to read more bytes than were provided
54 NeedMoreBytes, 54 NeedMoreBytes,
55 /// Transaction Complere, but controller stopped reading bytes before we ran out 55 /// Transaction Complete, but controller stopped reading bytes before we ran out
56 LeftoverBytes(u16), 56 LeftoverBytes(u16),
57} 57}
58 58
@@ -240,7 +240,7 @@ impl<'d, T: Instance> I2cSlave<'d, T> {
240 240
241 if p.ic_rxflr().read().rxflr() > 0 || me.pending_byte.is_some() { 241 if p.ic_rxflr().read().rxflr() > 0 || me.pending_byte.is_some() {
242 me.drain_fifo(buffer, &mut len); 242 me.drain_fifo(buffer, &mut len);
243 // we're recieving data, set rx fifo watermark to 12 bytes (3/4 full) to reduce interrupt noise 243 // we're receiving data, set rx fifo watermark to 12 bytes (3/4 full) to reduce interrupt noise
244 p.ic_rx_tl().write(|w| w.set_rx_tl(11)); 244 p.ic_rx_tl().write(|w| w.set_rx_tl(11));
245 } 245 }
246 246
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index 3b120e349..572d8db91 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -58,7 +58,7 @@ const PAUSE_TOKEN: u32 = 0xDEADBEEF;
58const RESUME_TOKEN: u32 = !0xDEADBEEF; 58const RESUME_TOKEN: u32 = !0xDEADBEEF;
59static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false); 59static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false);
60 60
61/// Represents a partiticular CPU core (SIO_CPUID) 61/// Represents a particular CPU core (SIO_CPUID)
62#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] 62#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))] 63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64#[repr(u8)] 64#[repr(u8)]
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index 38ee1f97c..92b2c603e 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -62,7 +62,7 @@ pub enum FifoJoin {
62 #[cfg(feature = "_rp235x")] 62 #[cfg(feature = "_rp235x")]
63 RxAsControl, 63 RxAsControl,
64 /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register, 64 /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register,
65 /// not accesible from the CPU 65 /// not accessible from the CPU
66 #[cfg(feature = "_rp235x")] 66 #[cfg(feature = "_rp235x")]
67 PioScratch, 67 PioScratch,
68} 68}
diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs
index 7e5f68ad6..5c49beecb 100644
--- a/embassy-rp/src/pio_programs/i2s.rs
+++ b/embassy-rp/src/pio_programs/i2s.rs
@@ -1,4 +1,4 @@
1//! Pio backed I2s output and output drivers 1//! Pio backed I2S output and output drivers
2 2
3use fixed::traits::ToFixed; 3use fixed::traits::ToFixed;
4 4
@@ -9,7 +9,7 @@ use crate::pio::{
9 Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, 9 Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
10}; 10};
11 11
12/// This struct represents an i2s receiver & controller driver program 12/// This struct represents an I2S receiver & controller driver program
13pub struct PioI2sInProgram<'d, PIO: Instance> { 13pub struct PioI2sInProgram<'d, PIO: Instance> {
14 prg: LoadedProgram<'d, PIO>, 14 prg: LoadedProgram<'d, PIO>,
15} 15}
@@ -35,7 +35,7 @@ impl<'d, PIO: Instance> PioI2sInProgram<'d, PIO> {
35 } 35 }
36} 36}
37 37
38/// Pio backed I2s input driver 38/// Pio backed I2S input driver
39pub struct PioI2sIn<'d, P: Instance, const S: usize> { 39pub struct PioI2sIn<'d, P: Instance, const S: usize> {
40 dma: Peri<'d, AnyChannel>, 40 dma: Peri<'d, AnyChannel>,
41 sm: StateMachine<'d, P, S>, 41 sm: StateMachine<'d, P, S>,
@@ -50,7 +50,7 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> {
50 // Whether or not to use the MCU's internal pull-down resistor, as the 50 // Whether or not to use the MCU's internal pull-down resistor, as the
51 // Pico 2 is known to have problems with the inbuilt pulldowns, many 51 // Pico 2 is known to have problems with the inbuilt pulldowns, many
52 // opt to just use an external pull down resistor to meet requirements of common 52 // opt to just use an external pull down resistor to meet requirements of common
53 // i2s microphones such as the INMP441 53 // I2S microphones such as the INMP441
54 data_pulldown: bool, 54 data_pulldown: bool,
55 data_pin: Peri<'d, impl PioPin>, 55 data_pin: Peri<'d, impl PioPin>,
56 bit_clock_pin: Peri<'d, impl PioPin>, 56 bit_clock_pin: Peri<'d, impl PioPin>,
@@ -90,13 +90,13 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> {
90 Self { dma: dma.into(), sm } 90 Self { dma: dma.into(), sm }
91 } 91 }
92 92
93 /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. 93 /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer.
94 pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> { 94 pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> {
95 self.sm.rx().dma_pull(self.dma.reborrow(), buff, false) 95 self.sm.rx().dma_pull(self.dma.reborrow(), buff, false)
96 } 96 }
97} 97}
98 98
99/// This struct represents an i2s output driver program 99/// This struct represents an I2S output driver program
100/// 100///
101/// The sample bit-depth is set through scratch register `Y`. 101/// The sample bit-depth is set through scratch register `Y`.
102/// `Y` has to be set to sample bit-depth - 2. 102/// `Y` has to be set to sample bit-depth - 2.
@@ -128,14 +128,14 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> {
128 } 128 }
129} 129}
130 130
131/// Pio backed I2s output driver 131/// Pio backed I2S output driver
132pub struct PioI2sOut<'d, P: Instance, const S: usize> { 132pub struct PioI2sOut<'d, P: Instance, const S: usize> {
133 dma: Peri<'d, AnyChannel>, 133 dma: Peri<'d, AnyChannel>,
134 sm: StateMachine<'d, P, S>, 134 sm: StateMachine<'d, P, S>,
135} 135}
136 136
137impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { 137impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
138 /// Configure a state machine to output I2s 138 /// Configure a state machine to output I2S
139 pub fn new( 139 pub fn new(
140 common: &mut Common<'d, P>, 140 common: &mut Common<'d, P>,
141 mut sm: StateMachine<'d, P, S>, 141 mut sm: StateMachine<'d, P, S>,
@@ -179,7 +179,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
179 Self { dma: dma.into(), sm } 179 Self { dma: dma.into(), sm }
180 } 180 }
181 181
182 /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. 182 /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer.
183 pub fn write<'b>(&'b mut self, buff: &'b [u32]) -> Transfer<'b, AnyChannel> { 183 pub fn write<'b>(&'b mut self, buff: &'b [u32]) -> Transfer<'b, AnyChannel> {
184 self.sm.tx().dma_push(self.dma.reborrow(), buff, false) 184 self.sm.tx().dma_push(self.dma.reborrow(), buff, false)
185 } 185 }
diff --git a/embassy-rp/src/pio_programs/onewire.rs b/embassy-rp/src/pio_programs/onewire.rs
index 09babc229..3adab3b79 100644
--- a/embassy-rp/src/pio_programs/onewire.rs
+++ b/embassy-rp/src/pio_programs/onewire.rs
@@ -163,7 +163,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
163 163
164 /// Write bytes to the onewire bus 164 /// Write bytes to the onewire bus
165 pub async fn write_bytes(&mut self, data: &[u8]) { 165 pub async fn write_bytes(&mut self, data: &[u8]) {
166 unsafe { self.sm.set_y(u32::MAX as u32) }; 166 unsafe {
167 self.sm.set_enable(false);
168 self.sm.set_y(u32::MAX as u32);
169 self.sm.set_enable(true);
170 }
167 let (rx, tx) = self.sm.rx_tx(); 171 let (rx, tx) = self.sm.rx_tx();
168 for b in data { 172 for b in data {
169 tx.wait_push(*b as u32).await; 173 tx.wait_push(*b as u32).await;
@@ -175,7 +179,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
175 179
176 /// Write bytes to the onewire bus, then apply a strong pullup 180 /// Write bytes to the onewire bus, then apply a strong pullup
177 pub async fn write_bytes_pullup(&mut self, data: &[u8], pullup_time: embassy_time::Duration) { 181 pub async fn write_bytes_pullup(&mut self, data: &[u8], pullup_time: embassy_time::Duration) {
178 unsafe { self.sm.set_y(data.len() as u32 * 8 - 1) }; 182 unsafe {
183 self.sm.set_enable(false);
184 self.sm.set_y(data.len() as u32 * 8 - 1);
185 self.sm.set_enable(true);
186 };
179 let (rx, tx) = self.sm.rx_tx(); 187 let (rx, tx) = self.sm.rx_tx();
180 for b in data { 188 for b in data {
181 tx.wait_push(*b as u32).await; 189 tx.wait_push(*b as u32).await;
@@ -195,7 +203,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
195 203
196 /// Read bytes from the onewire bus 204 /// Read bytes from the onewire bus
197 pub async fn read_bytes(&mut self, data: &mut [u8]) { 205 pub async fn read_bytes(&mut self, data: &mut [u8]) {
198 unsafe { self.sm.set_y(u32::MAX as u32) }; 206 unsafe {
207 self.sm.set_enable(false);
208 self.sm.set_y(u32::MAX as u32);
209 self.sm.set_enable(true);
210 };
199 let (rx, tx) = self.sm.rx_tx(); 211 let (rx, tx) = self.sm.rx_tx();
200 for b in data { 212 for b in data {
201 // Write all 1's so that we can read what the device responds 213 // Write all 1's so that we can read what the device responds
diff --git a/embassy-rp/src/pio_programs/pwm.rs b/embassy-rp/src/pio_programs/pwm.rs
index ba06bb3c1..e4ad4a6f0 100644
--- a/embassy-rp/src/pio_programs/pwm.rs
+++ b/embassy-rp/src/pio_programs/pwm.rs
@@ -67,7 +67,7 @@ impl<'d, T: Instance, const SM: usize> PioPwm<'d, T, SM> {
67 Self { sm, pin } 67 Self { sm, pin }
68 } 68 }
69 69
70 /// Enable's the PIO program, continuing the wave generation from the PIO program. 70 /// Enables the PIO program, continuing the wave generation from the PIO program.
71 pub fn start(&mut self) { 71 pub fn start(&mut self) {
72 self.sm.set_enable(true); 72 self.sm.set_enable(true);
73 } 73 }
diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs
index b10fc6628..765ffaa06 100644
--- a/embassy-rp/src/pio_programs/spi.rs
+++ b/embassy-rp/src/pio_programs/spi.rs
@@ -1,4 +1,4 @@
1//! PIO backed SPi drivers 1//! PIO backed SPI drivers
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
@@ -83,7 +83,7 @@ pub enum Error {
83 // No errors for now 83 // No errors for now
84} 84}
85 85
86/// PIO based Spi driver. 86/// PIO based SPI driver.
87/// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to 87/// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to
88/// the PIO memory it uses. This is so that it can be reconfigured at runtime if 88/// the PIO memory it uses. This is so that it can be reconfigured at runtime if
89/// desired. 89/// desired.
diff --git a/embassy-rp/src/pio_programs/uart.rs b/embassy-rp/src/pio_programs/uart.rs
index 444efb5db..d59596dd1 100644
--- a/embassy-rp/src/pio_programs/uart.rs
+++ b/embassy-rp/src/pio_programs/uart.rs
@@ -130,7 +130,7 @@ impl<'d, PIO: Instance> PioUartRxProgram<'d, PIO> {
130 } 130 }
131} 131}
132 132
133/// PIO backed Uart reciever 133/// PIO backed Uart receiver
134pub struct PioUartRx<'d, PIO: Instance, const SM: usize> { 134pub struct PioUartRx<'d, PIO: Instance, const SM: usize> {
135 sm_rx: StateMachine<'d, PIO, SM>, 135 sm_rx: StateMachine<'d, PIO, SM>,
136} 136}
diff --git a/embassy-rp/src/pio_programs/ws2812.rs b/embassy-rp/src/pio_programs/ws2812.rs
index e6851b1a6..0b6035316 100644
--- a/embassy-rp/src/pio_programs/ws2812.rs
+++ b/embassy-rp/src/pio_programs/ws2812.rs
@@ -1,4 +1,4 @@
1//! [ws2812](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) 1//! [ws2812](https://www.sparkfun.com/categories/tags/ws2812)
2 2
3use embassy_time::Timer; 3use embassy_time::Timer;
4use fixed::types::U24F8; 4use fixed::types::U24F8;
@@ -16,6 +16,54 @@ const T2: u8 = 5; // data bit
16const T3: u8 = 3; // stop bit 16const T3: u8 = 3; // stop bit
17const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; 17const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32;
18 18
19/// Color orders for WS2812B, type RGB8
20pub trait RgbColorOrder {
21 /// Pack an 8-bit RGB color into a u32
22 fn pack(color: RGB8) -> u32;
23}
24
25/// Green, Red, Blue order is the common default for WS2812B
26pub struct Grb;
27impl RgbColorOrder for Grb {
28 /// Pack an 8-bit RGB color into a u32 in GRB order
29 fn pack(color: RGB8) -> u32 {
30 (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8)
31 }
32}
33
34/// Red, Green, Blue is used by some WS2812B implementations
35pub struct Rgb;
36impl RgbColorOrder for Rgb {
37 /// Pack an 8-bit RGB color into a u32 in RGB order
38 fn pack(color: RGB8) -> u32 {
39 (u32::from(color.r) << 24) | (u32::from(color.g) << 16) | (u32::from(color.b) << 8)
40 }
41}
42
43/// Color orders RGBW strips
44pub trait RgbwColorOrder {
45 /// Pack an RGB+W color into a u32
46 fn pack(color: RGBW<u8>) -> u32;
47}
48
49/// Green, Red, Blue, White order is the common default for RGBW strips
50pub struct Grbw;
51impl RgbwColorOrder for Grbw {
52 /// Pack an RGB+W color into a u32 in GRBW order
53 fn pack(color: RGBW<u8>) -> u32 {
54 (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8) | u32::from(color.a.0)
55 }
56}
57
58/// Red, Green, Blue, White order
59pub struct Rgbw;
60impl RgbwColorOrder for Rgbw {
61 /// Pack an RGB+W color into a u32 in RGBW order
62 fn pack(color: RGBW<u8>) -> u32 {
63 (u32::from(color.r) << 24) | (u32::from(color.g) << 16) | (u32::from(color.b) << 8) | u32::from(color.a.0)
64 }
65}
66
19/// This struct represents a ws2812 program loaded into pio instruction memory. 67/// This struct represents a ws2812 program loaded into pio instruction memory.
20pub struct PioWs2812Program<'a, PIO: Instance> { 68pub struct PioWs2812Program<'a, PIO: Instance> {
21 prg: LoadedProgram<'a, PIO>, 69 prg: LoadedProgram<'a, PIO>,
@@ -52,15 +100,37 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> {
52 100
53/// Pio backed RGB ws2812 driver 101/// Pio backed RGB ws2812 driver
54/// Const N is the number of ws2812 leds attached to this pin 102/// Const N is the number of ws2812 leds attached to this pin
55pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize> { 103pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize, ORDER>
104where
105 ORDER: RgbColorOrder,
106{
56 dma: Peri<'d, AnyChannel>, 107 dma: Peri<'d, AnyChannel>,
57 sm: StateMachine<'d, P, S>, 108 sm: StateMachine<'d, P, S>,
109 _order: core::marker::PhantomData<ORDER>,
58} 110}
59 111
60impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> { 112impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N, Grb> {
61 /// Configure a pio state machine to use the loaded ws2812 program. 113 /// Configure a pio state machine to use the loaded ws2812 program.
114 /// Uses the default GRB order.
62 pub fn new( 115 pub fn new(
63 pio: &mut Common<'d, P>, 116 pio: &mut Common<'d, P>,
117 sm: StateMachine<'d, P, S>,
118 dma: Peri<'d, impl Channel>,
119 pin: Peri<'d, impl PioPin>,
120 program: &PioWs2812Program<'d, P>,
121 ) -> Self {
122 Self::with_color_order(pio, sm, dma, pin, program)
123 }
124}
125
126impl<'d, P: Instance, const S: usize, const N: usize, ORDER> PioWs2812<'d, P, S, N, ORDER>
127where
128 ORDER: RgbColorOrder,
129{
130 /// Configure a pio state machine to use the loaded ws2812 program.
131 /// Uses the specified color order.
132 pub fn with_color_order(
133 pio: &mut Common<'d, P>,
64 mut sm: StateMachine<'d, P, S>, 134 mut sm: StateMachine<'d, P, S>,
65 dma: Peri<'d, impl Channel>, 135 dma: Peri<'d, impl Channel>,
66 pin: Peri<'d, impl PioPin>, 136 pin: Peri<'d, impl PioPin>,
@@ -93,7 +163,11 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
93 sm.set_config(&cfg); 163 sm.set_config(&cfg);
94 sm.set_enable(true); 164 sm.set_enable(true);
95 165
96 Self { dma: dma.into(), sm } 166 Self {
167 dma: dma.into(),
168 sm,
169 _order: core::marker::PhantomData,
170 }
97 } 171 }
98 172
99 /// Write a buffer of [smart_leds::RGB8] to the ws2812 string 173 /// Write a buffer of [smart_leds::RGB8] to the ws2812 string
@@ -101,8 +175,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
101 // Precompute the word bytes from the colors 175 // Precompute the word bytes from the colors
102 let mut words = [0u32; N]; 176 let mut words = [0u32; N];
103 for i in 0..N { 177 for i in 0..N {
104 let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8); 178 words[i] = ORDER::pack(colors[i]);
105 words[i] = word;
106 } 179 }
107 180
108 // DMA transfer 181 // DMA transfer
@@ -115,15 +188,37 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
115/// Pio backed RGBW ws2812 driver 188/// Pio backed RGBW ws2812 driver
116/// This version is intended for ws2812 leds with 4 addressable lights 189/// This version is intended for ws2812 leds with 4 addressable lights
117/// Const N is the number of ws2812 leds attached to this pin 190/// Const N is the number of ws2812 leds attached to this pin
118pub struct RgbwPioWs2812<'d, P: Instance, const S: usize, const N: usize> { 191pub struct RgbwPioWs2812<'d, P: Instance, const S: usize, const N: usize, ORDER>
192where
193 ORDER: RgbwColorOrder,
194{
119 dma: Peri<'d, AnyChannel>, 195 dma: Peri<'d, AnyChannel>,
120 sm: StateMachine<'d, P, S>, 196 sm: StateMachine<'d, P, S>,
197 _order: core::marker::PhantomData<ORDER>,
121} 198}
122 199
123impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N> { 200impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N, Grbw> {
124 /// Configure a pio state machine to use the loaded ws2812 program. 201 /// Configure a pio state machine to use the loaded ws2812 program.
202 /// Uses the default GRBW color order
125 pub fn new( 203 pub fn new(
126 pio: &mut Common<'d, P>, 204 pio: &mut Common<'d, P>,
205 sm: StateMachine<'d, P, S>,
206 dma: Peri<'d, impl Channel>,
207 pin: Peri<'d, impl PioPin>,
208 program: &PioWs2812Program<'d, P>,
209 ) -> Self {
210 Self::with_color_order(pio, sm, dma, pin, program)
211 }
212}
213
214impl<'d, P: Instance, const S: usize, const N: usize, ORDER> RgbwPioWs2812<'d, P, S, N, ORDER>
215where
216 ORDER: RgbwColorOrder,
217{
218 /// Configure a pio state machine to use the loaded ws2812 program.
219 /// Uses the specified color order
220 pub fn with_color_order(
221 pio: &mut Common<'d, P>,
127 mut sm: StateMachine<'d, P, S>, 222 mut sm: StateMachine<'d, P, S>,
128 dma: Peri<'d, impl Channel>, 223 dma: Peri<'d, impl Channel>,
129 pin: Peri<'d, impl PioPin>, 224 pin: Peri<'d, impl PioPin>,
@@ -156,7 +251,11 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N>
156 sm.set_config(&cfg); 251 sm.set_config(&cfg);
157 sm.set_enable(true); 252 sm.set_enable(true);
158 253
159 Self { dma: dma.into(), sm } 254 Self {
255 dma: dma.into(),
256 sm,
257 _order: core::marker::PhantomData,
258 }
160 } 259 }
161 260
162 /// Write a buffer of [smart_leds::RGBW] to the ws2812 string 261 /// Write a buffer of [smart_leds::RGBW] to the ws2812 string
@@ -164,11 +263,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N>
164 // Precompute the word bytes from the colors 263 // Precompute the word bytes from the colors
165 let mut words = [0u32; N]; 264 let mut words = [0u32; N];
166 for i in 0..N { 265 for i in 0..N {
167 let word = (u32::from(colors[i].g) << 24) 266 words[i] = ORDER::pack(colors[i]);
168 | (u32::from(colors[i].r) << 16)
169 | (u32::from(colors[i].b) << 8)
170 | u32::from(colors[i].a.0);
171 words[i] = word;
172 } 267 }
173 268
174 // DMA transfer 269 // DMA transfer
diff --git a/embassy-rp/src/rom_data/rp2040.rs b/embassy-rp/src/rom_data/rp2040.rs
index 5a74eddd6..27a8d8981 100644
--- a/embassy-rp/src/rom_data/rp2040.rs
+++ b/embassy-rp/src/rom_data/rp2040.rs
@@ -30,7 +30,7 @@ const DATA_TABLE: *const u16 = 0x0000_0016 as _;
30/// Address of the version number of the ROM. 30/// Address of the version number of the ROM.
31const VERSION_NUMBER: *const u8 = 0x0000_0013 as _; 31const VERSION_NUMBER: *const u8 = 0x0000_0013 as _;
32 32
33/// Retrive rom content from a table using a code. 33/// Retrieve rom content from a table using a code.
34fn rom_table_lookup<T>(table: *const u16, tag: RomFnTableCode) -> T { 34fn rom_table_lookup<T>(table: *const u16, tag: RomFnTableCode) -> T {
35 unsafe { 35 unsafe {
36 let rom_table_lookup_ptr: *const u32 = rom_hword_as_ptr(ROM_TABLE_LOOKUP_PTR); 36 let rom_table_lookup_ptr: *const u32 = rom_hword_as_ptr(ROM_TABLE_LOOKUP_PTR);
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs
index 68fb3b765..054572903 100644
--- a/embassy-rp/src/rtc/mod.rs
+++ b/embassy-rp/src/rtc/mod.rs
@@ -47,7 +47,7 @@ impl<'d, T: Instance> Rtc<'d, T> {
47 Self { inner } 47 Self { inner }
48 } 48 }
49 49
50 /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. 50 /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisible by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check.
51 /// 51 ///
52 /// Leap year checking is enabled by default. 52 /// Leap year checking is enabled by default.
53 pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { 53 pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) {
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 559b3b909..d9410e78d 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -157,7 +157,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
157 157
158 /// Private function to apply SPI configuration (phase, polarity, frequency) settings. 158 /// Private function to apply SPI configuration (phase, polarity, frequency) settings.
159 /// 159 ///
160 /// Driver should be disabled before making changes and reenabled after the modifications 160 /// Driver should be disabled before making changes and re-enabled after the modifications
161 /// are applied. 161 /// are applied.
162 fn apply_config(inner: &Peri<'d, T>, config: &Config) { 162 fn apply_config(inner: &Peri<'d, T>, config: &Config) {
163 let p = inner.regs(); 163 let p = inner.regs();
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 43187df2d..8be87a5d2 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -315,7 +315,7 @@ impl<'d, M: Mode> UartRx<'d, M> {
315 } 315 }
316 316
317 /// Returns Ok(len) if no errors occurred. Returns Err((len, err)) if an error was 317 /// Returns Ok(len) if no errors occurred. Returns Err((len, err)) if an error was
318 /// encountered. in both cases, `len` is the number of *good* bytes copied into 318 /// encountered. In both cases, `len` is the number of *good* bytes copied into
319 /// `buffer`. 319 /// `buffer`.
320 fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> { 320 fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> {
321 let r = self.info.regs; 321 let r = self.info.regs;
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index a6ee5c4b8..f85fd82ef 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -5,9 +5,13 @@ All notable changes to this project will be documented in this file.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
8<!-- next-header -->
9## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
10 9
10- feat: Add support for injected ADC measurements for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840))
11- feat: Implement into_ring_buffered for g4 ([#4840](https://github.com/embassy-rs/embassy/pull/4840))
12- feat: Add support for 13-bit address and 16-bit data SDRAM chips
13- feat: stm32/hrtim add new_chx_with_config to provide pin configuration
14- fix flash erase on L4 & L5
11- fix: Fixed STM32H5 builds requiring time feature 15- fix: Fixed STM32H5 builds requiring time feature
12- feat: Derive Clone, Copy for QSPI Config 16- feat: Derive Clone, Copy for QSPI Config
13- fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received 17- fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received
@@ -31,10 +35,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
31- feat: stm32/usart: add `eager_reads` option to control if buffered readers return as soon as possible or after more data is available ([#4668](https://github.com/embassy-rs/embassy/pull/4668)) 35- feat: stm32/usart: add `eager_reads` option to control if buffered readers return as soon as possible or after more data is available ([#4668](https://github.com/embassy-rs/embassy/pull/4668))
32- feat: stm32/usart: add `de_assertion_time` and `de_deassertion_time` config options 36- feat: stm32/usart: add `de_assertion_time` and `de_deassertion_time` config options
33- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer 37- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer
38- fix: Prevent a HardFault crash on STM32H5 devices by changing `uid()` to return `[u8; 12]` by value instead of a reference. (Fixes #2696)
39- change: timer: added output compare values
40- feat: timer: add ability to set master mode
41- fix: sdmmc: don't wait for DBCKEND flag on sdmmc_v2 devices as it never fires (Fixes #4723)
42- fix: usart: fix race condition in ringbuffered usart
43- feat: Add backup_sram::init() for H5 devices to access BKPSRAM
44- feat: Add I2C MultiMaster (Slave) support for I2C v1
45- feat: stm32/fdcan: add ability to control automatic recovery from bus off ([#4821](https://github.com/embassy-rs/embassy/pull/4821))
46- low-power: update rtc api to allow reconfig
47- adc: consolidate ringbuffer
48- feat: Added RTC low-power support for STM32WLEx ([#4716](https://github.com/embassy-rs/embassy/pull/4716))
49- fix: Correct STM32WBA VREFBUFTRIM values
50- low_power: remove stop_with rtc and initialize in init if low-power feature enabled.
51- feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847))
52- feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388))
53- chore: Updated stm32-metapac and stm32-data dependencies
34 54
35## 0.4.0 - 2025-08-26 55## 0.4.0 - 2025-08-26
36 56
37- feat: stm32/sai: make NODIV independent of MCKDIV 57- feat: stm32/sai: make NODIV independent of MCKDIV
38- fix: stm32/sai: fix WB MCKDIV 58- fix: stm32/sai: fix WB MCKDIV
39- fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed. 59- fix: stm32/i2c: pull-down was enabled instead of pull-none when no internal pull-up was needed.
40- feat: Improve blocking hash speed 60- feat: Improve blocking hash speed
@@ -43,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43- chore: Updated stm32-metapac and stm32-data dependencies 63- chore: Updated stm32-metapac and stm32-data dependencies
44- feat: stm32/adc/v3: allow DMA reads to loop through enable channels 64- feat: stm32/adc/v3: allow DMA reads to loop through enable channels
45- fix: Fix XSPI not disabling alternate bytes when they were previously enabled 65- fix: Fix XSPI not disabling alternate bytes when they were previously enabled
66- feat: stm32/adc/v3: added support for Continuous DMA configuration
46- fix: Fix stm32h7rs init when using external flash via XSPI 67- fix: Fix stm32h7rs init when using external flash via XSPI
47- feat: Add Adc::new_with_clock() to configure analog clock 68- feat: Add Adc::new_with_clock() to configure analog clock
48- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923)) 69- feat: Add GPDMA linked-list + ringbuffer support ([#3923](https://github.com/embassy-rs/embassy/pull/3923))
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 7c243b350..108321d0a 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -177,12 +177,10 @@ cortex-m = "0.7.6"
177futures-util = { version = "0.3.30", default-features = false } 177futures-util = { version = "0.3.30", default-features = false }
178sdio-host = "0.9.0" 178sdio-host = "0.9.0"
179critical-section = "1.1" 179critical-section = "1.1"
180#stm32-metapac = { version = "18" }
181stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0" }
182 180
183vcell = "0.1.3" 181vcell = "0.1.3"
184nb = "1.0.0" 182nb = "1.0.0"
185stm32-fmc = "0.3.0" 183stm32-fmc = "0.4.0"
186cfg-if = "1.0.0" 184cfg-if = "1.0.0"
187embedded-io = { version = "0.6.0" } 185embedded-io = { version = "0.6.0" }
188embedded-io-async = { version = "0.6.1" } 186embedded-io-async = { version = "0.6.1" }
@@ -198,17 +196,23 @@ block-device-driver = { version = "0.2" }
198aligned = "0.4.1" 196aligned = "0.4.1"
199heapless = "0.9.1" 197heapless = "0.9.1"
200 198
199#stm32-metapac = { version = "18" }
200stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e" }
201
202[build-dependencies]
203#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
204stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-22374e3344a2c9150b9b3d4da45c03f398fdc54e", default-features = false, features = ["metadata"] }
205
206proc-macro2 = "1.0.36"
207quote = "1.0.15"
208
209
201[dev-dependencies] 210[dev-dependencies]
202critical-section = { version = "1.1", features = ["std"] } 211critical-section = { version = "1.1", features = ["std"] }
203proptest = "1.5.0" 212proptest = "1.5.0"
204proptest-state-machine = "0.3.0" 213proptest-state-machine = "0.3.0"
205 214
206[build-dependencies]
207proc-macro2 = "1.0.36"
208quote = "1.0.15"
209 215
210#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
211stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0", default-features = false, features = ["metadata"] }
212 216
213[features] 217[features]
214default = ["rt"] 218default = ["rt"]
@@ -313,6 +317,7 @@ single-bank = []
313 317
314## internal use only 318## internal use only
315_split-pins-enabled = [] 319_split-pins-enabled = []
320_allow-disable-rtc = []
316 321
317## internal use only 322## internal use only
318_dual-core = [] 323_dual-core = []
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index eea1acf68..940e29417 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -114,6 +114,8 @@ fn main() {
114 } 114 }
115 }; 115 };
116 116
117 let has_bkpsram = memory.iter().any(|m| m.name == "BKPSRAM");
118
117 // ======== 119 // ========
118 // Generate singletons 120 // Generate singletons
119 121
@@ -124,6 +126,13 @@ fn main() {
124 singletons.push(p.name.to_string()); 126 singletons.push(p.name.to_string());
125 } 127 }
126 128
129 cfgs.declare("backup_sram");
130
131 if has_bkpsram {
132 singletons.push("BKPSRAM".to_string());
133 cfgs.enable("backup_sram")
134 }
135
127 // generate one singleton per peripheral (with many exceptions...) 136 // generate one singleton per peripheral (with many exceptions...)
128 for p in METADATA.peripherals { 137 for p in METADATA.peripherals {
129 if let Some(r) = &p.registers { 138 if let Some(r) = &p.registers {
@@ -1985,6 +1994,18 @@ fn main() {
1985 )); 1994 ));
1986 1995
1987 // ======== 1996 // ========
1997 // Generate backup sram constants
1998 if let Some(m) = memory.iter().find(|m| m.name == "BKPSRAM") {
1999 let bkpsram_base = m.address as usize;
2000 let bkpsram_size = m.size as usize;
2001
2002 g.extend(quote!(
2003 pub const BKPSRAM_BASE: usize = #bkpsram_base;
2004 pub const BKPSRAM_SIZE: usize = #bkpsram_size;
2005 ));
2006 }
2007
2008 // ========
1988 // Generate flash constants 2009 // Generate flash constants
1989 2010
1990 let flash_regions: Vec<&MemoryRegion> = memory 2011 let flash_regions: Vec<&MemoryRegion> = memory
@@ -2311,6 +2332,10 @@ fn mem_filter(chip: &str, region: &str) -> bool {
2311 return false; 2332 return false;
2312 } 2333 }
2313 2334
2335 if region.starts_with("SDRAM_") || region.starts_with("FMC_") || region.starts_with("OCTOSPI_") {
2336 return false;
2337 }
2338
2314 true 2339 true
2315} 2340}
2316 2341
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 5098aadd8..3767820cf 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -1,11 +1,14 @@
1use core::mem;
2
1#[allow(unused)] 3#[allow(unused)]
2#[cfg(stm32h7)] 4#[cfg(stm32h7)]
3use pac::adc::vals::{Adcaldif, Difsel, Exten}; 5use pac::adc::vals::{Adcaldif, Difsel, Exten};
4#[allow(unused)] 6#[allow(unused)]
5#[cfg(stm32g4)] 7#[cfg(stm32g4)]
6use pac::adc::vals::{Adcaldif, Difsel, Exten, Rovsm, Trovs}; 8pub use pac::adc::vals::{Adcaldif, Difsel, Exten, Rovsm, Trovs};
7use pac::adccommon::vals::Presc; 9pub use pac::adccommon::vals::Presc;
8use stm32_metapac::adc::vals::{Adstp, Dmacfg, Dmaen}; 10pub use stm32_metapac::adc::vals::{Adstp, Dmacfg, Dmaen};
11pub use stm32_metapac::adccommon::vals::Dual;
9 12
10use super::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, blocking_delay_us}; 13use super::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, blocking_delay_us};
11use crate::adc::SealedAdcChannel; 14use crate::adc::SealedAdcChannel;
@@ -13,11 +16,19 @@ use crate::dma::Transfer;
13use crate::time::Hertz; 16use crate::time::Hertz;
14use crate::{Peri, pac, rcc}; 17use crate::{Peri, pac, rcc};
15 18
19mod ringbuffered;
20pub use ringbuffered::RingBufferedAdc;
21
22mod injected;
23pub use injected::InjectedAdc;
24
16/// Default VREF voltage used for sample conversion to millivolts. 25/// Default VREF voltage used for sample conversion to millivolts.
17pub const VREF_DEFAULT_MV: u32 = 3300; 26pub const VREF_DEFAULT_MV: u32 = 3300;
18/// VREF voltage used for factory calibration of VREFINTCAL register. 27/// VREF voltage used for factory calibration of VREFINTCAL register.
19pub const VREF_CALIB_MV: u32 = 3300; 28pub const VREF_CALIB_MV: u32 = 3300;
20 29
30const NR_INJECTED_RANKS: usize = 4;
31
21/// Max single ADC operation clock frequency 32/// Max single ADC operation clock frequency
22#[cfg(stm32g4)] 33#[cfg(stm32g4)]
23const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); 34const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
@@ -120,6 +131,24 @@ impl Prescaler {
120 } 131 }
121} 132}
122 133
134// Trigger source for ADC conversions¨
135#[derive(Copy, Clone)]
136pub struct ConversionTrigger {
137 // See Table 166 and 167 in RM0440 Rev 9 for ADC1/2 External triggers
138 // Note that Injected and Regular channels uses different mappings
139 pub channel: u8,
140 pub edge: Exten,
141}
142
143// Conversion mode for regular ADC channels
144#[derive(Copy, Clone)]
145pub enum RegularConversionMode {
146 // Samples as fast as possible
147 Continuous,
148 // Sample at rate determined by external trigger
149 Triggered(ConversionTrigger),
150}
151
123impl<'d, T: Instance> Adc<'d, T> { 152impl<'d, T: Instance> Adc<'d, T> {
124 /// Create a new ADC driver. 153 /// Create a new ADC driver.
125 pub fn new(adc: Peri<'d, T>) -> Self { 154 pub fn new(adc: Peri<'d, T>) -> Self {
@@ -357,7 +386,29 @@ impl<'d, T: Instance> Adc<'d, T> {
357 self.read_channel(channel) 386 self.read_channel(channel)
358 } 387 }
359 388
360 /// Read one or multiple ADC channels using DMA. 389 /// Start regular adc conversion
390 pub(super) fn start() {
391 T::regs().cr().modify(|reg| {
392 reg.set_adstart(true);
393 });
394 }
395
396 /// Stop regular conversions
397 pub(super) fn stop() {
398 Self::stop_regular_conversions();
399 }
400
401 /// Teardown method for stopping regular ADC conversions
402 pub(super) fn teardown_adc() {
403 Self::stop_regular_conversions();
404
405 // Disable dma control
406 T::regs().cfgr().modify(|reg| {
407 reg.set_dmaen(Dmaen::DISABLE);
408 });
409 }
410
411 /// Read one or multiple ADC regular channels using DMA.
361 /// 412 ///
362 /// `sequence` iterator and `readings` must have the same length. 413 /// `sequence` iterator and `readings` must have the same length.
363 /// 414 ///
@@ -382,6 +433,9 @@ impl<'d, T: Instance> Adc<'d, T> {
382 /// .await; 433 /// .await;
383 /// defmt::info!("measurements: {}", measurements); 434 /// defmt::info!("measurements: {}", measurements);
384 /// ``` 435 /// ```
436 ///
437 /// Note: This is not very efficient as the ADC needs to be reconfigured for each read. Use
438 /// `into_ring_buffered`, `into_ring_buffered_and_injected`
385 pub async fn read( 439 pub async fn read(
386 &mut self, 440 &mut self,
387 rx_dma: Peri<'_, impl RxDma<T>>, 441 rx_dma: Peri<'_, impl RxDma<T>>,
@@ -399,18 +453,16 @@ impl<'d, T: Instance> Adc<'d, T> {
399 ); 453 );
400 454
401 // Ensure no conversions are ongoing and ADC is enabled. 455 // Ensure no conversions are ongoing and ADC is enabled.
402 Self::cancel_conversions(); 456 Self::stop_regular_conversions();
403 self.enable(); 457 self.enable();
404 458
405 // Set sequence length 459 // Set sequence length
406 T::regs().sqr1().modify(|w| { 460 T::regs().sqr1().modify(|w| {
407 w.set_l(sequence.len() as u8 - 1); 461 w.set_l(sequence.len() as u8 - 1);
408 }); 462 });
409
410 // Configure channels and ranks 463 // Configure channels and ranks
411 for (_i, (channel, sample_time)) in sequence.enumerate() { 464 for (_i, (channel, sample_time)) in sequence.enumerate() {
412 Self::configure_channel(channel, sample_time); 465 Self::configure_channel(channel, sample_time);
413
414 match _i { 466 match _i {
415 0..=3 => { 467 0..=3 => {
416 T::regs().sqr1().modify(|w| { 468 T::regs().sqr1().modify(|w| {
@@ -469,7 +521,7 @@ impl<'d, T: Instance> Adc<'d, T> {
469 transfer.await; 521 transfer.await;
470 522
471 // Ensure conversions are finished. 523 // Ensure conversions are finished.
472 Self::cancel_conversions(); 524 Self::stop_regular_conversions();
473 525
474 // Reset configuration. 526 // Reset configuration.
475 T::regs().cfgr().modify(|reg| { 527 T::regs().cfgr().modify(|reg| {
@@ -477,6 +529,277 @@ impl<'d, T: Instance> Adc<'d, T> {
477 }); 529 });
478 } 530 }
479 531
532 /// Set external trigger for regular conversion sequence
533 fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) {
534 T::regs().cfgr().modify(|r| {
535 r.set_extsel(trigger.channel);
536 r.set_exten(trigger.edge);
537 });
538 // Regular conversions uses DMA so no need to generate interrupt
539 T::regs().ier().modify(|r| r.set_eosie(false));
540 }
541
542 // Dual ADC mode selection
543 pub fn configure_dual_mode(&mut self, val: Dual) {
544 T::common_regs().ccr().modify(|reg| {
545 reg.set_dual(val);
546 })
547 }
548
549 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
550 ///
551 /// Use the [`read`] method to retrieve measurements from the DMA ring buffer. The read buffer
552 /// should be exactly half the size of `dma_buf`. When using triggered mode, it is recommended
553 /// to configure `dma_buf` as a double buffer so that one half can be read while the other half
554 /// is being filled by the DMA, preventing data loss. The trigger period of the ADC effectively
555 /// defines the period at which the buffer should be read.
556 ///
557 /// If continous conversion mode is selected, the provided `dma_buf` must be large enough to prevent
558 /// DMA buffer overruns. Its length should be a multiple of the number of ADC channels being measured.
559 /// For example, if 3 channels are measured and you want to store 40 samples per channel,
560 /// the buffer length should be `3 * 40 = 120`.
561 ///
562 /// # Parameters
563 /// - `dma`: The DMA peripheral used to transfer ADC data into the buffer.
564 /// - `dma_buf`: The buffer where DMA stores ADC samples.
565 /// - `regular_sequence`: Sequence of channels and sample times for regular ADC conversions.
566 /// - `regular_conversion_mode`: Mode for regular conversions (continuous or triggered).
567 ///
568 /// # Returns
569 /// A `RingBufferedAdc<'a, T>` instance configured for continuous DMA-based sampling.
570 pub fn into_ring_buffered<'a>(
571 mut self,
572 dma: Peri<'a, impl RxDma<T>>,
573 dma_buf: &'a mut [u16],
574 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>,
575 mode: RegularConversionMode,
576 ) -> RingBufferedAdc<'a, T> {
577 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
578 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
579 assert!(
580 sequence.len() <= 16,
581 "Asynchronous read sequence cannot be more than 16 in length"
582 );
583 // reset conversions and enable the adc
584 Self::stop_regular_conversions();
585 self.enable();
586
587 //adc side setup
588
589 // Set sequence length
590 T::regs().sqr1().modify(|w| {
591 w.set_l(sequence.len() as u8 - 1);
592 });
593
594 // Configure channels and ranks
595 for (_i, (mut channel, sample_time)) in sequence.enumerate() {
596 Self::configure_channel(&mut channel, sample_time);
597
598 match _i {
599 0..=3 => {
600 T::regs().sqr1().modify(|w| {
601 w.set_sq(_i, channel.channel());
602 });
603 }
604 4..=8 => {
605 T::regs().sqr2().modify(|w| {
606 w.set_sq(_i - 4, channel.channel());
607 });
608 }
609 9..=13 => {
610 T::regs().sqr3().modify(|w| {
611 w.set_sq(_i - 9, channel.channel());
612 });
613 }
614 14..=15 => {
615 T::regs().sqr4().modify(|w| {
616 w.set_sq(_i - 14, channel.channel());
617 });
618 }
619 _ => unreachable!(),
620 }
621 }
622
623 // Clear overrun flag before starting transfer.
624 T::regs().isr().modify(|reg| {
625 reg.set_ovr(true);
626 });
627
628 T::regs().cfgr().modify(|reg| {
629 reg.set_discen(false); // Convert all channels for each trigger
630 reg.set_dmacfg(Dmacfg::CIRCULAR);
631 reg.set_dmaen(Dmaen::ENABLE);
632 });
633
634 match mode {
635 RegularConversionMode::Continuous => {
636 T::regs().cfgr().modify(|reg| {
637 reg.set_cont(true);
638 });
639 }
640 RegularConversionMode::Triggered(trigger) => {
641 T::regs().cfgr().modify(|r| {
642 r.set_cont(false); // New trigger is neede for each sample to be read
643 });
644 self.set_regular_conversion_trigger(trigger);
645 }
646 }
647
648 mem::forget(self);
649
650 RingBufferedAdc::new(dma, dma_buf)
651 }
652
653 /// Configures the ADC for injected conversions.
654 ///
655 /// Injected conversions are separate from the regular conversion sequence and are typically
656 /// triggered by software or an external event. This method sets up a fixed-length sequence of
657 /// injected channels with specified sample times, the trigger source, and whether the end-of-sequence
658 /// interrupt should be enabled.
659 ///
660 /// # Parameters
661 /// - `sequence`: An array of tuples containing the ADC channels and their sample times. The length
662 /// `N` determines the number of injected ranks to configure (maximum 4 for STM32).
663 /// - `trigger`: The trigger source that starts the injected conversion sequence.
664 /// - `interrupt`: If `true`, enables the end-of-sequence (JEOS) interrupt for injected conversions.
665 ///
666 /// # Returns
667 /// An `InjectedAdc<T, N>` instance that represents the configured injected sequence. The returned
668 /// type encodes the sequence length `N` in its type, ensuring that reads return exactly `N` samples.
669 ///
670 /// # Panics
671 /// This function will panic if:
672 /// - `sequence` is empty.
673 /// - `sequence` length exceeds the maximum number of injected ranks (`NR_INJECTED_RANKS`).
674 ///
675 /// # Notes
676 /// - Injected conversions can run independently of regular ADC conversions.
677 /// - The order of channels in `sequence` determines the rank order in the injected sequence.
678 /// - Accessing samples beyond `N` will result in a panic; use the returned type
679 /// `InjectedAdc<T, N>` to enforce bounds at compile time.
680 pub fn setup_injected_conversions<'a, const N: usize>(
681 mut self,
682 sequence: [(AnyAdcChannel<T>, SampleTime); N],
683 trigger: ConversionTrigger,
684 interrupt: bool,
685 ) -> InjectedAdc<T, N> {
686 assert!(N != 0, "Read sequence cannot be empty");
687 assert!(
688 N <= NR_INJECTED_RANKS,
689 "Read sequence cannot be more than {} in length",
690 NR_INJECTED_RANKS
691 );
692
693 Self::stop_regular_conversions();
694 self.enable();
695
696 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
697
698 for (n, (mut channel, sample_time)) in sequence.into_iter().enumerate() {
699 Self::configure_channel(&mut channel, sample_time);
700
701 let idx = match n {
702 0..=3 => n,
703 4..=8 => n - 4,
704 9..=13 => n - 9,
705 14..=15 => n - 14,
706 _ => unreachable!(),
707 };
708
709 T::regs().jsqr().modify(|w| w.set_jsq(idx, channel.channel()));
710 }
711
712 T::regs().cfgr().modify(|reg| reg.set_jdiscen(false));
713
714 self.set_injected_conversion_trigger(trigger);
715 self.enable_injected_eos_interrupt(interrupt);
716 Self::start_injected_conversions();
717
718 InjectedAdc::new(sequence) // InjectedAdc<'a, T, N> now borrows the channels
719 }
720
721 /// Configures ADC for both regular conversions with a ring-buffered DMA and injected conversions.
722 ///
723 /// # Parameters
724 /// - `dma`: The DMA peripheral to use for the ring-buffered ADC transfers.
725 /// - `dma_buf`: The buffer to store DMA-transferred samples for regular conversions.
726 /// - `regular_sequence`: The sequence of channels and their sample times for regular conversions.
727 /// - `regular_conversion_mode`: The mode for regular conversions (e.g., continuous or triggered).
728 /// - `injected_sequence`: An array of channels and sample times for injected conversions (length `N`).
729 /// - `injected_trigger`: The trigger source for injected conversions.
730 /// - `injected_interrupt`: Whether to enable the end-of-sequence interrupt for injected conversions.
731 ///
732 /// Injected conversions are typically used with interrupts. If ADC1 and ADC2 are used in dual mode,
733 /// it is recommended to enable interrupts only for the ADC whose sequence takes the longest to complete.
734 ///
735 /// # Returns
736 /// A tuple containing:
737 /// 1. `RingBufferedAdc<'a, T>` — the configured ADC for regular conversions using DMA.
738 /// 2. `InjectedAdc<T, N>` — the configured ADC for injected conversions.
739 ///
740 /// # Safety
741 /// This function is `unsafe` because it clones the ADC peripheral handle unchecked. Both the
742 /// `RingBufferedAdc` and `InjectedAdc` take ownership of the handle and drop it independently.
743 /// Ensure no other code concurrently accesses the same ADC instance in a conflicting way.
744 pub fn into_ring_buffered_and_injected<'a, const N: usize>(
745 self,
746 dma: Peri<'a, impl RxDma<T>>,
747 dma_buf: &'a mut [u16],
748 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>,
749 regular_conversion_mode: RegularConversionMode,
750 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N],
751 injected_trigger: ConversionTrigger,
752 injected_interrupt: bool,
753 ) -> (RingBufferedAdc<'a, T>, InjectedAdc<T, N>) {
754 unsafe {
755 (
756 Self {
757 adc: self.adc.clone_unchecked(),
758 sample_time: self.sample_time,
759 }
760 .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode),
761 Self {
762 adc: self.adc.clone_unchecked(),
763 sample_time: self.sample_time,
764 }
765 .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt),
766 )
767 }
768 }
769
770 /// Stop injected conversions
771 pub(super) fn stop_injected_conversions() {
772 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
773 T::regs().cr().modify(|reg| {
774 reg.set_jadstp(Adstp::STOP);
775 });
776 // The software must poll JADSTART until the bit is reset before assuming the
777 // ADC is completely stopped
778 while T::regs().cr().read().jadstart() {}
779 }
780 }
781
782 /// Start injected ADC conversion
783 pub(super) fn start_injected_conversions() {
784 T::regs().cr().modify(|reg| {
785 reg.set_jadstart(true);
786 });
787 }
788
789 /// Set external trigger for injected conversion sequence
790 /// Possible trigger values are seen in Table 167 in RM0440 Rev 9
791 fn set_injected_conversion_trigger(&mut self, trigger: ConversionTrigger) {
792 T::regs().jsqr().modify(|r| {
793 r.set_jextsel(trigger.channel);
794 r.set_jexten(trigger.edge);
795 });
796 }
797
798 /// Enable end of injected sequence interrupt
799 fn enable_injected_eos_interrupt(&mut self, enable: bool) {
800 T::regs().ier().modify(|r| r.set_jeosie(enable));
801 }
802
480 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) { 803 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
481 // Configure channel 804 // Configure channel
482 Self::set_channel_sample_time(channel.channel(), sample_time); 805 Self::set_channel_sample_time(channel.channel(), sample_time);
@@ -509,16 +832,34 @@ impl<'d, T: Instance> Adc<'d, T> {
509 } 832 }
510 } 833 }
511 834
512 fn cancel_conversions() { 835 // Stop regular conversions
836 fn stop_regular_conversions() {
513 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 837 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
514 T::regs().cr().modify(|reg| { 838 T::regs().cr().modify(|reg| {
515 reg.set_adstp(Adstp::STOP); 839 reg.set_adstp(Adstp::STOP);
516 }); 840 });
841 // The software must poll ADSTART until the bit is reset before assuming the
842 // ADC is completely stopped
517 while T::regs().cr().read().adstart() {} 843 while T::regs().cr().read().adstart() {}
518 } 844 }
519 } 845 }
520} 846}
521 847
848impl<T: Instance, const N: usize> InjectedAdc<T, N> {
849 /// Read sampled data from all injected ADC injected ranks
850 /// Clear the JEOS flag to allow a new injected sequence
851 pub(super) fn read_injected_data() -> [u16; N] {
852 let mut data = [0u16; N];
853 for i in 0..N {
854 data[i] = T::regs().jdr(i).read().jdata();
855 }
856
857 // Clear JEOS by writing 1
858 T::regs().isr().modify(|r| r.set_jeos(true));
859 data
860 }
861}
862
522/// Implemented for ADCs that have a Temperature channel 863/// Implemented for ADCs that have a Temperature channel
523pub trait TemperatureChannel { 864pub trait TemperatureChannel {
524 const CHANNEL: u8; 865 const CHANNEL: u8;
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs
new file mode 100644
index 000000000..0e4fe5847
--- /dev/null
+++ b/embassy-stm32/src/adc/injected.rs
@@ -0,0 +1,44 @@
1use core::marker::PhantomData;
2use core::sync::atomic::{Ordering, compiler_fence};
3
4#[allow(unused_imports)]
5use embassy_hal_internal::Peri;
6
7use super::{AnyAdcChannel, SampleTime};
8use crate::adc::Adc;
9#[allow(unused_imports)]
10use crate::adc::Instance;
11
12/// Injected ADC sequence with owned channels.
13pub struct InjectedAdc<T: Instance, const N: usize> {
14 _channels: [(AnyAdcChannel<T>, SampleTime); N],
15 _phantom: PhantomData<T>,
16}
17
18impl<T: Instance, const N: usize> InjectedAdc<T, N> {
19 pub(crate) fn new(channels: [(AnyAdcChannel<T>, SampleTime); N]) -> Self {
20 Self {
21 _channels: channels,
22 _phantom: PhantomData,
23 }
24 }
25
26 pub fn stop_injected_conversions(&mut self) {
27 Adc::<T>::stop_injected_conversions()
28 }
29
30 pub fn start_injected_conversions(&mut self) {
31 Adc::<T>::start_injected_conversions()
32 }
33
34 pub fn read_injected_samples(&mut self) -> [u16; N] {
35 InjectedAdc::<T, N>::read_injected_data()
36 }
37}
38
39impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> {
40 fn drop(&mut self) {
41 Adc::<T>::teardown_adc();
42 compiler_fence(Ordering::SeqCst);
43 }
44}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 22ed8295f..ea7341f75 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -87,14 +87,18 @@ pub(crate) trait SealedAdcChannel<T> {
87/// Performs a busy-wait delay for a specified number of microseconds. 87/// Performs a busy-wait delay for a specified number of microseconds.
88#[allow(unused)] 88#[allow(unused)]
89pub(crate) fn blocking_delay_us(us: u32) { 89pub(crate) fn blocking_delay_us(us: u32) {
90 #[cfg(feature = "time")] 90 cfg_if::cfg_if! {
91 embassy_time::block_for(embassy_time::Duration::from_micros(us as u64)); 91 // this does strange things on stm32wlx in low power mode depending on exactly when it's called
92 #[cfg(not(feature = "time"))] 92 // as in sometimes 15 us (1 tick) would take > 20 seconds.
93 { 93 if #[cfg(all(feature = "time", all(not(feature = "low-power"), not(stm32wlex))))] {
94 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64; 94 let duration = embassy_time::Duration::from_micros(us as u64);
95 let us = us as u64; 95 embassy_time::block_for(duration);
96 let cycles = freq * us / 1_000_000; 96 } else {
97 cortex_m::asm::delay(cycles as u32); 97 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64;
98 let us = us as u64;
99 let cycles = freq * us / 1_000_000;
100 cortex_m::asm::delay(cycles as u32);
101 }
98 } 102 }
99} 103}
100 104
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
new file mode 100644
index 000000000..971c8195c
--- /dev/null
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -0,0 +1,182 @@
1use core::marker::PhantomData;
2use core::sync::atomic::{Ordering, compiler_fence};
3
4#[allow(unused_imports)]
5use embassy_hal_internal::Peri;
6
7use crate::adc::Adc;
8#[allow(unused_imports)]
9use crate::adc::{Instance, RxDma};
10#[allow(unused_imports)]
11use crate::dma::{ReadableRingBuffer, TransferOptions};
12use crate::rcc;
13
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct OverrunError;
16
17pub struct RingBufferedAdc<'d, T: Instance> {
18 _phantom: PhantomData<T>,
19 ring_buf: ReadableRingBuffer<'d, u16>,
20}
21
22impl<'d, T: Instance> RingBufferedAdc<'d, T> {
23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self {
24 //dma side setup
25 let opts = TransferOptions {
26 half_transfer_ir: true,
27 circular: true,
28 ..Default::default()
29 };
30
31 // Safety: we forget the struct before this function returns.
32 let request = dma.request();
33
34 let ring_buf =
35 unsafe { ReadableRingBuffer::new(dma, request, T::regs().dr().as_ptr() as *mut u16, dma_buf, opts) };
36
37 Self {
38 _phantom: PhantomData,
39 ring_buf,
40 }
41 }
42
43 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer.
44 pub fn start(&mut self) {
45 compiler_fence(Ordering::SeqCst);
46 self.ring_buf.start();
47
48 Adc::<T>::start();
49 }
50
51 pub fn stop(&mut self) {
52 Adc::<T>::stop();
53
54 self.ring_buf.request_pause();
55
56 compiler_fence(Ordering::SeqCst);
57 }
58
59 pub fn clear(&mut self) {
60 self.ring_buf.clear();
61 }
62
63 /// Reads measurements from the DMA ring buffer.
64 ///
65 /// This method fills the provided `measurements` array with ADC readings from the DMA buffer.
66 /// The length of the `measurements` array should be exactly half of the DMA buffer length.
67 /// Because interrupts are only generated if half or full DMA transfer completes.
68 ///
69 /// Each call to `read` will populate the `measurements` array in the same order as the channels
70 /// defined with `sequence`. There will be many sequences worth of measurements in this array
71 /// because it only returns if at least half of the DMA buffer is filled. For example if 2
72 /// channels are sampled `measurements` contain: `[sq0 sq1 sq0 sq1 sq0 sq1 ..]`.
73 ///
74 /// Note that the ADC Datarate can be very fast, it is suggested to use DMA mode inside tightly
75 /// running tasks. Otherwise, you'll see constant Overrun errors occurring, this means that
76 /// you're sampling too quickly for the task to handle, and you may need to increase the buffer size.
77 /// Example:
78 /// ```rust,ignore
79 /// const DMA_BUF_LEN: usize = 120;
80 /// use embassy_stm32::adc::{Adc, AdcChannel}
81 ///
82 /// let mut adc = Adc::new(p.ADC1);
83 /// let mut adc_pin0 = p.PA0.degrade_adc();
84 /// let mut adc_pin1 = p.PA1.degrade_adc();
85 /// let adc_dma_buf = [0u16; DMA_BUF_LEN];
86 ///
87 /// let mut ring_buffered_adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(
88 /// p.DMA2_CH0,
89 /// adc_dma_buf, [
90 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
91 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
92 /// ].into_iter());
93 ///
94 ///
95 /// let mut measurements = [0u16; DMA_BUF_LEN / 2];
96 /// loop {
97 /// match ring_buffered_adc.read(&mut measurements).await {
98 /// Ok(_) => {
99 /// defmt::info!("adc1: {}", measurements);
100 /// }
101 /// Err(e) => {
102 /// defmt::warn!("Error: {:?}", e);
103 /// }
104 /// }
105 /// }
106 /// ```
107 ///
108 ///
109 /// [`teardown_adc`]: #method.teardown_adc
110 /// [`start_continuous_sampling`]: #method.start_continuous_sampling
111 pub async fn read(&mut self, measurements: &mut [u16]) -> Result<usize, OverrunError> {
112 assert_eq!(
113 self.ring_buf.capacity() / 2,
114 measurements.len(),
115 "Buffer size must be half the size of the ring buffer"
116 );
117
118 if !self.ring_buf.is_running() {
119 self.start();
120 }
121
122 #[cfg(adc_v2)]
123 {
124 // Clear overrun flag if set.
125 if T::regs().sr().read().ovr() {
126 self.stop();
127
128 return Err(OverrunError);
129 }
130 }
131
132 self.ring_buf.read_exact(measurements).await.map_err(|_| OverrunError)
133 }
134
135 /// Read bytes that are readily available in the ring buffer.
136 /// If no bytes are currently available in the buffer the call waits until the some
137 /// bytes are available (at least one byte and at most half the buffer size)
138 ///
139 /// Background receive is started if `start_continuous_sampling()` has not been previously called.
140 ///
141 /// Receive in the background is terminated if an error is returned.
142 /// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`.
143 pub fn blocking_read(&mut self, buf: &mut [u16]) -> Result<usize, OverrunError> {
144 if !self.ring_buf.is_running() {
145 self.start();
146 }
147
148 #[cfg(adc_v2)]
149 {
150 // Clear overrun flag if set.
151 if T::regs().sr().read().ovr() {
152 self.stop();
153
154 return Err(OverrunError);
155 }
156 }
157 loop {
158 match self.ring_buf.read(buf) {
159 Ok((0, _)) => {}
160 Ok((len, _)) => {
161 return Ok(len);
162 }
163 Err(_) => {
164 self.stop();
165
166 return Err(OverrunError);
167 }
168 }
169 }
170 }
171}
172
173impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
174 fn drop(&mut self) {
175 Adc::<T>::teardown_adc();
176
177 compiler_fence(Ordering::SeqCst);
178
179 self.ring_buf.request_pause();
180 rcc::disable::<T>();
181 }
182}
diff --git a/embassy-stm32/src/adc/ringbuffered_v2.rs b/embassy-stm32/src/adc/ringbuffered_v2.rs
deleted file mode 100644
index 9b2e5b8fe..000000000
--- a/embassy-stm32/src/adc/ringbuffered_v2.rs
+++ /dev/null
@@ -1,432 +0,0 @@
1use core::marker::PhantomData;
2use core::mem;
3use core::sync::atomic::{Ordering, compiler_fence};
4
5use stm32_metapac::adc::vals::SampleTime;
6
7use crate::adc::{Adc, AdcChannel, Instance, RxDma};
8use crate::dma::{Priority, ReadableRingBuffer, TransferOptions};
9use crate::pac::adc::vals;
10use crate::{Peri, rcc};
11
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct OverrunError;
14
15fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
16 r.sr().modify(|regs| {
17 regs.set_eoc(false);
18 regs.set_ovr(false);
19 });
20}
21
22#[derive(PartialOrd, PartialEq, Debug, Clone, Copy)]
23pub enum Sequence {
24 One,
25 Two,
26 Three,
27 Four,
28 Five,
29 Six,
30 Seven,
31 Eight,
32 Nine,
33 Ten,
34 Eleven,
35 Twelve,
36 Thirteen,
37 Fourteen,
38 Fifteen,
39 Sixteen,
40}
41
42impl From<Sequence> for u8 {
43 fn from(s: Sequence) -> u8 {
44 match s {
45 Sequence::One => 0,
46 Sequence::Two => 1,
47 Sequence::Three => 2,
48 Sequence::Four => 3,
49 Sequence::Five => 4,
50 Sequence::Six => 5,
51 Sequence::Seven => 6,
52 Sequence::Eight => 7,
53 Sequence::Nine => 8,
54 Sequence::Ten => 9,
55 Sequence::Eleven => 10,
56 Sequence::Twelve => 11,
57 Sequence::Thirteen => 12,
58 Sequence::Fourteen => 13,
59 Sequence::Fifteen => 14,
60 Sequence::Sixteen => 15,
61 }
62 }
63}
64
65impl From<u8> for Sequence {
66 fn from(val: u8) -> Self {
67 match val {
68 0 => Sequence::One,
69 1 => Sequence::Two,
70 2 => Sequence::Three,
71 3 => Sequence::Four,
72 4 => Sequence::Five,
73 5 => Sequence::Six,
74 6 => Sequence::Seven,
75 7 => Sequence::Eight,
76 8 => Sequence::Nine,
77 9 => Sequence::Ten,
78 10 => Sequence::Eleven,
79 11 => Sequence::Twelve,
80 12 => Sequence::Thirteen,
81 13 => Sequence::Fourteen,
82 14 => Sequence::Fifteen,
83 15 => Sequence::Sixteen,
84 _ => panic!("Invalid sequence number"),
85 }
86 }
87}
88
89pub struct RingBufferedAdc<'d, T: Instance> {
90 _phantom: PhantomData<T>,
91 ring_buf: ReadableRingBuffer<'d, u16>,
92}
93
94impl<'d, T: Instance> Adc<'d, T> {
95 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
96 ///
97 /// The `dma_buf` should be large enough to prevent DMA buffer overrun.
98 /// The length of the `dma_buf` should be a multiple of the ADC channel count.
99 /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements.
100 ///
101 /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length.
102 /// It is critical to call `read` frequently to prevent DMA buffer overrun.
103 ///
104 /// [`read`]: #method.read
105 pub fn into_ring_buffered(self, dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> RingBufferedAdc<'d, T> {
106 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
107
108 let opts: crate::dma::TransferOptions = TransferOptions {
109 half_transfer_ir: true,
110 priority: Priority::VeryHigh,
111 ..Default::default()
112 };
113
114 // Safety: we forget the struct before this function returns.
115 let rx_src = T::regs().dr().as_ptr() as *mut u16;
116 let request = dma.request();
117
118 let ring_buf = unsafe { ReadableRingBuffer::new(dma, request, rx_src, dma_buf, opts) };
119
120 // Don't disable the clock
121 mem::forget(self);
122
123 RingBufferedAdc {
124 _phantom: PhantomData,
125 ring_buf,
126 }
127 }
128}
129
130impl<'d, T: Instance> RingBufferedAdc<'d, T> {
131 fn is_on() -> bool {
132 T::regs().cr2().read().adon()
133 }
134
135 fn stop_adc() {
136 T::regs().cr2().modify(|reg| {
137 reg.set_adon(false);
138 });
139 }
140
141 fn start_adc() {
142 T::regs().cr2().modify(|reg| {
143 reg.set_adon(true);
144 });
145 }
146
147 /// Sets the channel sample time
148 ///
149 /// ## SAFETY:
150 /// - ADON == 0 i.e ADC must not be enabled when this is called.
151 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
152 if ch <= 9 {
153 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
154 } else {
155 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
156 }
157 }
158
159 fn set_channels_sample_time(&mut self, ch: &[u8], sample_time: SampleTime) {
160 let ch_iter = ch.iter();
161 for idx in ch_iter {
162 unsafe {
163 Self::set_channel_sample_time(*idx, sample_time);
164 }
165 }
166 }
167
168 pub fn set_sample_sequence(
169 &mut self,
170 sequence: Sequence,
171 channel: &mut impl AdcChannel<T>,
172 sample_time: SampleTime,
173 ) {
174 let was_on = Self::is_on();
175 if !was_on {
176 Self::start_adc();
177 }
178
179 // Check the sequence is long enough
180 T::regs().sqr1().modify(|r| {
181 let prev: Sequence = r.l().into();
182 if prev < sequence {
183 let new_l: Sequence = sequence;
184 trace!("Setting sequence length from {:?} to {:?}", prev as u8, new_l as u8);
185 r.set_l(sequence.into())
186 } else {
187 r.set_l(prev.into())
188 }
189 });
190
191 // Set this GPIO as an analog input.
192 channel.setup();
193
194 // Set the channel in the right sequence field.
195 match sequence {
196 Sequence::One => T::regs().sqr3().modify(|w| w.set_sq(0, channel.channel())),
197 Sequence::Two => T::regs().sqr3().modify(|w| w.set_sq(1, channel.channel())),
198 Sequence::Three => T::regs().sqr3().modify(|w| w.set_sq(2, channel.channel())),
199 Sequence::Four => T::regs().sqr3().modify(|w| w.set_sq(3, channel.channel())),
200 Sequence::Five => T::regs().sqr3().modify(|w| w.set_sq(4, channel.channel())),
201 Sequence::Six => T::regs().sqr3().modify(|w| w.set_sq(5, channel.channel())),
202 Sequence::Seven => T::regs().sqr2().modify(|w| w.set_sq(0, channel.channel())),
203 Sequence::Eight => T::regs().sqr2().modify(|w| w.set_sq(1, channel.channel())),
204 Sequence::Nine => T::regs().sqr2().modify(|w| w.set_sq(2, channel.channel())),
205 Sequence::Ten => T::regs().sqr2().modify(|w| w.set_sq(3, channel.channel())),
206 Sequence::Eleven => T::regs().sqr2().modify(|w| w.set_sq(4, channel.channel())),
207 Sequence::Twelve => T::regs().sqr2().modify(|w| w.set_sq(5, channel.channel())),
208 Sequence::Thirteen => T::regs().sqr1().modify(|w| w.set_sq(0, channel.channel())),
209 Sequence::Fourteen => T::regs().sqr1().modify(|w| w.set_sq(1, channel.channel())),
210 Sequence::Fifteen => T::regs().sqr1().modify(|w| w.set_sq(2, channel.channel())),
211 Sequence::Sixteen => T::regs().sqr1().modify(|w| w.set_sq(3, channel.channel())),
212 };
213
214 if !was_on {
215 Self::stop_adc();
216 }
217
218 self.set_channels_sample_time(&[channel.channel()], sample_time);
219
220 Self::start_adc();
221 }
222
223 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer.
224 pub fn start(&mut self) -> Result<(), OverrunError> {
225 self.setup_adc();
226 self.ring_buf.clear();
227
228 Ok(())
229 }
230
231 fn stop(&mut self, err: OverrunError) -> Result<usize, OverrunError> {
232 self.teardown_adc();
233 Err(err)
234 }
235
236 /// Stops DMA transfer.
237 /// It does not turn off ADC.
238 /// Calling `start` restarts continuous DMA transfer.
239 ///
240 /// [`start`]: #method.start
241 pub fn teardown_adc(&mut self) {
242 // Stop the DMA transfer
243 self.ring_buf.request_pause();
244
245 let r = T::regs();
246
247 // Stop ADC
248 r.cr2().modify(|reg| {
249 // Stop ADC
250 reg.set_swstart(false);
251 // Stop DMA
252 reg.set_dma(false);
253 });
254
255 r.cr1().modify(|w| {
256 // Disable interrupt for end of conversion
257 w.set_eocie(false);
258 // Disable interrupt for overrun
259 w.set_ovrie(false);
260 });
261
262 clear_interrupt_flags(r);
263
264 compiler_fence(Ordering::SeqCst);
265 }
266
267 fn setup_adc(&mut self) {
268 compiler_fence(Ordering::SeqCst);
269
270 self.ring_buf.start();
271
272 let r = T::regs();
273
274 // Enable ADC
275 let was_on = Self::is_on();
276 if !was_on {
277 r.cr2().modify(|reg| {
278 reg.set_adon(false);
279 reg.set_swstart(false);
280 });
281 }
282
283 // Clear all interrupts
284 r.sr().modify(|regs| {
285 regs.set_eoc(false);
286 regs.set_ovr(false);
287 regs.set_strt(false);
288 });
289
290 r.cr1().modify(|w| {
291 // Enable interrupt for end of conversion
292 w.set_eocie(true);
293 // Enable interrupt for overrun
294 w.set_ovrie(true);
295 // Scanning converisons of multiple channels
296 w.set_scan(true);
297 // Continuous conversion mode
298 w.set_discen(false);
299 });
300
301 r.cr2().modify(|w| {
302 // Enable DMA mode
303 w.set_dma(true);
304 // Enable continuous conversions
305 w.set_cont(true);
306 // DMA requests are issues as long as DMA=1 and data are converted.
307 w.set_dds(vals::Dds::CONTINUOUS);
308 // EOC flag is set at the end of each conversion.
309 w.set_eocs(vals::Eocs::EACH_CONVERSION);
310 });
311
312 // Begin ADC conversions
313 T::regs().cr2().modify(|reg| {
314 reg.set_adon(true);
315 reg.set_swstart(true);
316 });
317
318 super::blocking_delay_us(3);
319 }
320
321 /// Read bytes that are readily available in the ring buffer.
322 /// If no bytes are currently available in the buffer the call waits until the some
323 /// bytes are available (at least one byte and at most half the buffer size)
324 ///
325 /// Background receive is started if `start()` has not been previously called.
326 ///
327 /// Receive in the background is terminated if an error is returned.
328 /// It must then manually be started again by calling `start()` or by re-calling `read()`.
329 pub fn blocking_read<const N: usize>(&mut self, buf: &mut [u16; N]) -> Result<usize, OverrunError> {
330 let r = T::regs();
331
332 // Start background receive if it was not already started
333 if !r.cr2().read().dma() {
334 self.start()?;
335 }
336
337 // Clear overrun flag if set.
338 if r.sr().read().ovr() {
339 return self.stop(OverrunError);
340 }
341
342 loop {
343 match self.ring_buf.read(buf) {
344 Ok((0, _)) => {}
345 Ok((len, _)) => {
346 return Ok(len);
347 }
348 Err(_) => {
349 return self.stop(OverrunError);
350 }
351 }
352 }
353 }
354
355 /// Reads measurements from the DMA ring buffer.
356 ///
357 /// This method fills the provided `measurements` array with ADC readings from the DMA buffer.
358 /// The length of the `measurements` array should be exactly half of the DMA buffer length. Because interrupts are only generated if half or full DMA transfer completes.
359 ///
360 /// Each call to `read` will populate the `measurements` array in the same order as the channels defined with `set_sample_sequence`.
361 /// There will be many sequences worth of measurements in this array because it only returns if at least half of the DMA buffer is filled.
362 /// For example if 3 channels are sampled `measurements` contain: `[sq0 sq1 sq3 sq0 sq1 sq3 sq0 sq1 sq3 sq0 sq1 sq3..]`.
363 ///
364 /// If an error is returned, it indicates a DMA overrun, and the process must be restarted by calling `start` or `read` again.
365 ///
366 /// By default, the ADC fills the DMA buffer as quickly as possible. To control the sample rate, call `teardown_adc` after each readout, and then start the DMA again at the desired interval.
367 /// Note that even if using `teardown_adc` to control the sample rate, with each call to `read`, measurements equivalent to half the size of the DMA buffer are still collected.
368 ///
369 /// Example:
370 /// ```rust,ignore
371 /// const DMA_BUF_LEN: usize = 120;
372 /// let adc_dma_buf = [0u16; DMA_BUF_LEN];
373 /// let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_dma_buf);
374 ///
375 /// adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112);
376 /// adc.set_sample_sequence(Sequence::Two, &mut p.PA1, SampleTime::CYCLES112);
377 /// adc.set_sample_sequence(Sequence::Three, &mut p.PA2, SampleTime::CYCLES112);
378 ///
379 /// let mut measurements = [0u16; DMA_BUF_LEN / 2];
380 /// loop {
381 /// match adc.read(&mut measurements).await {
382 /// Ok(_) => {
383 /// defmt::info!("adc1: {}", measurements);
384 /// // Only needed to manually control sample rate.
385 /// adc.teardown_adc();
386 /// }
387 /// Err(e) => {
388 /// defmt::warn!("Error: {:?}", e);
389 /// // DMA overrun, next call to `read` restarts ADC.
390 /// }
391 /// }
392 ///
393 /// // Manually control sample rate.
394 /// Timer::after_millis(100).await;
395 /// }
396 /// ```
397 ///
398 ///
399 /// [`set_sample_sequence`]: #method.set_sample_sequence
400 /// [`teardown_adc`]: #method.teardown_adc
401 /// [`start`]: #method.start
402 pub async fn read<const N: usize>(&mut self, measurements: &mut [u16; N]) -> Result<usize, OverrunError> {
403 assert_eq!(
404 self.ring_buf.capacity() / 2,
405 N,
406 "Buffer size must be half the size of the ring buffer"
407 );
408
409 let r = T::regs();
410
411 // Start background receive if it was not already started
412 if !r.cr2().read().dma() {
413 self.start()?;
414 }
415
416 // Clear overrun flag if set.
417 if r.sr().read().ovr() {
418 return self.stop(OverrunError);
419 }
420 match self.ring_buf.read_exact(measurements).await {
421 Ok(len) => Ok(len),
422 Err(_) => self.stop(OverrunError),
423 }
424 }
425}
426
427impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
428 fn drop(&mut self) {
429 self.teardown_adc();
430 rcc::disable::<T>();
431 }
432}
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 93ec78548..90c6294d2 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,11 +1,22 @@
1use core::mem;
2use core::sync::atomic::{Ordering, compiler_fence};
3
1use super::blocking_delay_us; 4use super::blocking_delay_us;
2use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; 5use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel};
6use crate::pac::adc::vals;
3use crate::peripherals::ADC1; 7use crate::peripherals::ADC1;
4use crate::time::Hertz; 8use crate::time::Hertz;
5use crate::{Peri, rcc}; 9use crate::{Peri, rcc};
6 10
7mod ringbuffered_v2; 11mod ringbuffered;
8pub use ringbuffered_v2::{RingBufferedAdc, Sequence}; 12pub use ringbuffered::RingBufferedAdc;
13
14fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
15 r.sr().modify(|regs| {
16 regs.set_eoc(false);
17 regs.set_ovr(false);
18 });
19}
9 20
10/// Default VREF voltage used for sample conversion to millivolts. 21/// Default VREF voltage used for sample conversion to millivolts.
11pub const VREF_DEFAULT_MV: u32 = 3300; 22pub const VREF_DEFAULT_MV: u32 = 3300;
@@ -112,6 +123,98 @@ where
112 } 123 }
113 } 124 }
114 125
126 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
127 ///
128 /// The `dma_buf` should be large enough to prevent DMA buffer overrun.
129 /// The length of the `dma_buf` should be a multiple of the ADC channel count.
130 /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements.
131 ///
132 /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length.
133 /// It is critical to call `read` frequently to prevent DMA buffer overrun.
134 ///
135 /// [`read`]: #method.read
136 pub fn into_ring_buffered<'a>(
137 self,
138 dma: Peri<'d, impl RxDma<T>>,
139 dma_buf: &'d mut [u16],
140 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>,
141 ) -> RingBufferedAdc<'d, T> {
142 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
143
144 T::regs().cr2().modify(|reg| {
145 reg.set_adon(true);
146 });
147
148 // Check the sequence is long enough
149 T::regs().sqr1().modify(|r| {
150 r.set_l((sequence.len() - 1).try_into().unwrap());
151 });
152
153 for (i, (channel, sample_time)) in sequence.enumerate() {
154 // Set this GPIO as an analog input.
155 channel.setup();
156
157 // Set the channel in the right sequence field.
158 T::regs().sqr3().modify(|w| w.set_sq(i, channel.channel()));
159
160 Self::set_channel_sample_time(channel.channel(), sample_time);
161 }
162
163 compiler_fence(Ordering::SeqCst);
164
165 let r = T::regs();
166
167 // Clear all interrupts
168 r.sr().modify(|regs| {
169 regs.set_eoc(false);
170 regs.set_ovr(false);
171 regs.set_strt(false);
172 });
173
174 r.cr1().modify(|w| {
175 // Enable interrupt for end of conversion
176 w.set_eocie(true);
177 // Enable interrupt for overrun
178 w.set_ovrie(true);
179 // Scanning converisons of multiple channels
180 w.set_scan(true);
181 // Continuous conversion mode
182 w.set_discen(false);
183 });
184
185 r.cr2().modify(|w| {
186 // Enable DMA mode
187 w.set_dma(true);
188 // Enable continuous conversions
189 w.set_cont(true);
190 // DMA requests are issues as long as DMA=1 and data are converted.
191 w.set_dds(vals::Dds::CONTINUOUS);
192 // EOC flag is set at the end of each conversion.
193 w.set_eocs(vals::Eocs::EACH_CONVERSION);
194 });
195
196 // Don't disable the clock
197 mem::forget(self);
198
199 RingBufferedAdc::new(dma, dma_buf)
200 }
201
202 pub(super) fn start() {
203 // Begin ADC conversions
204 T::regs().cr2().modify(|reg| {
205 reg.set_adon(true);
206 reg.set_swstart(true);
207 });
208 }
209
210 pub(super) fn stop() {
211 // Stop ADC
212 T::regs().cr2().modify(|reg| {
213 // Stop ADC
214 reg.set_swstart(false);
215 });
216 }
217
115 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 218 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
116 self.sample_time = sample_time; 219 self.sample_time = sample_time;
117 } 220 }
@@ -198,6 +301,31 @@ where
198 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 301 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
199 } 302 }
200 } 303 }
304
305 pub(super) fn teardown_adc() {
306 let r = T::regs();
307
308 // Stop ADC
309 r.cr2().modify(|reg| {
310 // Stop ADC
311 reg.set_swstart(false);
312 // Stop ADC
313 reg.set_adon(false);
314 // Stop DMA
315 reg.set_dma(false);
316 });
317
318 r.cr1().modify(|w| {
319 // Disable interrupt for end of conversion
320 w.set_eocie(false);
321 // Disable interrupt for overrun
322 w.set_ovrie(false);
323 });
324
325 clear_interrupt_flags(r);
326
327 compiler_fence(Ordering::SeqCst);
328 }
201} 329}
202 330
203impl<'d, T: Instance> Drop for Adc<'d, T> { 331impl<'d, T: Instance> Drop for Adc<'d, T> {
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 47632263b..170b08a25 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -12,6 +12,13 @@ pub use pac::adc::vals::{Ovsr, Ovss, Presc};
12use super::{ 12use super::{
13 Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, 13 Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us,
14}; 14};
15
16#[cfg(any(adc_v3, adc_g0, adc_u0))]
17mod ringbuffered;
18
19#[cfg(any(adc_v3, adc_g0, adc_u0))]
20use ringbuffered::RingBufferedAdc;
21
15use crate::dma::Transfer; 22use crate::dma::Transfer;
16use crate::{Peri, pac, rcc}; 23use crate::{Peri, pac, rcc};
17 24
@@ -174,6 +181,38 @@ impl<'d, T: Instance> Adc<'d, T> {
174 blocking_delay_us(1); 181 blocking_delay_us(1);
175 } 182 }
176 183
184 #[cfg(any(adc_v3, adc_g0, adc_u0))]
185 pub(super) fn start() {
186 // Start adc conversion
187 T::regs().cr().modify(|reg| {
188 reg.set_adstart(true);
189 });
190 }
191
192 #[cfg(any(adc_v3, adc_g0, adc_u0))]
193 pub(super) fn stop() {
194 // Stop adc conversion
195 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
196 T::regs().cr().modify(|reg| {
197 reg.set_adstp(true);
198 });
199 while T::regs().cr().read().adstart() {}
200 }
201 }
202
203 #[cfg(any(adc_v3, adc_g0, adc_u0))]
204 pub(super) fn teardown_adc() {
205 //disable dma control
206 #[cfg(not(any(adc_g0, adc_u0)))]
207 T::regs().cfgr().modify(|reg| {
208 reg.set_dmaen(false);
209 });
210 #[cfg(any(adc_g0, adc_u0))]
211 T::regs().cfgr1().modify(|reg| {
212 reg.set_dmaen(false);
213 });
214 }
215
177 /// Initialize the ADC leaving any analog clock at reset value. 216 /// Initialize the ADC leaving any analog clock at reset value.
178 /// For G0 and WL, this is the async clock without prescaler. 217 /// For G0 and WL, this is the async clock without prescaler.
179 pub fn new(adc: Peri<'d, T>) -> Self { 218 pub fn new(adc: Peri<'d, T>) -> Self {
@@ -423,6 +462,9 @@ impl<'d, T: Instance> Adc<'d, T> {
423 "Asynchronous read sequence cannot be more than 16 in length" 462 "Asynchronous read sequence cannot be more than 16 in length"
424 ); 463 );
425 464
465 #[cfg(all(feature = "low-power", stm32wlex))]
466 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
467
426 // Ensure no conversions are ongoing and ADC is enabled. 468 // Ensure no conversions are ongoing and ADC is enabled.
427 Self::cancel_conversions(); 469 Self::cancel_conversions();
428 self.enable(); 470 self.enable();
@@ -559,6 +601,137 @@ impl<'d, T: Instance> Adc<'d, T> {
559 }); 601 });
560 } 602 }
561 603
604 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
605 ///
606 /// The `dma_buf` should be large enough to prevent DMA buffer overrun.
607 /// The length of the `dma_buf` should be a multiple of the ADC channel count.
608 /// For example, if 3 channels are measured, its length can be 3 * 40 = 120 measurements.
609 ///
610 /// `read` method is used to read out measurements from the DMA ring buffer, and its buffer should be exactly half of the `dma_buf` length.
611 /// It is critical to call `read` frequently to prevent DMA buffer overrun.
612 ///
613 /// [`read`]: #method.read
614 #[cfg(any(adc_v3, adc_g0, adc_u0))]
615 pub fn into_ring_buffered<'a>(
616 &mut self,
617 dma: Peri<'a, impl RxDma<T>>,
618 dma_buf: &'a mut [u16],
619 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>,
620 ) -> RingBufferedAdc<'a, T> {
621 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
622 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
623 assert!(
624 sequence.len() <= 16,
625 "Asynchronous read sequence cannot be more than 16 in length"
626 );
627 // reset conversions and enable the adc
628 Self::cancel_conversions();
629 self.enable();
630
631 //adc side setup
632
633 // Set sequence length
634 #[cfg(not(any(adc_g0, adc_u0)))]
635 T::regs().sqr1().modify(|w| {
636 w.set_l(sequence.len() as u8 - 1);
637 });
638
639 #[cfg(adc_g0)]
640 {
641 let mut sample_times = Vec::<SampleTime, SAMPLE_TIMES_CAPACITY>::new();
642
643 T::regs().chselr().write(|chselr| {
644 T::regs().smpr().write(|smpr| {
645 for (channel, sample_time) in sequence {
646 chselr.set_chsel(channel.channel.into(), true);
647 if let Some(i) = sample_times.iter().position(|&t| t == sample_time) {
648 smpr.set_smpsel(channel.channel.into(), (i as u8).into());
649 } else {
650 smpr.set_sample_time(sample_times.len(), sample_time);
651 if let Err(_) = sample_times.push(sample_time) {
652 panic!(
653 "Implementation is limited to {} unique sample times among all channels.",
654 SAMPLE_TIMES_CAPACITY
655 );
656 }
657 }
658 }
659 })
660 });
661 }
662 #[cfg(not(adc_g0))]
663 {
664 #[cfg(adc_u0)]
665 let mut channel_mask = 0;
666
667 // Configure channels and ranks
668 for (_i, (channel, sample_time)) in sequence.enumerate() {
669 Self::configure_channel(channel, sample_time);
670
671 // Each channel is sampled according to sequence
672 #[cfg(not(any(adc_g0, adc_u0)))]
673 match _i {
674 0..=3 => {
675 T::regs().sqr1().modify(|w| {
676 w.set_sq(_i, channel.channel());
677 });
678 }
679 4..=8 => {
680 T::regs().sqr2().modify(|w| {
681 w.set_sq(_i - 4, channel.channel());
682 });
683 }
684 9..=13 => {
685 T::regs().sqr3().modify(|w| {
686 w.set_sq(_i - 9, channel.channel());
687 });
688 }
689 14..=15 => {
690 T::regs().sqr4().modify(|w| {
691 w.set_sq(_i - 14, channel.channel());
692 });
693 }
694 _ => unreachable!(),
695 }
696
697 #[cfg(adc_u0)]
698 {
699 channel_mask |= 1 << channel.channel();
700 }
701 }
702
703 // On G0 and U0 enabled channels are sampled from 0 to last channel.
704 // It is possible to add up to 8 sequences if CHSELRMOD = 1.
705 // However for supporting more than 8 channels alternative CHSELRMOD = 0 approach is used.
706 #[cfg(adc_u0)]
707 T::regs().chselr().modify(|reg| {
708 reg.set_chsel(channel_mask);
709 });
710 }
711 // Set continuous mode with Circular dma.
712 // Clear overrun flag before starting transfer.
713 T::regs().isr().modify(|reg| {
714 reg.set_ovr(true);
715 });
716
717 #[cfg(not(any(adc_g0, adc_u0)))]
718 T::regs().cfgr().modify(|reg| {
719 reg.set_discen(false);
720 reg.set_cont(true);
721 reg.set_dmacfg(Dmacfg::CIRCULAR);
722 reg.set_dmaen(true);
723 });
724 #[cfg(any(adc_g0, adc_u0))]
725 T::regs().cfgr1().modify(|reg| {
726 reg.set_discen(false);
727 reg.set_cont(true);
728 reg.set_dmacfg(Dmacfg::CIRCULAR);
729 reg.set_dmaen(true);
730 });
731
732 RingBufferedAdc::new(dma, dma_buf)
733 }
734
562 #[cfg(not(adc_g0))] 735 #[cfg(not(adc_g0))]
563 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) { 736 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
564 // RM0492, RM0481, etc. 737 // RM0492, RM0481, etc.
diff --git a/embassy-stm32/src/backup_sram.rs b/embassy-stm32/src/backup_sram.rs
new file mode 100644
index 000000000..31b373c6c
--- /dev/null
+++ b/embassy-stm32/src/backup_sram.rs
@@ -0,0 +1,28 @@
1//! Battary backed SRAM
2
3use core::slice;
4
5use embassy_hal_internal::Peri;
6
7use crate::_generated::{BKPSRAM_BASE, BKPSRAM_SIZE};
8use crate::peripherals::BKPSRAM;
9
10/// Struct used to initilize backup sram
11pub struct BackupMemory {}
12
13impl BackupMemory {
14 /// Setup battery backed sram
15 ///
16 /// Returns slice to sram and whether the sram was retained
17 pub fn new(_backup_sram: Peri<'static, BKPSRAM>) -> (&'static mut [u8], bool) {
18 // Assert bksram has been enabled in rcc
19 assert!(crate::pac::PWR.bdcr().read().bren() == crate::pac::pwr::vals::Retention::PRESERVED);
20
21 unsafe {
22 (
23 slice::from_raw_parts_mut(BKPSRAM_BASE as *mut u8, BKPSRAM_SIZE),
24 critical_section::with(|_| crate::rcc::BKSRAM_RETAINED),
25 )
26 }
27 }
28}
diff --git a/embassy-stm32/src/can/fd/config.rs b/embassy-stm32/src/can/fd/config.rs
index e08349f02..4fe634ce4 100644
--- a/embassy-stm32/src/can/fd/config.rs
+++ b/embassy-stm32/src/can/fd/config.rs
@@ -360,6 +360,8 @@ pub struct FdCanConfig {
360 pub global_filter: GlobalFilter, 360 pub global_filter: GlobalFilter,
361 /// TX buffer mode (FIFO or priority queue) 361 /// TX buffer mode (FIFO or priority queue)
362 pub tx_buffer_mode: TxBufferMode, 362 pub tx_buffer_mode: TxBufferMode,
363 /// Automatic recovery from bus off state
364 pub automatic_bus_off_recovery: bool,
363} 365}
364 366
365impl FdCanConfig { 367impl FdCanConfig {
@@ -456,6 +458,16 @@ impl FdCanConfig {
456 self.tx_buffer_mode = txbm; 458 self.tx_buffer_mode = txbm;
457 self 459 self
458 } 460 }
461
462 /// Enables or disables automatic recovery from bus off state
463 ///
464 /// Automatic recovery is performed by clearing the INIT bit in the CCCR register if
465 /// the BO bit is active in the IR register in the IT0 interrupt.
466 #[inline]
467 pub const fn set_automatic_bus_off_recovery(mut self, enabled: bool) -> Self {
468 self.automatic_bus_off_recovery = enabled;
469 self
470 }
459} 471}
460 472
461impl Default for FdCanConfig { 473impl Default for FdCanConfig {
@@ -474,6 +486,7 @@ impl Default for FdCanConfig {
474 timestamp_source: TimestampSource::None, 486 timestamp_source: TimestampSource::None,
475 global_filter: GlobalFilter::default(), 487 global_filter: GlobalFilter::default(),
476 tx_buffer_mode: TxBufferMode::Priority, 488 tx_buffer_mode: TxBufferMode::Priority,
489 automatic_bus_off_recovery: true,
477 } 490 }
478 } 491 }
479} 492}
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index a142a6d63..9883aff57 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -53,7 +53,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
53 regs.ir().write(|w| w.set_tefn(true)); 53 regs.ir().write(|w| w.set_tefn(true));
54 } 54 }
55 55
56 T::info().state.lock(|s| { 56 let recover_from_bo = T::info().state.lock(|s| {
57 let state = s.borrow_mut(); 57 let state = s.borrow_mut();
58 match &state.tx_mode { 58 match &state.tx_mode {
59 TxMode::NonBuffered(waker) => waker.wake(), 59 TxMode::NonBuffered(waker) => waker.wake(),
@@ -85,11 +85,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup
85 if ir.rfn(1) { 85 if ir.rfn(1) {
86 state.rx_mode.on_interrupt::<T>(1, state.ns_per_timer_tick); 86 state.rx_mode.on_interrupt::<T>(1, state.ns_per_timer_tick);
87 } 87 }
88
89 state.automatic_bus_off_recovery
88 }); 90 });
89 91
90 if ir.bo() { 92 if ir.bo() {
91 regs.ir().write(|w| w.set_bo(true)); 93 regs.ir().write(|w| w.set_bo(true));
92 if regs.psr().read().bo() { 94 if let Some(true) = recover_from_bo
95 && regs.psr().read().bo()
96 {
93 // Initiate bus-off recovery sequence by resetting CCCR.INIT 97 // Initiate bus-off recovery sequence by resetting CCCR.INIT
94 regs.cccr().modify(|w| w.set_init(false)); 98 regs.cccr().modify(|w| w.set_init(false));
95 } 99 }
@@ -263,7 +267,9 @@ impl<'d> CanConfigurator<'d> {
263 pub fn start(self, mode: OperatingMode) -> Can<'d> { 267 pub fn start(self, mode: OperatingMode) -> Can<'d> {
264 let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit); 268 let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit);
265 self.info.state.lock(|s| { 269 self.info.state.lock(|s| {
266 s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick; 270 let mut state = s.borrow_mut();
271 state.ns_per_timer_tick = ns_per_timer_tick;
272 state.automatic_bus_off_recovery = Some(self.config.automatic_bus_off_recovery);
267 }); 273 });
268 self.info.regs.into_mode(self.config, mode); 274 self.info.regs.into_mode(self.config, mode);
269 Can { 275 Can {
@@ -861,7 +867,7 @@ struct State {
861 sender_instance_count: usize, 867 sender_instance_count: usize,
862 tx_pin_port: Option<u8>, 868 tx_pin_port: Option<u8>,
863 rx_pin_port: Option<u8>, 869 rx_pin_port: Option<u8>,
864 870 automatic_bus_off_recovery: Option<bool>, // controlled by CanConfigurator::start()
865 pub err_waker: AtomicWaker, 871 pub err_waker: AtomicWaker,
866} 872}
867 873
@@ -876,6 +882,7 @@ impl State {
876 sender_instance_count: 0, 882 sender_instance_count: 0,
877 tx_pin_port: None, 883 tx_pin_port: None,
878 rx_pin_port: None, 884 rx_pin_port: None,
885 automatic_bus_off_recovery: None,
879 } 886 }
880 } 887 }
881} 888}
diff --git a/embassy-stm32/src/dsihost.rs b/embassy-stm32/src/dsihost.rs
index fd1682d2b..59a2cbcdb 100644
--- a/embassy-stm32/src/dsihost.rs
+++ b/embassy-stm32/src/dsihost.rs
@@ -121,17 +121,15 @@ impl<'d, T: Instance> DsiHost<'d, T> {
121 121
122 /// DCS or Generic short/long write command 122 /// DCS or Generic short/long write command
123 pub fn write_cmd(&mut self, channel_id: u8, address: u8, data: &[u8]) -> Result<(), Error> { 123 pub fn write_cmd(&mut self, channel_id: u8, address: u8, data: &[u8]) -> Result<(), Error> {
124 assert!(data.len() > 0); 124 match data.len() {
125 125 0 => self.short_write(channel_id, PacketType::DcsShortPktWriteP0, address, 0),
126 if data.len() == 1 { 126 1 => self.short_write(channel_id, PacketType::DcsShortPktWriteP1, address, data[0]),
127 self.short_write(channel_id, PacketType::DcsShortPktWriteP1, address, data[0]) 127 _ => self.long_write(
128 } else {
129 self.long_write(
130 channel_id, 128 channel_id,
131 PacketType::DcsLongPktWrite, // FIXME: This might be a generic long packet, as well... 129 PacketType::DcsLongPktWrite, // FIXME: This might be a generic long packet, as well...
132 address, 130 address,
133 data, 131 data,
134 ) 132 ),
135 } 133 }
136 } 134 }
137 135
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 12600d4eb..2f5c3406a 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -71,7 +71,7 @@ unsafe fn on_irq() {
71 } 71 }
72 72
73 #[cfg(feature = "low-power")] 73 #[cfg(feature = "low-power")]
74 crate::low_power::on_wakeup_irq(); 74 crate::low_power::Executor::on_wakeup_irq();
75} 75}
76 76
77struct BitIter(u32); 77struct BitIter(u32);
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs
index cd23cda5c..b3281f2d5 100644
--- a/embassy-stm32/src/flash/l.rs
+++ b/embassy-stm32/src/flash/l.rs
@@ -96,14 +96,20 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
96 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l5))] 96 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l5))]
97 { 97 {
98 let idx = (sector.start - super::FLASH_BASE as u32) / super::BANK1_REGION.erase_size as u32; 98 let idx = (sector.start - super::FLASH_BASE as u32) / super::BANK1_REGION.erase_size as u32;
99 #[cfg(any(flash_l4, flash_l5))]
100 let pgn = super::BANK1_REGION.size as u32 / super::BANK1_REGION.erase_size as u32;
99 101
100 #[cfg(flash_l4)] 102 #[cfg(flash_l4)]
101 let (idx, bank) = if idx > 255 { (idx - 256, true) } else { (idx, false) }; 103 let (idx, bank) = if idx > (pgn - 1) {
104 (idx - pgn, true)
105 } else {
106 (idx, false)
107 };
102 108
103 #[cfg(flash_l5)] 109 #[cfg(flash_l5)]
104 let (idx, bank) = if pac::FLASH.optr().read().dbank() { 110 let (idx, bank) = if pac::FLASH.optr().read().dbank() {
105 if idx > 255 { 111 if idx > (pgn - 1) {
106 (idx - 256, Some(true)) 112 (idx - pgn, Some(true))
107 } else { 113 } else {
108 (idx, Some(false)) 114 (idx, Some(false))
109 } 115 }
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 8ecfbc522..a7c6c90bb 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -236,6 +236,42 @@ impl<'d, T: Instance> Fmc<'d, T> {
236 (sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) 236 (sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin)
237 ] 237 ]
238 )); 238 ));
239
240 fmc_sdram_constructor!(sdram_a13bits_d16bits_4banks_bank1: (
241 bank: stm32_fmc::SdramTargetBank::Bank1,
242 addr: [
243 (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin), (a12: A12Pin)
244 ],
245 ba: [(ba0: BA0Pin), (ba1: BA1Pin)],
246 d: [
247 (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin),
248 (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin)
249 ],
250 nbl: [
251 (nbl0: NBL0Pin), (nbl1: NBL1Pin)
252 ],
253 ctrl: [
254 (sdcke: SDCKE0Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE0Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin)
255 ]
256 ));
257
258 fmc_sdram_constructor!(sdram_a13bits_d16bits_4banks_bank2: (
259 bank: stm32_fmc::SdramTargetBank::Bank2,
260 addr: [
261 (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin), (a12: A12Pin)
262 ],
263 ba: [(ba0: BA0Pin), (ba1: BA1Pin)],
264 d: [
265 (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin),
266 (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin)
267 ],
268 nbl: [
269 (nbl0: NBL0Pin), (nbl1: NBL1Pin)
270 ],
271 ctrl: [
272 (sdcke: SDCKE1Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE1Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin)
273 ]
274 ));
239} 275}
240 276
241trait SealedInstance: crate::rcc::RccPeripheral { 277trait SealedInstance: crate::rcc::RccPeripheral {
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 6fece5eb2..6c6807479 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -10,6 +10,7 @@ pub use traits::Instance;
10use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 10use crate::gpio::{AfType, AnyPin, OutputType, Speed};
11use crate::rcc; 11use crate::rcc;
12use crate::time::Hertz; 12use crate::time::Hertz;
13pub use crate::timer::simple_pwm::PwmPinConfig;
13 14
14/// HRTIM burst controller instance. 15/// HRTIM burst controller instance.
15pub struct BurstController<T: Instance> { 16pub struct BurstController<T: Instance> {
@@ -73,7 +74,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
73} 74}
74 75
75macro_rules! advanced_channel_impl { 76macro_rules! advanced_channel_impl {
76 ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => { 77 ($new_chx:ident, $new_chx_with_config:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
77 impl<'d, T: Instance> PwmPin<'d, T, $channel<T>> { 78 impl<'d, T: Instance> PwmPin<'d, T, $channel<T>> {
78 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] 79 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
79 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self { 80 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self {
@@ -86,6 +87,21 @@ macro_rules! advanced_channel_impl {
86 phantom: PhantomData, 87 phantom: PhantomData,
87 } 88 }
88 } 89 }
90
91 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with a specific configuration.")]
92 pub fn $new_chx_with_config(
93 pin: Peri<'d, impl $pin_trait<T>>,
94 pin_config: PwmPinConfig,
95 ) -> Self {
96 critical_section::with(|_| {
97 pin.set_low();
98 set_as_af!(pin, AfType::output(pin_config.output_type, pin_config.speed));
99 });
100 PwmPin {
101 _pin: pin.into(),
102 phantom: PhantomData,
103 }
104 }
89 } 105 }
90 106
91 impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel<T>> { 107 impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel<T>> {
@@ -100,6 +116,21 @@ macro_rules! advanced_channel_impl {
100 phantom: PhantomData, 116 phantom: PhantomData,
101 } 117 }
102 } 118 }
119
120 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance with a specific configuration.")]
121 pub fn $new_chx_with_config(
122 pin: Peri<'d, impl $complementary_pin_trait<T>>,
123 pin_config: PwmPinConfig,
124 ) -> Self {
125 critical_section::with(|_| {
126 pin.set_low();
127 set_as_af!(pin, AfType::output(pin_config.output_type, pin_config.speed));
128 });
129 ComplementaryPwmPin {
130 _pin: pin.into(),
131 phantom: PhantomData,
132 }
133 }
103 } 134 }
104 135
105 impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> { 136 impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> {
@@ -111,13 +142,55 @@ macro_rules! advanced_channel_impl {
111 }; 142 };
112} 143}
113 144
114advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin); 145advanced_channel_impl!(
115advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin); 146 new_cha,
116advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin); 147 new_cha_with_config,
117advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin); 148 ChA,
118advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin); 149 0,
150 ChannelAPin,
151 ChannelAComplementaryPin
152);
153advanced_channel_impl!(
154 new_chb,
155 new_chb_with_config,
156 ChB,
157 1,
158 ChannelBPin,
159 ChannelBComplementaryPin
160);
161advanced_channel_impl!(
162 new_chc,
163 new_chc_with_config,
164 ChC,
165 2,
166 ChannelCPin,
167 ChannelCComplementaryPin
168);
169advanced_channel_impl!(
170 new_chd,
171 new_chd_with_config,
172 ChD,
173 3,
174 ChannelDPin,
175 ChannelDComplementaryPin
176);
177advanced_channel_impl!(
178 new_che,
179 new_che_with_config,
180 ChE,
181 4,
182 ChannelEPin,
183 ChannelEComplementaryPin
184);
119#[cfg(hrtim_v2)] 185#[cfg(hrtim_v2)]
120advanced_channel_impl!(new_chf, ChF, 5, ChannelFPin, ChannelFComplementaryPin); 186advanced_channel_impl!(
187 new_chf,
188 new_chf_with_config,
189 ChF,
190 5,
191 ChannelFPin,
192 ChannelFComplementaryPin
193);
121 194
122/// Struct used to divide a high resolution timer into multiple channels 195/// Struct used to divide a high resolution timer into multiple channels
123pub struct AdvancedPwm<'d, T: Instance> { 196pub struct AdvancedPwm<'d, T: Instance> {
diff --git a/embassy-stm32/src/i2c/config.rs b/embassy-stm32/src/i2c/config.rs
index 4e3b736c7..74fac14b2 100644
--- a/embassy-stm32/src/i2c/config.rs
+++ b/embassy-stm32/src/i2c/config.rs
@@ -4,7 +4,7 @@ use crate::gpio::{AfType, OutputType, Speed};
4use crate::time::Hertz; 4use crate::time::Hertz;
5 5
6#[repr(u8)] 6#[repr(u8)]
7#[derive(Copy, Clone)] 7#[derive(Debug, Copy, Clone)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))] 8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9/// Bits of the I2C OA2 register to mask out. 9/// Bits of the I2C OA2 register to mask out.
10pub enum AddrMask { 10pub enum AddrMask {
@@ -60,7 +60,7 @@ impl Address {
60 } 60 }
61} 61}
62 62
63#[derive(Copy, Clone)] 63#[derive(Debug, Copy, Clone)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))] 64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65/// The second Own Address register. 65/// The second Own Address register.
66pub struct OA2 { 66pub struct OA2 {
@@ -70,7 +70,7 @@ pub struct OA2 {
70 pub mask: AddrMask, 70 pub mask: AddrMask,
71} 71}
72 72
73#[derive(Copy, Clone)] 73#[derive(Debug, Copy, Clone)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75/// The Own Address(es) of the I2C peripheral. 75/// The Own Address(es) of the I2C peripheral.
76pub enum OwnAddresses { 76pub enum OwnAddresses {
@@ -88,7 +88,7 @@ pub enum OwnAddresses {
88} 88}
89 89
90/// Slave Configuration 90/// Slave Configuration
91#[derive(Copy, Clone)] 91#[derive(Debug, Copy, Clone)]
92#[cfg_attr(feature = "defmt", derive(defmt::Format))] 92#[cfg_attr(feature = "defmt", derive(defmt::Format))]
93pub struct SlaveAddrConfig { 93pub struct SlaveAddrConfig {
94 /// Target Address(es) 94 /// Target Address(es)
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index f4bf55d34..ee60c3f44 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -219,6 +219,7 @@ impl<'d, M: Mode> I2c<'d, M, Master> {
219 sda, 219 sda,
220 }, 220 },
221 }; 221 };
222
222 this.enable_and_init(config); 223 this.enable_and_init(config);
223 224
224 this 225 this
@@ -437,15 +438,15 @@ impl<'d, IM: MasterMode> embedded_hal_async::i2c::I2c for I2c<'d, Async, IM> {
437 438
438/// Frame type in I2C transaction. 439/// Frame type in I2C transaction.
439/// 440///
440/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST 441/// This tells each method what kind of frame to use, to generate a (repeated) start condition (ST
441/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an 442/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an
442/// ACK or NACK after the last byte received. 443/// ACK or NACK after the last byte received.
443/// 444///
444/// For write operations, the following options are identical because they differ only in the (N)ACK 445/// For write operations, the following options are identical because they differ only in the (N)ACK
445/// treatment relevant for read operations: 446/// treatment relevant for read operations:
446/// 447///
447/// - `FirstFrame` and `FirstAndNextFrame` 448/// - `FirstFrame` and `FirstAndNextFrame` behave identically for writes
448/// - `NextFrame` and `LastFrameNoStop` 449/// - `NextFrame` and `LastFrameNoStop` behave identically for writes
449/// 450///
450/// Abbreviations used below: 451/// Abbreviations used below:
451/// 452///
@@ -474,7 +475,7 @@ enum FrameOptions {
474 475
475#[allow(dead_code)] 476#[allow(dead_code)]
476impl FrameOptions { 477impl FrameOptions {
477 /// Sends start or repeated start condition before transfer. 478 /// Returns true if a start or repeated start condition should be generated before this operation.
478 fn send_start(self) -> bool { 479 fn send_start(self) -> bool {
479 match self { 480 match self {
480 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, 481 Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true,
@@ -482,7 +483,7 @@ impl FrameOptions {
482 } 483 }
483 } 484 }
484 485
485 /// Sends stop condition after transfer. 486 /// Returns true if a stop condition should be generated after this operation.
486 fn send_stop(self) -> bool { 487 fn send_stop(self) -> bool {
487 match self { 488 match self {
488 Self::FirstAndLastFrame | Self::LastFrame => true, 489 Self::FirstAndLastFrame | Self::LastFrame => true,
@@ -490,7 +491,10 @@ impl FrameOptions {
490 } 491 }
491 } 492 }
492 493
493 /// Sends NACK after last byte received, indicating end of read operation. 494 /// Returns true if NACK should be sent after the last byte received in a read operation.
495 ///
496 /// This signals the end of a read sequence and releases the bus for the master's
497 /// next transmission (or stop condition).
494 fn send_nack(self) -> bool { 498 fn send_nack(self) -> bool {
495 match self { 499 match self {
496 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, 500 Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true,
@@ -499,24 +503,44 @@ impl FrameOptions {
499 } 503 }
500} 504}
501 505
502/// Iterates over operations in transaction. 506/// Analyzes I2C transaction operations and assigns appropriate frame to each.
507///
508/// This function processes a sequence of I2C operations and determines the correct
509/// frame configuration for each operation to ensure proper I2C protocol compliance.
510/// It handles the complex logic of:
511///
512/// - Generating start conditions for the first operation of each type (read/write)
513/// - Generating stop conditions for the final operation in the entire transaction
514/// - Managing ACK/NACK behavior for read operations, including merging consecutive reads
515/// - Ensuring proper bus handoff between different operation types
516///
517/// **Transaction Contract Compliance:**
518/// The frame assignments ensure compliance with the embedded-hal I2C transaction contract,
519/// where consecutive operations of the same type are logically merged while maintaining
520/// proper protocol boundaries.
503/// 521///
504/// Returns necessary frame options for each operation to uphold the [transaction contract] and have 522/// **Error Handling:**
505/// the right start/stop/(N)ACK conditions on the wire. 523/// Returns an error if any read operation has an empty buffer, as this would create
524/// an invalid I2C transaction that could halt mid-execution.
525///
526/// # Arguments
527/// * `operations` - Mutable slice of I2C operations from embedded-hal
528///
529/// # Returns
530/// An iterator over (operation, frame) pairs, or an error if the transaction is invalid
506/// 531///
507/// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
508#[allow(dead_code)] 532#[allow(dead_code)]
509fn operation_frames<'a, 'b: 'a>( 533fn operation_frames<'a, 'b: 'a>(
510 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>], 534 operations: &'a mut [embedded_hal_1::i2c::Operation<'b>],
511) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> { 535) -> Result<impl IntoIterator<Item = (&'a mut embedded_hal_1::i2c::Operation<'b>, FrameOptions)>, Error> {
512 use embedded_hal_1::i2c::Operation::{Read, Write}; 536 use embedded_hal_1::i2c::Operation::{Read, Write};
513 537
514 // Check empty read buffer before starting transaction. Otherwise, we would risk halting with an 538 // Validate that no read operations have empty buffers before starting the transaction.
515 // error in the middle of the transaction. 539 // Empty read operations would risk halting with an error mid-transaction.
516 // 540 //
517 // In principle, we could allow empty read frames within consecutive read operations, as long as 541 // Note: We could theoretically allow empty read operations within consecutive read
518 // at least one byte remains in the final (merged) read operation, but that makes the logic more 542 // sequences as long as the final merged read has at least one byte, but this would
519 // complicated and error-prone. 543 // complicate the logic significantly and create error-prone edge cases.
520 if operations.iter().any(|op| match op { 544 if operations.iter().any(|op| match op {
521 Read(read) => read.is_empty(), 545 Read(read) => read.is_empty(),
522 Write(_) => false, 546 Write(_) => false,
@@ -525,46 +549,52 @@ fn operation_frames<'a, 'b: 'a>(
525 } 549 }
526 550
527 let mut operations = operations.iter_mut().peekable(); 551 let mut operations = operations.iter_mut().peekable();
528 552 let mut next_first_operation = true;
529 let mut next_first_frame = true;
530 553
531 Ok(iter::from_fn(move || { 554 Ok(iter::from_fn(move || {
532 let op = operations.next()?; 555 let current_op = operations.next()?;
533 556
534 // Is `op` first frame of its type? 557 // Determine if this is the first operation of its type (read or write)
535 let first_frame = next_first_frame; 558 let is_first_of_type = next_first_operation;
536 let next_op = operations.peek(); 559 let next_op = operations.peek();
537 560
538 // Get appropriate frame options as combination of the following properties: 561 // Compute the appropriate frame based on three key properties:
539 // 562 //
540 // - For each first operation of its type, generate a (repeated) start condition. 563 // 1. **Start Condition**: Generate (repeated) start for first operation of each type
541 // - For the last operation overall in the entire transaction, generate a stop condition. 564 // 2. **Stop Condition**: Generate stop for the final operation in the entire transaction
542 // - For read operations, check the next operation: if it is also a read operation, we merge 565 // 3. **ACK/NACK for Reads**: For read operations, send ACK if more reads follow in the
543 // these and send ACK for all bytes in the current operation; send NACK only for the final 566 // sequence, or NACK for the final read in a sequence (before write or transaction end)
544 // read operation's last byte (before write or end of entire transaction) to indicate last
545 // byte read and release the bus for transmission of the bus master's next byte (or stop).
546 // 567 //
547 // We check the third property unconditionally, i.e. even for write opeartions. This is okay 568 // The third property is checked for all operations since the resulting frame
548 // because the resulting frame options are identical for write operations. 569 // configurations are identical for write operations regardless of ACK/NACK treatment.
549 let frame = match (first_frame, next_op) { 570 let frame = match (is_first_of_type, next_op) {
571 // First operation of type, and it's also the final operation overall
550 (true, None) => FrameOptions::FirstAndLastFrame, 572 (true, None) => FrameOptions::FirstAndLastFrame,
573 // First operation of type, next operation is also a read (continue read sequence)
551 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame, 574 (true, Some(Read(_))) => FrameOptions::FirstAndNextFrame,
575 // First operation of type, next operation is write (end current sequence)
552 (true, Some(Write(_))) => FrameOptions::FirstFrame, 576 (true, Some(Write(_))) => FrameOptions::FirstFrame,
553 // 577
578 // Continuation operation, and it's the final operation overall
554 (false, None) => FrameOptions::LastFrame, 579 (false, None) => FrameOptions::LastFrame,
580 // Continuation operation, next operation is also a read (continue read sequence)
555 (false, Some(Read(_))) => FrameOptions::NextFrame, 581 (false, Some(Read(_))) => FrameOptions::NextFrame,
582 // Continuation operation, next operation is write (end current sequence, no stop)
556 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop, 583 (false, Some(Write(_))) => FrameOptions::LastFrameNoStop,
557 }; 584 };
558 585
559 // Pre-calculate if `next_op` is the first operation of its type. We do this here and not at 586 // Pre-calculate whether the next operation will be the first of its type.
560 // the beginning of the loop because we hand out `op` as iterator value and cannot access it 587 // This is done here because we consume `current_op` as the iterator value
561 // anymore in the next iteration. 588 // and cannot access it in the next iteration.
562 next_first_frame = match (&op, next_op) { 589 next_first_operation = match (&current_op, next_op) {
590 // No next operation
563 (_, None) => false, 591 (_, None) => false,
592 // Operation type changes: next will be first of its type
564 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true, 593 (Read(_), Some(Write(_))) | (Write(_), Some(Read(_))) => true,
594 // Operation type continues: next will not be first of its type
565 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false, 595 (Read(_), Some(Read(_))) | (Write(_), Some(Write(_))) => false,
566 }; 596 };
567 597
568 Some((op, frame)) 598 Some((current_op, frame))
569 })) 599 }))
570} 600}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index e6b6c7c42..128a58db7 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -30,6 +30,7 @@ use crate::pac::i2c;
30// hit a case like this! 30// hit a case like this!
31pub unsafe fn on_interrupt<T: Instance>() { 31pub unsafe fn on_interrupt<T: Instance>() {
32 let regs = T::info().regs; 32 let regs = T::info().regs;
33 trace!("I2C interrupt triggered");
33 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of 34 // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of
34 // other stuff, so we wake the task on every interrupt. 35 // other stuff, so we wake the task on every interrupt.
35 T::state().waker.wake(); 36 T::state().waker.wake();
@@ -92,6 +93,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
92 self.info.regs.cr1().modify(|reg| { 93 self.info.regs.cr1().modify(|reg| {
93 reg.set_pe(true); 94 reg.set_pe(true);
94 }); 95 });
96 trace!("i2c v1 init complete");
95 } 97 }
96 98
97 fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> { 99 fn check_and_clear_error_flags(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
@@ -151,7 +153,13 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
151 Ok(sr1) 153 Ok(sr1)
152 } 154 }
153 155
154 fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: FrameOptions) -> Result<(), Error> { 156 fn write_bytes(
157 &mut self,
158 address: u8,
159 write_buffer: &[u8],
160 timeout: Timeout,
161 frame: FrameOptions,
162 ) -> Result<(), Error> {
155 if frame.send_start() { 163 if frame.send_start() {
156 // Send a START condition 164 // Send a START condition
157 165
@@ -170,7 +178,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
170 } 178 }
171 179
172 // Set up current address we're trying to talk to 180 // Set up current address we're trying to talk to
173 self.info.regs.dr().write(|reg| reg.set_dr(addr << 1)); 181 self.info.regs.dr().write(|reg| reg.set_dr(address << 1));
174 182
175 // Wait until address was sent 183 // Wait until address was sent
176 // Wait for the address to be acknowledged 184 // Wait for the address to be acknowledged
@@ -184,7 +192,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
184 } 192 }
185 193
186 // Send bytes 194 // Send bytes
187 for c in bytes { 195 for c in write_buffer {
188 self.send_byte(*c, timeout)?; 196 self.send_byte(*c, timeout)?;
189 } 197 }
190 198
@@ -236,12 +244,12 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
236 244
237 fn blocking_read_timeout( 245 fn blocking_read_timeout(
238 &mut self, 246 &mut self,
239 addr: u8, 247 address: u8,
240 buffer: &mut [u8], 248 read_buffer: &mut [u8],
241 timeout: Timeout, 249 timeout: Timeout,
242 frame: FrameOptions, 250 frame: FrameOptions,
243 ) -> Result<(), Error> { 251 ) -> Result<(), Error> {
244 let Some((last, buffer)) = buffer.split_last_mut() else { 252 let Some((last_byte, read_buffer)) = read_buffer.split_last_mut() else {
245 return Err(Error::Overrun); 253 return Err(Error::Overrun);
246 }; 254 };
247 255
@@ -263,7 +271,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
263 } 271 }
264 272
265 // Set up current address we're trying to talk to 273 // Set up current address we're trying to talk to
266 self.info.regs.dr().write(|reg| reg.set_dr((addr << 1) + 1)); 274 self.info.regs.dr().write(|reg| reg.set_dr((address << 1) + 1));
267 275
268 // Wait until address was sent 276 // Wait until address was sent
269 // Wait for the address to be acknowledged 277 // Wait for the address to be acknowledged
@@ -276,7 +284,7 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
276 } 284 }
277 285
278 // Receive bytes into buffer 286 // Receive bytes into buffer
279 for c in buffer { 287 for c in read_buffer {
280 *c = self.recv_byte(timeout)?; 288 *c = self.recv_byte(timeout)?;
281 } 289 }
282 290
@@ -291,37 +299,42 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
291 }); 299 });
292 300
293 // Receive last byte 301 // Receive last byte
294 *last = self.recv_byte(timeout)?; 302 *last_byte = self.recv_byte(timeout)?;
295 303
296 // Fallthrough is success 304 // Fallthrough is success
297 Ok(()) 305 Ok(())
298 } 306 }
299 307
300 /// Blocking read. 308 /// Blocking read.
301 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { 309 pub fn blocking_read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> {
302 self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) 310 self.blocking_read_timeout(address, read_buffer, self.timeout(), FrameOptions::FirstAndLastFrame)
303 } 311 }
304 312
305 /// Blocking write. 313 /// Blocking write.
306 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { 314 pub fn blocking_write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> {
307 self.write_bytes(addr, write, self.timeout(), FrameOptions::FirstAndLastFrame)?; 315 self.write_bytes(address, write_buffer, self.timeout(), FrameOptions::FirstAndLastFrame)?;
308 316
309 // Fallthrough is success 317 // Fallthrough is success
310 Ok(()) 318 Ok(())
311 } 319 }
312 320
313 /// Blocking write, restart, read. 321 /// Blocking write, restart, read.
314 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 322 pub fn blocking_write_read(
323 &mut self,
324 address: u8,
325 write_buffer: &[u8],
326 read_buffer: &mut [u8],
327 ) -> Result<(), Error> {
315 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 328 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
316 // stop condition below. 329 // stop condition below.
317 if read.is_empty() { 330 if read_buffer.is_empty() {
318 return Err(Error::Overrun); 331 return Err(Error::Overrun);
319 } 332 }
320 333
321 let timeout = self.timeout(); 334 let timeout = self.timeout();
322 335
323 self.write_bytes(addr, write, timeout, FrameOptions::FirstFrame)?; 336 self.write_bytes(address, write_buffer, timeout, FrameOptions::FirstFrame)?;
324 self.blocking_read_timeout(addr, read, timeout, FrameOptions::FirstAndLastFrame)?; 337 self.blocking_read_timeout(address, read_buffer, timeout, FrameOptions::FirstAndLastFrame)?;
325 338
326 Ok(()) 339 Ok(())
327 } 340 }
@@ -331,32 +344,43 @@ impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
331 /// Consecutive operations of same type are merged. See [transaction contract] for details. 344 /// Consecutive operations of same type are merged. See [transaction contract] for details.
332 /// 345 ///
333 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 346 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
334 pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 347 pub fn blocking_transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
335 let timeout = self.timeout(); 348 let timeout = self.timeout();
336 349
337 for (op, frame) in operation_frames(operations)? { 350 for (op, frame) in operation_frames(operations)? {
338 match op { 351 match op {
339 Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, 352 Operation::Read(read_buffer) => self.blocking_read_timeout(address, read_buffer, timeout, frame)?,
340 Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, 353 Operation::Write(write_buffer) => self.write_bytes(address, write_buffer, timeout, frame)?,
341 } 354 }
342 } 355 }
343 356
344 Ok(()) 357 Ok(())
345 } 358 }
346 359
347 // Async 360 /// Can be used by both blocking and async implementations
348
349 #[inline] // pretty sure this should always be inlined 361 #[inline] // pretty sure this should always be inlined
350 fn enable_interrupts(info: &'static Info) -> () { 362 fn enable_interrupts(info: &'static Info) {
351 info.regs.cr2().modify(|w| { 363 // The interrupt handler disables interrupts globally, so we need to re-enable them
352 w.set_iterren(true); 364 // This must be done in a critical section to avoid races
353 w.set_itevten(true); 365 critical_section::with(|_| {
366 info.regs.cr2().modify(|w| {
367 w.set_iterren(true);
368 w.set_itevten(true);
369 });
354 }); 370 });
355 } 371 }
372
373 /// Can be used by both blocking and async implementations
374 fn clear_stop_flag(info: &'static Info) {
375 trace!("I2C slave: clearing STOPF flag (v1 sequence)");
376 // v1 requires: READ SR1 then WRITE CR1 to clear STOPF
377 let _ = info.regs.sr1().read();
378 info.regs.cr1().modify(|_| {}); // Dummy write to clear STOPF
379 }
356} 380}
357 381
358impl<'d, IM: MasterMode> I2c<'d, Async, IM> { 382impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
359 async fn write_frame(&mut self, address: u8, write: &[u8], frame: FrameOptions) -> Result<(), Error> { 383 async fn write_frame(&mut self, address: u8, write_buffer: &[u8], frame: FrameOptions) -> Result<(), Error> {
360 self.info.regs.cr2().modify(|w| { 384 self.info.regs.cr2().modify(|w| {
361 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 385 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
362 // reception. 386 // reception.
@@ -439,7 +463,10 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
439 // this address from the memory after each TxE event. 463 // this address from the memory after each TxE event.
440 let dst = self.info.regs.dr().as_ptr() as *mut u8; 464 let dst = self.info.regs.dr().as_ptr() as *mut u8;
441 465
442 self.tx_dma.as_mut().unwrap().write(write, dst, Default::default()) 466 self.tx_dma
467 .as_mut()
468 .unwrap()
469 .write(write_buffer, dst, Default::default())
443 }; 470 };
444 471
445 // Wait for bytes to be sent, or an error to occur. 472 // Wait for bytes to be sent, or an error to occur.
@@ -501,28 +528,28 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
501 } 528 }
502 529
503 /// Write. 530 /// Write.
504 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 531 pub async fn write(&mut self, address: u8, write_buffer: &[u8]) -> Result<(), Error> {
505 self.write_frame(address, write, FrameOptions::FirstAndLastFrame) 532 self.write_frame(address, write_buffer, FrameOptions::FirstAndLastFrame)
506 .await?; 533 .await?;
507 534
508 Ok(()) 535 Ok(())
509 } 536 }
510 537
511 /// Read. 538 /// Read.
512 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 539 pub async fn read(&mut self, address: u8, read_buffer: &mut [u8]) -> Result<(), Error> {
513 self.read_frame(address, buffer, FrameOptions::FirstAndLastFrame) 540 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame)
514 .await?; 541 .await?;
515 542
516 Ok(()) 543 Ok(())
517 } 544 }
518 545
519 async fn read_frame(&mut self, address: u8, buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> { 546 async fn read_frame(&mut self, address: u8, read_buffer: &mut [u8], frame: FrameOptions) -> Result<(), Error> {
520 if buffer.is_empty() { 547 if read_buffer.is_empty() {
521 return Err(Error::Overrun); 548 return Err(Error::Overrun);
522 } 549 }
523 550
524 // Some branches below depend on whether the buffer contains only a single byte. 551 // Some branches below depend on whether the buffer contains only a single byte.
525 let single_byte = buffer.len() == 1; 552 let single_byte = read_buffer.len() == 1;
526 553
527 self.info.regs.cr2().modify(|w| { 554 self.info.regs.cr2().modify(|w| {
528 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for 555 // Note: Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is used for
@@ -612,7 +639,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
612 self.info.regs.sr2().read(); 639 self.info.regs.sr2().read();
613 } else { 640 } else {
614 // Before starting reception of single byte (but without START condition, i.e. in case 641 // Before starting reception of single byte (but without START condition, i.e. in case
615 // of continued frame), program NACK to emit at end of this byte. 642 // of merged operations), program NACK to emit at end of this byte.
616 if frame.send_nack() && single_byte { 643 if frame.send_nack() && single_byte {
617 self.info.regs.cr1().modify(|w| { 644 self.info.regs.cr1().modify(|w| {
618 w.set_ack(false); 645 w.set_ack(false);
@@ -634,7 +661,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
634 // from this address from the memory after each RxE event. 661 // from this address from the memory after each RxE event.
635 let src = self.info.regs.dr().as_ptr() as *mut u8; 662 let src = self.info.regs.dr().as_ptr() as *mut u8;
636 663
637 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default()) 664 self.rx_dma.as_mut().unwrap().read(src, read_buffer, Default::default())
638 }; 665 };
639 666
640 // Wait for bytes to be received, or an error to occur. 667 // Wait for bytes to be received, or an error to occur.
@@ -673,15 +700,17 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
673 } 700 }
674 701
675 /// Write, restart, read. 702 /// Write, restart, read.
676 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 703 pub async fn write_read(&mut self, address: u8, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<(), Error> {
677 // Check empty read buffer before starting transaction. Otherwise, we would not generate the 704 // Check empty read buffer before starting transaction. Otherwise, we would not generate the
678 // stop condition below. 705 // stop condition below.
679 if read.is_empty() { 706 if read_buffer.is_empty() {
680 return Err(Error::Overrun); 707 return Err(Error::Overrun);
681 } 708 }
682 709
683 self.write_frame(address, write, FrameOptions::FirstFrame).await?; 710 self.write_frame(address, write_buffer, FrameOptions::FirstFrame)
684 self.read_frame(address, read, FrameOptions::FirstAndLastFrame).await 711 .await?;
712 self.read_frame(address, read_buffer, FrameOptions::FirstAndLastFrame)
713 .await
685 } 714 }
686 715
687 /// Transaction with operations. 716 /// Transaction with operations.
@@ -689,11 +718,11 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
689 /// Consecutive operations of same type are merged. See [transaction contract] for details. 718 /// Consecutive operations of same type are merged. See [transaction contract] for details.
690 /// 719 ///
691 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 720 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
692 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 721 pub async fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
693 for (op, frame) in operation_frames(operations)? { 722 for (op, frame) in operation_frames(operations)? {
694 match op { 723 match op {
695 Operation::Read(read) => self.read_frame(addr, read, frame).await?, 724 Operation::Read(read_buffer) => self.read_frame(address, read_buffer, frame).await?,
696 Operation::Write(write) => self.write_frame(addr, write, frame).await?, 725 Operation::Write(write_buffer) => self.write_frame(address, write_buffer, frame).await?,
697 } 726 }
698 } 727 }
699 728
@@ -729,12 +758,956 @@ impl Duty {
729 } 758 }
730} 759}
731 760
761/// Result of attempting to send a byte in slave transmitter mode
762#[derive(Debug, PartialEq)]
763enum TransmitResult {
764 /// Byte sent and ACKed by master - continue transmission
765 Acknowledged,
766 /// Byte sent but NACKed by master - normal end of read transaction
767 NotAcknowledged,
768 /// STOP condition detected - master terminated transaction
769 Stopped,
770 /// RESTART condition detected - master starting new transaction
771 Restarted,
772}
773
774/// Result of attempting to receive a byte in slave receiver mode
775#[derive(Debug, PartialEq)]
776enum ReceiveResult {
777 /// Data byte successfully received
778 Data(u8),
779 /// STOP condition detected - end of write transaction
780 Stopped,
781 /// RESTART condition detected - master starting new transaction
782 Restarted,
783}
784
785/// Enumeration of slave transaction termination conditions
786#[derive(Debug, Clone, Copy, PartialEq)]
787#[cfg_attr(feature = "defmt", derive(defmt::Format))]
788enum SlaveTermination {
789 /// STOP condition received - normal end of transaction
790 Stop,
791 /// RESTART condition received - master starting new transaction
792 Restart,
793 /// NACK received - normal end of read transaction
794 Nack,
795}
796
797impl<'d, M: PeriMode> I2c<'d, M, Master> {
798 /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster)
799 pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> {
800 let mut slave = I2c {
801 info: self.info,
802 state: self.state,
803 kernel_clock: self.kernel_clock,
804 tx_dma: self.tx_dma.take(), // Use take() to move ownership
805 rx_dma: self.rx_dma.take(), // Use take() to move ownership
806 #[cfg(feature = "time")]
807 timeout: self.timeout,
808 _phantom: PhantomData,
809 _phantom2: PhantomData,
810 _drop_guard: self._drop_guard, // Move the drop guard
811 };
812 slave.init_slave(slave_addr_config);
813 slave
814 }
815}
816
817// Address configuration methods
818impl<'d, M: PeriMode, IM: MasterMode> I2c<'d, M, IM> {
819 /// Initialize slave mode with address configuration
820 pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) {
821 trace!("I2C slave: initializing with config={:?}", config);
822
823 // Disable peripheral for configuration
824 self.info.regs.cr1().modify(|reg| reg.set_pe(false));
825
826 // Configure slave addresses
827 self.apply_address_configuration(config);
828
829 // Enable peripheral with slave settings
830 self.info.regs.cr1().modify(|reg| {
831 reg.set_pe(true);
832 reg.set_ack(true); // Enable acknowledgment for slave mode
833 reg.set_nostretch(false); // Allow clock stretching for processing time
834 });
835
836 trace!("I2C slave: initialization complete");
837 }
838
839 /// Apply the complete address configuration for slave mode
840 fn apply_address_configuration(&mut self, config: SlaveAddrConfig) {
841 match config.addr {
842 OwnAddresses::OA1(addr) => {
843 self.configure_primary_address(addr);
844 self.disable_secondary_address();
845 }
846 OwnAddresses::OA2(oa2) => {
847 self.configure_default_primary_address();
848 self.configure_secondary_address(oa2.addr); // v1 ignores mask
849 }
850 OwnAddresses::Both { oa1, oa2 } => {
851 self.configure_primary_address(oa1);
852 self.configure_secondary_address(oa2.addr); // v1 ignores mask
853 }
854 }
855
856 // Configure general call detection
857 if config.general_call {
858 self.info.regs.cr1().modify(|w| w.set_engc(true));
859 }
860 }
861
862 /// Configure the primary address (OA1) register
863 fn configure_primary_address(&mut self, addr: Address) {
864 match addr {
865 Address::SevenBit(addr) => {
866 self.info.regs.oar1().write(|reg| {
867 let hw_addr = (addr as u16) << 1; // Address in bits [7:1]
868 reg.set_add(hw_addr);
869 reg.set_addmode(i2c::vals::Addmode::BIT7);
870 });
871 }
872 Address::TenBit(addr) => {
873 self.info.regs.oar1().write(|reg| {
874 reg.set_add(addr);
875 reg.set_addmode(i2c::vals::Addmode::BIT10);
876 });
877 }
878 }
879
880 // Set required bit 14 as per reference manual
881 self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14);
882 }
883
884 /// Configure the secondary address (OA2) register
885 fn configure_secondary_address(&mut self, addr: u8) {
886 self.info.regs.oar2().write(|reg| {
887 reg.set_add2(addr);
888 reg.set_endual(i2c::vals::Endual::DUAL);
889 });
890 }
891
892 /// Set a default primary address when using OA2-only mode
893 fn configure_default_primary_address(&mut self) {
894 self.info.regs.oar1().write(|reg| {
895 reg.set_add(0); // Reserved address, safe to use
896 reg.set_addmode(i2c::vals::Addmode::BIT7);
897 });
898 self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14);
899 }
900
901 /// Disable secondary address when not needed
902 fn disable_secondary_address(&mut self) {
903 self.info.regs.oar2().write(|reg| {
904 reg.set_endual(i2c::vals::Endual::SINGLE);
905 });
906 }
907}
908
909impl<'d, M: PeriMode> I2c<'d, M, MultiMaster> {
910 /// Listen for incoming I2C address match and return the command type
911 ///
912 /// This method blocks until the slave address is matched by a master.
913 /// Returns the command type (Read/Write) and the matched address.
914 pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> {
915 trace!("I2C slave: starting blocking listen for address match");
916 let result = self.blocking_listen_with_timeout(self.timeout());
917 trace!("I2C slave: blocking listen complete, result={:?}", result);
918 result
919 }
920
921 /// Respond to a master read request by transmitting data
922 ///
923 /// Sends the provided data to the master. If the master requests more bytes
924 /// than available, padding bytes (0x00) are sent until the master terminates
925 /// the transaction with NACK.
926 ///
927 /// Returns the total number of bytes transmitted (including padding).
928 pub fn blocking_respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> {
929 trace!("I2C slave: starting blocking respond_to_read, data_len={}", data.len());
930
931 if let Some(zero_length_result) = self.detect_zero_length_read(self.timeout())? {
932 trace!("I2C slave: zero-length read detected");
933 return Ok(zero_length_result);
934 }
935
936 let result = self.transmit_to_master(data, self.timeout());
937 trace!("I2C slave: blocking respond_to_read complete, result={:?}", result);
938 result
939 }
940
941 /// Respond to a master write request by receiving data
942 ///
943 /// Receives data from the master into the provided buffer. If the master
944 /// sends more bytes than the buffer can hold, excess bytes are acknowledged
945 /// but discarded.
946 ///
947 /// Returns the number of bytes stored in the buffer (not total received).
948 pub fn blocking_respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
949 trace!(
950 "I2C slave: starting blocking respond_to_write, buffer_len={}",
951 buffer.len()
952 );
953 let result = self.receive_from_master(buffer, self.timeout());
954 trace!("I2C slave: blocking respond_to_write complete, result={:?}", result);
955 result
956 }
957
958 // Private implementation methods
959
960 /// Wait for address match and determine transaction type
961 fn blocking_listen_with_timeout(&mut self, timeout: Timeout) -> Result<SlaveCommand, Error> {
962 // Ensure interrupts are disabled for blocking operation
963 self.disable_i2c_interrupts();
964
965 // Wait for address match (ADDR flag)
966 loop {
967 let sr1 = Self::read_status_and_handle_errors(self.info)?;
968
969 if sr1.addr() {
970 // Address matched - read SR2 to get direction and clear ADDR flag
971 let sr2 = self.info.regs.sr2().read();
972 let direction = if sr2.tra() {
973 SlaveCommandKind::Read
974 } else {
975 SlaveCommandKind::Write
976 };
977
978 // Use the static method instead of the instance method
979 let matched_address = Self::decode_matched_address(sr2, self.info)?;
980 trace!(
981 "I2C slave: address matched, direction={:?}, addr={:?}",
982 direction, matched_address
983 );
984
985 return Ok(SlaveCommand {
986 kind: direction,
987 address: matched_address,
988 });
989 }
990
991 timeout.check()?;
992 }
993 }
994
995 /// Transmit data to master in response to read request
996 fn transmit_to_master(&mut self, data: &[u8], timeout: Timeout) -> Result<usize, Error> {
997 let mut bytes_transmitted = 0;
998 let mut padding_count = 0;
999
1000 loop {
1001 let byte_to_send = if bytes_transmitted < data.len() {
1002 data[bytes_transmitted]
1003 } else {
1004 padding_count += 1;
1005 0x00 // Send padding bytes when data is exhausted
1006 };
1007
1008 match self.transmit_byte(byte_to_send, timeout)? {
1009 TransmitResult::Acknowledged => {
1010 bytes_transmitted += 1;
1011 }
1012 TransmitResult::NotAcknowledged => {
1013 bytes_transmitted += 1; // Count the NACKed byte
1014 break;
1015 }
1016 TransmitResult::Stopped | TransmitResult::Restarted => {
1017 break;
1018 }
1019 }
1020 }
1021
1022 if padding_count > 0 {
1023 trace!(
1024 "I2C slave: sent {} data bytes + {} padding bytes = {} total",
1025 data.len(),
1026 padding_count,
1027 bytes_transmitted
1028 );
1029 }
1030
1031 Ok(bytes_transmitted)
1032 }
1033
1034 /// Receive data from master during write request
1035 fn receive_from_master(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
1036 let mut bytes_stored = 0;
1037
1038 // Receive bytes that fit in buffer
1039 while bytes_stored < buffer.len() {
1040 match self.receive_byte(timeout)? {
1041 ReceiveResult::Data(byte) => {
1042 buffer[bytes_stored] = byte;
1043 bytes_stored += 1;
1044 }
1045 ReceiveResult::Stopped | ReceiveResult::Restarted => {
1046 return Ok(bytes_stored);
1047 }
1048 }
1049 }
1050
1051 // Handle buffer overflow by discarding excess bytes
1052 if bytes_stored == buffer.len() {
1053 trace!("I2C slave: buffer full, discarding excess bytes");
1054 self.discard_excess_bytes(timeout)?;
1055 }
1056
1057 Ok(bytes_stored)
1058 }
1059
1060 /// Detect zero-length read pattern early
1061 ///
1062 /// Zero-length reads occur when a master sends START+ADDR+R followed immediately
1063 /// by NACK+STOP without wanting any data. This must be detected before attempting
1064 /// to transmit any bytes to avoid SDA line issues.
1065 fn detect_zero_length_read(&mut self, _timeout: Timeout) -> Result<Option<usize>, Error> {
1066 // Quick check for immediate termination signals
1067 let sr1 = self.info.regs.sr1().read();
1068
1069 // Check for immediate NACK (fastest zero-length pattern)
1070 if sr1.af() {
1071 self.clear_acknowledge_failure();
1072 return Ok(Some(0));
1073 }
1074
1075 // Check for immediate STOP (alternative zero-length pattern)
1076 if sr1.stopf() {
1077 Self::clear_stop_flag(self.info);
1078 return Ok(Some(0));
1079 }
1080
1081 // Give a brief window for master to send termination signals
1082 // This handles masters that have slight delays between address ACK and NACK
1083 const ZERO_LENGTH_DETECTION_CYCLES: u32 = 20; // ~5-10µs window
1084
1085 for _ in 0..ZERO_LENGTH_DETECTION_CYCLES {
1086 let sr1 = self.info.regs.sr1().read();
1087
1088 // Immediate NACK indicates zero-length read
1089 if sr1.af() {
1090 self.clear_acknowledge_failure();
1091 return Ok(Some(0));
1092 }
1093
1094 // Immediate STOP indicates zero-length read
1095 if sr1.stopf() {
1096 Self::clear_stop_flag(self.info);
1097 return Ok(Some(0));
1098 }
1099
1100 // If TXE becomes ready, master is waiting for data - not zero-length
1101 if sr1.txe() {
1102 return Ok(None); // Proceed with normal transmission
1103 }
1104
1105 // If RESTART detected, handle as zero-length
1106 if sr1.addr() {
1107 return Ok(Some(0));
1108 }
1109 }
1110
1111 // No zero-length pattern detected within the window
1112 Ok(None)
1113 }
1114
1115 /// Discard excess bytes when buffer is full
1116 fn discard_excess_bytes(&mut self, timeout: Timeout) -> Result<(), Error> {
1117 let mut discarded_count = 0;
1118
1119 loop {
1120 match self.receive_byte(timeout)? {
1121 ReceiveResult::Data(_) => {
1122 discarded_count += 1;
1123 continue;
1124 }
1125 ReceiveResult::Stopped | ReceiveResult::Restarted => {
1126 if discarded_count > 0 {
1127 trace!("I2C slave: discarded {} excess bytes", discarded_count);
1128 }
1129 break;
1130 }
1131 }
1132 }
1133 Ok(())
1134 }
1135
1136 /// Send a single byte and wait for master's response
1137 fn transmit_byte(&mut self, byte: u8, timeout: Timeout) -> Result<TransmitResult, Error> {
1138 // Wait for transmit buffer ready
1139 self.wait_for_transmit_ready(timeout)?;
1140
1141 // Send the byte
1142 self.info.regs.dr().write(|w| w.set_dr(byte));
1143
1144 // Wait for transmission completion or master response
1145 self.wait_for_transmit_completion(timeout)
1146 }
1147
1148 /// Wait until transmit buffer is ready (TXE flag set)
1149 fn wait_for_transmit_ready(&mut self, timeout: Timeout) -> Result<(), Error> {
1150 loop {
1151 let sr1 = Self::read_status_and_handle_errors(self.info)?;
1152
1153 // Check for early termination conditions
1154 if let Some(result) = Self::check_early_termination(sr1) {
1155 return Err(self.handle_early_termination(result));
1156 }
1157
1158 if sr1.txe() {
1159 return Ok(()); // Ready to transmit
1160 }
1161
1162 timeout.check()?;
1163 }
1164 }
1165
1166 /// Wait for byte transmission completion or master response
1167 fn wait_for_transmit_completion(&mut self, timeout: Timeout) -> Result<TransmitResult, Error> {
1168 loop {
1169 let sr1 = self.info.regs.sr1().read();
1170
1171 // Check flags in priority order
1172 if sr1.af() {
1173 self.clear_acknowledge_failure();
1174 return Ok(TransmitResult::NotAcknowledged);
1175 }
1176
1177 if sr1.btf() {
1178 return Ok(TransmitResult::Acknowledged);
1179 }
1180
1181 if sr1.stopf() {
1182 Self::clear_stop_flag(self.info);
1183 return Ok(TransmitResult::Stopped);
1184 }
1185
1186 if sr1.addr() {
1187 return Ok(TransmitResult::Restarted);
1188 }
1189
1190 // Check for other error conditions
1191 self.check_for_hardware_errors(sr1)?;
1192
1193 timeout.check()?;
1194 }
1195 }
1196
1197 /// Receive a single byte or detect transaction termination
1198 fn receive_byte(&mut self, timeout: Timeout) -> Result<ReceiveResult, Error> {
1199 loop {
1200 let sr1 = Self::read_status_and_handle_errors(self.info)?;
1201
1202 // Check for received data first (prioritize data over control signals)
1203 if sr1.rxne() {
1204 let byte = self.info.regs.dr().read().dr();
1205 return Ok(ReceiveResult::Data(byte));
1206 }
1207
1208 // Check for transaction termination
1209 if sr1.addr() {
1210 return Ok(ReceiveResult::Restarted);
1211 }
1212
1213 if sr1.stopf() {
1214 Self::clear_stop_flag(self.info);
1215 return Ok(ReceiveResult::Stopped);
1216 }
1217
1218 timeout.check()?;
1219 }
1220 }
1221
1222 /// Determine which slave address was matched based on SR2 flags
1223 fn decode_matched_address(sr2: i2c::regs::Sr2, info: &'static Info) -> Result<Address, Error> {
1224 if sr2.gencall() {
1225 Ok(Address::SevenBit(0x00)) // General call address
1226 } else if sr2.dualf() {
1227 // OA2 (secondary address) was matched
1228 let oar2 = info.regs.oar2().read();
1229 if oar2.endual() != i2c::vals::Endual::DUAL {
1230 return Err(Error::Bus); // Hardware inconsistency
1231 }
1232 Ok(Address::SevenBit(oar2.add2()))
1233 } else {
1234 // OA1 (primary address) was matched
1235 let oar1 = info.regs.oar1().read();
1236 match oar1.addmode() {
1237 i2c::vals::Addmode::BIT7 => {
1238 let addr = (oar1.add() >> 1) as u8;
1239 Ok(Address::SevenBit(addr))
1240 }
1241 i2c::vals::Addmode::BIT10 => Ok(Address::TenBit(oar1.add())),
1242 }
1243 }
1244 }
1245
1246 // Helper methods for hardware interaction
1247
1248 /// Read status register and handle I2C errors (except NACK in slave mode)
1249 fn read_status_and_handle_errors(info: &'static Info) -> Result<i2c::regs::Sr1, Error> {
1250 match Self::check_and_clear_error_flags(info) {
1251 Ok(sr1) => Ok(sr1),
1252 Err(Error::Nack) => {
1253 // In slave mode, NACK is normal protocol behavior, not an error
1254 Ok(info.regs.sr1().read())
1255 }
1256 Err(other_error) => Err(other_error),
1257 }
1258 }
1259
1260 /// Check for conditions that cause early termination of operations
1261 fn check_early_termination(sr1: i2c::regs::Sr1) -> Option<TransmitResult> {
1262 if sr1.stopf() {
1263 Some(TransmitResult::Stopped)
1264 } else if sr1.addr() {
1265 Some(TransmitResult::Restarted)
1266 } else if sr1.af() {
1267 Some(TransmitResult::NotAcknowledged)
1268 } else {
1269 None
1270 }
1271 }
1272
1273 /// Convert early termination to appropriate error
1274 fn handle_early_termination(&mut self, result: TransmitResult) -> Error {
1275 match result {
1276 TransmitResult::Stopped => {
1277 Self::clear_stop_flag(self.info);
1278 Error::Bus // Unexpected STOP during setup
1279 }
1280 TransmitResult::Restarted => {
1281 Error::Bus // Unexpected RESTART during setup
1282 }
1283 TransmitResult::NotAcknowledged => {
1284 self.clear_acknowledge_failure();
1285 Error::Bus // Unexpected NACK during setup
1286 }
1287 TransmitResult::Acknowledged => {
1288 unreachable!() // This should never be passed to this function
1289 }
1290 }
1291 }
1292
1293 /// Check for hardware-level I2C errors during transmission
1294 fn check_for_hardware_errors(&self, sr1: i2c::regs::Sr1) -> Result<(), Error> {
1295 if sr1.timeout() || sr1.ovr() || sr1.arlo() || sr1.berr() {
1296 // Delegate to existing error handling
1297 Self::check_and_clear_error_flags(self.info)?;
1298 }
1299 Ok(())
1300 }
1301
1302 /// Disable I2C event and error interrupts for blocking operations
1303 fn disable_i2c_interrupts(&mut self) {
1304 self.info.regs.cr2().modify(|w| {
1305 w.set_itevten(false);
1306 w.set_iterren(false);
1307 });
1308 }
1309
1310 /// Clear the acknowledge failure flag
1311 fn clear_acknowledge_failure(&mut self) {
1312 self.info.regs.sr1().write(|reg| {
1313 reg.0 = !0;
1314 reg.set_af(false);
1315 });
1316 }
1317
1318 /// Configure DMA settings for slave operations (shared between read/write)
1319 fn setup_slave_dma_base(&mut self) {
1320 self.info.regs.cr2().modify(|w| {
1321 w.set_itbufen(false); // Always disable buffer interrupts when using DMA
1322 w.set_dmaen(true); // Enable DMA requests
1323 w.set_last(false); // LAST bit not used in slave mode for v1 hardware
1324 });
1325 }
1326
1327 /// Disable DMA and interrupts in a critical section
1328 fn disable_dma_and_interrupts(info: &'static Info) {
1329 critical_section::with(|_| {
1330 info.regs.cr2().modify(|w| {
1331 w.set_dmaen(false);
1332 w.set_iterren(false);
1333 w.set_itevten(false);
1334 });
1335 });
1336 }
1337
1338 /// Check for early termination conditions during slave operations
1339 /// Returns Some(result) if termination detected, None to continue
1340 fn check_slave_termination_conditions(sr1: i2c::regs::Sr1) -> Option<SlaveTermination> {
1341 if sr1.stopf() {
1342 Some(SlaveTermination::Stop)
1343 } else if sr1.addr() {
1344 Some(SlaveTermination::Restart)
1345 } else if sr1.af() {
1346 Some(SlaveTermination::Nack)
1347 } else {
1348 None
1349 }
1350 }
1351}
1352
1353impl<'d> I2c<'d, Async, MultiMaster> {
1354 /// Async listen for incoming I2C messages using interrupts
1355 ///
1356 /// Waits for a master to address this slave and returns the command type
1357 /// (Read/Write) and the matched address. This method will suspend until
1358 /// an address match occurs.
1359 pub async fn listen(&mut self) -> Result<SlaveCommand, Error> {
1360 trace!("I2C slave: starting async listen for address match");
1361 let state = self.state;
1362 let info = self.info;
1363
1364 Self::enable_interrupts(info);
1365
1366 let on_drop = OnDrop::new(|| {
1367 Self::disable_dma_and_interrupts(info);
1368 });
1369
1370 let result = poll_fn(|cx| {
1371 state.waker.register(cx.waker());
1372
1373 match Self::check_and_clear_error_flags(info) {
1374 Err(e) => {
1375 error!("I2C slave: error during listen: {:?}", e);
1376 Poll::Ready(Err(e))
1377 }
1378 Ok(sr1) => {
1379 if sr1.addr() {
1380 let sr2 = info.regs.sr2().read();
1381 let direction = if sr2.tra() {
1382 SlaveCommandKind::Read
1383 } else {
1384 SlaveCommandKind::Write
1385 };
1386
1387 let matched_address = match Self::decode_matched_address(sr2, info) {
1388 Ok(addr) => {
1389 trace!("I2C slave: address matched, direction={:?}, addr={:?}", direction, addr);
1390 addr
1391 }
1392 Err(e) => {
1393 error!("I2C slave: failed to decode matched address: {:?}", e);
1394 return Poll::Ready(Err(e));
1395 }
1396 };
1397
1398 Poll::Ready(Ok(SlaveCommand {
1399 kind: direction,
1400 address: matched_address,
1401 }))
1402 } else {
1403 Self::enable_interrupts(info);
1404 Poll::Pending
1405 }
1406 }
1407 }
1408 })
1409 .await;
1410
1411 drop(on_drop);
1412 trace!("I2C slave: listen complete, result={:?}", result);
1413 result
1414 }
1415
1416 /// Async respond to write command using RX DMA
1417 ///
1418 /// Receives data from the master into the provided buffer using DMA.
1419 /// If the master sends more bytes than the buffer can hold, excess bytes
1420 /// are acknowledged but discarded to prevent interrupt flooding.
1421 ///
1422 /// Returns the number of bytes stored in the buffer (not total received).
1423 pub async fn respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1424 trace!("I2C slave: starting respond_to_write, buffer_len={}", buffer.len());
1425
1426 if buffer.is_empty() {
1427 warn!("I2C slave: respond_to_write called with empty buffer");
1428 return Err(Error::Overrun);
1429 }
1430
1431 let state = self.state;
1432 let info = self.info;
1433
1434 self.setup_slave_dma_base();
1435
1436 let on_drop = OnDrop::new(|| {
1437 Self::disable_dma_and_interrupts(info);
1438 });
1439
1440 info.regs.sr2().read();
1441
1442 let result = self.execute_slave_receive_transfer(buffer, state, info).await;
1443
1444 drop(on_drop);
1445 trace!("I2C slave: respond_to_write complete, result={:?}", result);
1446 result
1447 }
1448
1449 /// Async respond to read command using TX DMA
1450 ///
1451 /// Transmits data to the master using DMA. If the master requests more bytes
1452 /// than available in the data buffer, padding bytes (0x00) are sent until
1453 /// the master terminates the transaction with NACK, STOP, or RESTART.
1454 ///
1455 /// Returns the total number of bytes transmitted (data + padding).
1456 pub async fn respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> {
1457 trace!("I2C slave: starting respond_to_read, data_len={}", data.len());
1458
1459 if data.is_empty() {
1460 warn!("I2C slave: respond_to_read called with empty data");
1461 return Err(Error::Overrun);
1462 }
1463
1464 let state = self.state;
1465 let info = self.info;
1466
1467 self.setup_slave_dma_base();
1468
1469 let on_drop = OnDrop::new(|| {
1470 Self::disable_dma_and_interrupts(info);
1471 });
1472
1473 info.regs.sr2().read();
1474
1475 let result = self.execute_slave_transmit_transfer(data, state, info).await;
1476
1477 drop(on_drop);
1478 trace!("I2C slave: respond_to_read complete, result={:?}", result);
1479 result
1480 }
1481
1482 // === Private Transfer Execution Methods ===
1483
1484 /// Execute complete slave receive transfer with excess byte handling
1485 async fn execute_slave_receive_transfer(
1486 &mut self,
1487 buffer: &mut [u8],
1488 state: &'static State,
1489 info: &'static Info,
1490 ) -> Result<usize, Error> {
1491 let dma_transfer = unsafe {
1492 let src = info.regs.dr().as_ptr() as *mut u8;
1493 self.rx_dma.as_mut().unwrap().read(src, buffer, Default::default())
1494 };
1495
1496 let i2c_monitor =
1497 Self::create_termination_monitor(state, info, &[SlaveTermination::Stop, SlaveTermination::Restart]);
1498
1499 match select(dma_transfer, i2c_monitor).await {
1500 Either::Second(Err(e)) => {
1501 error!("I2C slave: error during receive transfer: {:?}", e);
1502 Self::disable_dma_and_interrupts(info);
1503 Err(e)
1504 }
1505 Either::First(_) => {
1506 trace!("I2C slave: DMA receive completed, handling excess bytes");
1507 Self::disable_dma_and_interrupts(info);
1508 self.handle_excess_bytes(state, info).await?;
1509 Ok(buffer.len())
1510 }
1511 Either::Second(Ok(termination)) => {
1512 trace!("I2C slave: receive terminated by I2C event: {:?}", termination);
1513 Self::disable_dma_and_interrupts(info);
1514 Ok(buffer.len())
1515 }
1516 }
1517 }
1518
1519 /// Execute complete slave transmit transfer with padding byte handling
1520 async fn execute_slave_transmit_transfer(
1521 &mut self,
1522 data: &[u8],
1523 state: &'static State,
1524 info: &'static Info,
1525 ) -> Result<usize, Error> {
1526 let dma_transfer = unsafe {
1527 let dst = info.regs.dr().as_ptr() as *mut u8;
1528 self.tx_dma.as_mut().unwrap().write(data, dst, Default::default())
1529 };
1530
1531 let i2c_monitor = Self::create_termination_monitor(
1532 state,
1533 info,
1534 &[
1535 SlaveTermination::Stop,
1536 SlaveTermination::Restart,
1537 SlaveTermination::Nack,
1538 ],
1539 );
1540
1541 match select(dma_transfer, i2c_monitor).await {
1542 Either::Second(Err(e)) => {
1543 error!("I2C slave: error during transmit transfer: {:?}", e);
1544 Self::disable_dma_and_interrupts(info);
1545 Err(e)
1546 }
1547 Either::First(_) => {
1548 trace!("I2C slave: DMA transmit completed, handling padding bytes");
1549 Self::disable_dma_and_interrupts(info);
1550 let padding_count = self.handle_padding_bytes(state, info).await?;
1551 let total_bytes = data.len() + padding_count;
1552 trace!(
1553 "I2C slave: sent {} data bytes + {} padding bytes = {} total",
1554 data.len(),
1555 padding_count,
1556 total_bytes
1557 );
1558 Ok(total_bytes)
1559 }
1560 Either::Second(Ok(termination)) => {
1561 trace!("I2C slave: transmit terminated by I2C event: {:?}", termination);
1562 Self::disable_dma_and_interrupts(info);
1563 Ok(data.len())
1564 }
1565 }
1566 }
1567
1568 /// Create a future that monitors for specific slave termination conditions
1569 fn create_termination_monitor(
1570 state: &'static State,
1571 info: &'static Info,
1572 allowed_terminations: &'static [SlaveTermination],
1573 ) -> impl Future<Output = Result<SlaveTermination, Error>> {
1574 poll_fn(move |cx| {
1575 state.waker.register(cx.waker());
1576
1577 match Self::check_and_clear_error_flags(info) {
1578 Err(Error::Nack) if allowed_terminations.contains(&SlaveTermination::Nack) => {
1579 Poll::Ready(Ok(SlaveTermination::Nack))
1580 }
1581 Err(e) => Poll::Ready(Err(e)),
1582 Ok(sr1) => {
1583 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1584 if allowed_terminations.contains(&termination) {
1585 // Handle the specific termination condition
1586 match termination {
1587 SlaveTermination::Stop => Self::clear_stop_flag(info),
1588 SlaveTermination::Nack => {
1589 info.regs.sr1().write(|reg| {
1590 reg.0 = !0;
1591 reg.set_af(false);
1592 });
1593 }
1594 SlaveTermination::Restart => {
1595 // ADDR flag will be handled by next listen() call
1596 }
1597 }
1598 Poll::Ready(Ok(termination))
1599 } else {
1600 // Unexpected termination condition
1601 Poll::Ready(Err(Error::Bus))
1602 }
1603 } else {
1604 Self::enable_interrupts(info);
1605 Poll::Pending
1606 }
1607 }
1608 }
1609 })
1610 }
1611
1612 /// Handle excess bytes after DMA buffer is full
1613 ///
1614 /// Reads and discards bytes until transaction termination to prevent interrupt flooding
1615 async fn handle_excess_bytes(&mut self, state: &'static State, info: &'static Info) -> Result<(), Error> {
1616 let mut discarded_count = 0;
1617
1618 poll_fn(|cx| {
1619 state.waker.register(cx.waker());
1620
1621 match Self::check_and_clear_error_flags(info) {
1622 Err(e) => {
1623 error!("I2C slave: error while discarding excess bytes: {:?}", e);
1624 Poll::Ready(Err(e))
1625 }
1626 Ok(sr1) => {
1627 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1628 match termination {
1629 SlaveTermination::Stop => Self::clear_stop_flag(info),
1630 SlaveTermination::Restart => {}
1631 SlaveTermination::Nack => unreachable!("NACK not expected during receive"),
1632 }
1633 if discarded_count > 0 {
1634 trace!("I2C slave: discarded {} excess bytes", discarded_count);
1635 }
1636 return Poll::Ready(Ok(()));
1637 }
1638
1639 if sr1.rxne() {
1640 let _discarded_byte = info.regs.dr().read().dr();
1641 discarded_count += 1;
1642 Self::enable_interrupts(info);
1643 return Poll::Pending;
1644 }
1645
1646 Self::enable_interrupts(info);
1647 Poll::Pending
1648 }
1649 }
1650 })
1651 .await
1652 }
1653
1654 /// Handle padding bytes after DMA data is exhausted
1655 ///
1656 /// Sends 0x00 bytes until transaction termination to prevent interrupt flooding
1657 async fn handle_padding_bytes(&mut self, state: &'static State, info: &'static Info) -> Result<usize, Error> {
1658 let mut padding_count = 0;
1659
1660 poll_fn(|cx| {
1661 state.waker.register(cx.waker());
1662
1663 match Self::check_and_clear_error_flags(info) {
1664 Err(Error::Nack) => Poll::Ready(Ok(padding_count)),
1665 Err(e) => {
1666 error!("I2C slave: error while sending padding bytes: {:?}", e);
1667 Poll::Ready(Err(e))
1668 }
1669 Ok(sr1) => {
1670 if let Some(termination) = Self::check_slave_termination_conditions(sr1) {
1671 match termination {
1672 SlaveTermination::Stop => Self::clear_stop_flag(info),
1673 SlaveTermination::Restart => {}
1674 SlaveTermination::Nack => {
1675 info.regs.sr1().write(|reg| {
1676 reg.0 = !0;
1677 reg.set_af(false);
1678 });
1679 }
1680 }
1681 return Poll::Ready(Ok(padding_count));
1682 }
1683
1684 if sr1.txe() {
1685 info.regs.dr().write(|w| w.set_dr(0x00));
1686 padding_count += 1;
1687 Self::enable_interrupts(info);
1688 return Poll::Pending;
1689 }
1690
1691 Self::enable_interrupts(info);
1692 Poll::Pending
1693 }
1694 }
1695 })
1696 .await
1697 }
1698}
1699
1700/// Timing configuration for I2C v1 hardware
1701///
1702/// This struct encapsulates the complex timing calculations required for STM32 I2C v1
1703/// peripherals, which use three separate registers (CR2.FREQ, CCR, TRISE) instead of
1704/// the unified TIMINGR register found in v2 hardware.
732struct Timings { 1705struct Timings {
733 freq: u8, 1706 freq: u8, // APB frequency in MHz for CR2.FREQ register
734 mode: Mode, 1707 mode: Mode, // Standard or Fast mode selection
735 trise: u8, 1708 trise: u8, // Rise time compensation value
736 ccr: u16, 1709 ccr: u16, // Clock control register value
737 duty: Duty, 1710 duty: Duty, // Fast mode duty cycle selection
738} 1711}
739 1712
740impl Timings { 1713impl Timings {
@@ -771,14 +1744,10 @@ impl Timings {
771 duty = Duty::Duty2_1; 1744 duty = Duty::Duty2_1;
772 ccr = clock / (frequency * 3); 1745 ccr = clock / (frequency * 3);
773 ccr = if ccr < 1 { 1 } else { ccr }; 1746 ccr = if ccr < 1 { 1 } else { ccr };
774
775 // Set clock to fast mode with appropriate parameters for selected speed (2:1 duty cycle)
776 } else { 1747 } else {
777 duty = Duty::Duty16_9; 1748 duty = Duty::Duty16_9;
778 ccr = clock / (frequency * 25); 1749 ccr = clock / (frequency * 25);
779 ccr = if ccr < 1 { 1 } else { ccr }; 1750 ccr = if ccr < 1 { 1 } else { ccr };
780
781 // Set clock to fast mode with appropriate parameters for selected speed (16:9 duty cycle)
782 } 1751 }
783 } 1752 }
784 1753
@@ -788,11 +1757,6 @@ impl Timings {
788 ccr: ccr as u16, 1757 ccr: ccr as u16,
789 duty, 1758 duty,
790 mode, 1759 mode,
791 //prescale: presc_reg,
792 //scll,
793 //sclh,
794 //sdadel,
795 //scldel,
796 } 1760 }
797 } 1761 }
798} 1762}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 01b6b8800..57a7acee7 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -70,6 +70,11 @@ fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) {
70} 70}
71 71
72pub(crate) unsafe fn on_interrupt<T: Instance>() { 72pub(crate) unsafe fn on_interrupt<T: Instance>() {
73 // restore the clocks to their last configured state as
74 // much is lost in STOP modes
75 #[cfg(all(feature = "low-power", stm32wlex))]
76 crate::low_power::Executor::on_wakeup_irq();
77
73 let regs = T::info().regs; 78 let regs = T::info().regs;
74 let isr = regs.isr().read(); 79 let isr = regs.isr().read();
75 80
@@ -814,6 +819,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
814 819
815 /// Write. 820 /// Write.
816 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 821 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
822 #[cfg(all(feature = "low-power", stm32wlex))]
823 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
817 let timeout = self.timeout(); 824 let timeout = self.timeout();
818 if write.is_empty() { 825 if write.is_empty() {
819 self.write_internal(address.into(), write, true, timeout) 826 self.write_internal(address.into(), write, true, timeout)
@@ -828,6 +835,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
828 /// 835 ///
829 /// The buffers are concatenated in a single write transaction. 836 /// The buffers are concatenated in a single write transaction.
830 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> { 837 pub async fn write_vectored(&mut self, address: Address, write: &[&[u8]]) -> Result<(), Error> {
838 #[cfg(all(feature = "low-power", stm32wlex))]
839 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
831 let timeout = self.timeout(); 840 let timeout = self.timeout();
832 841
833 if write.is_empty() { 842 if write.is_empty() {
@@ -851,6 +860,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
851 860
852 /// Read. 861 /// Read.
853 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 862 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
863 #[cfg(all(feature = "low-power", stm32wlex))]
864 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
854 let timeout = self.timeout(); 865 let timeout = self.timeout();
855 866
856 if buffer.is_empty() { 867 if buffer.is_empty() {
@@ -863,6 +874,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
863 874
864 /// Write, restart, read. 875 /// Write, restart, read.
865 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 876 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
877 #[cfg(all(feature = "low-power", stm32wlex))]
878 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
866 let timeout = self.timeout(); 879 let timeout = self.timeout();
867 880
868 if write.is_empty() { 881 if write.is_empty() {
@@ -888,6 +901,8 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> {
888 /// 901 ///
889 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction 902 /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction
890 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { 903 pub async fn transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> {
904 #[cfg(all(feature = "low-power", stm32wlex))]
905 let _device_busy = crate::low_power::DeviceBusy::new_stop1();
891 let _ = addr; 906 let _ = addr;
892 let _ = operations; 907 let _ = operations;
893 todo!() 908 todo!()
@@ -1181,7 +1196,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1181 1196
1182 let regs = self.info.regs; 1197 let regs = self.info.regs;
1183 1198
1184 let dma_transfer = unsafe { 1199 let mut dma_transfer = unsafe {
1185 regs.cr1().modify(|w| { 1200 regs.cr1().modify(|w| {
1186 w.set_rxdmaen(true); 1201 w.set_rxdmaen(true);
1187 w.set_stopie(true); 1202 w.set_stopie(true);
@@ -1229,6 +1244,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1229 }) 1244 })
1230 .await?; 1245 .await?;
1231 1246
1247 dma_transfer.request_pause();
1232 dma_transfer.await; 1248 dma_transfer.await;
1233 1249
1234 drop(on_drop); 1250 drop(on_drop);
@@ -1294,6 +1310,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1294 }) 1310 })
1295 .await?; 1311 .await?;
1296 1312
1313 dma_transfer.request_pause();
1297 dma_transfer.await; 1314 dma_transfer.await;
1298 1315
1299 drop(on_drop); 1316 drop(on_drop);
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index db22cfa11..df077a3ae 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -7,6 +7,7 @@ use crate::Peri;
7use crate::dma::{ChannelAndRequest, ReadableRingBuffer, TransferOptions, WritableRingBuffer, ringbuffer}; 7use crate::dma::{ChannelAndRequest, ReadableRingBuffer, TransferOptions, WritableRingBuffer, ringbuffer};
8use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; 8use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed};
9use crate::mode::Async; 9use crate::mode::Async;
10use crate::spi::mode::Master;
10use crate::spi::{Config as SpiConfig, RegsExt as _, *}; 11use crate::spi::{Config as SpiConfig, RegsExt as _, *};
11use crate::time::Hertz; 12use crate::time::Hertz;
12 13
@@ -225,7 +226,7 @@ impl<'s, 'd, W: Word> Reader<'s, 'd, W> {
225pub struct I2S<'d, W: Word> { 226pub struct I2S<'d, W: Word> {
226 #[allow(dead_code)] 227 #[allow(dead_code)]
227 mode: Mode, 228 mode: Mode,
228 spi: Spi<'d, Async>, 229 spi: Spi<'d, Async, Master>,
229 txsd: Option<Peri<'d, AnyPin>>, 230 txsd: Option<Peri<'d, AnyPin>>,
230 rxsd: Option<Peri<'d, AnyPin>>, 231 rxsd: Option<Peri<'d, AnyPin>>,
231 ws: Option<Peri<'d, AnyPin>>, 232 ws: Option<Peri<'d, AnyPin>>,
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index dbf0fe620..e08ab30e6 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -54,6 +54,8 @@ pub mod timer;
54 54
55#[cfg(adc)] 55#[cfg(adc)]
56pub mod adc; 56pub mod adc;
57#[cfg(backup_sram)]
58pub mod backup_sram;
57#[cfg(can)] 59#[cfg(can)]
58pub mod can; 60pub mod can;
59// FIXME: Cordic driver cause stm32u5a5zj crash 61// FIXME: Cordic driver cause stm32u5a5zj crash
@@ -241,6 +243,14 @@ pub struct Config {
241 /// RCC config. 243 /// RCC config.
242 pub rcc: rcc::Config, 244 pub rcc: rcc::Config,
243 245
246 #[cfg(feature = "low-power")]
247 /// RTC config
248 pub rtc: rtc::RtcConfig,
249
250 #[cfg(feature = "low-power")]
251 /// Minimum time to stop
252 pub min_stop_pause: embassy_time::Duration,
253
244 /// Enable debug during sleep and stop. 254 /// Enable debug during sleep and stop.
245 /// 255 ///
246 /// May increase power consumption. Defaults to true. 256 /// May increase power consumption. Defaults to true.
@@ -294,6 +304,10 @@ impl Default for Config {
294 fn default() -> Self { 304 fn default() -> Self {
295 Self { 305 Self {
296 rcc: Default::default(), 306 rcc: Default::default(),
307 #[cfg(feature = "low-power")]
308 rtc: Default::default(),
309 #[cfg(feature = "low-power")]
310 min_stop_pause: embassy_time::Duration::from_millis(250),
297 #[cfg(dbgmcu)] 311 #[cfg(dbgmcu)]
298 enable_debug_during_sleep: true, 312 enable_debug_during_sleep: true,
299 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] 313 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))]
@@ -623,6 +637,12 @@ fn init_hw(config: Config) -> Peripherals {
623 exti::init(cs); 637 exti::init(cs);
624 638
625 rcc::init_rcc(cs, config.rcc); 639 rcc::init_rcc(cs, config.rcc);
640
641 #[cfg(feature = "low-power")]
642 crate::rtc::init_rtc(cs, config.rtc);
643
644 #[cfg(feature = "low-power")]
645 crate::time_driver::get_driver().set_min_stop_pause(cs, config.min_stop_pause);
626 } 646 }
627 647
628 p 648 p
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 1b66ca680..696dfe83f 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -41,12 +41,6 @@
41//! config.enable_debug_during_sleep = false; 41//! config.enable_debug_during_sleep = false;
42//! let p = embassy_stm32::init(config); 42//! let p = embassy_stm32::init(config);
43//! 43//!
44//! // give the RTC to the executor...
45//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
46//! static RTC: StaticCell<Rtc> = StaticCell::new();
47//! let rtc = RTC.init(rtc);
48//! embassy_stm32::low_power::stop_with_rtc(rtc);
49//!
50//! // your application here... 44//! // your application here...
51//! } 45//! }
52//! ``` 46//! ```
@@ -59,24 +53,69 @@ use core::marker::PhantomData;
59use core::sync::atomic::{Ordering, compiler_fence}; 53use core::sync::atomic::{Ordering, compiler_fence};
60 54
61use cortex_m::peripheral::SCB; 55use cortex_m::peripheral::SCB;
56use critical_section::CriticalSection;
62use embassy_executor::*; 57use embassy_executor::*;
63 58
64use crate::interrupt; 59use crate::interrupt;
65use crate::time_driver::{RtcDriver, get_driver}; 60use crate::time_driver::get_driver;
66 61
67const THREAD_PENDER: usize = usize::MAX; 62const THREAD_PENDER: usize = usize::MAX;
68 63
69use crate::rtc::Rtc;
70
71static mut EXECUTOR: Option<Executor> = None; 64static mut EXECUTOR: Option<Executor> = None;
72 65
66/// Prevent the device from going into the stop mode if held
67pub struct DeviceBusy(StopMode);
68
69impl DeviceBusy {
70 /// Create a new DeviceBusy with stop1.
71 pub fn new_stop1() -> Self {
72 Self::new(StopMode::Stop1)
73 }
74
75 /// Create a new DeviceBusy with stop2.
76 pub fn new_stop2() -> Self {
77 Self::new(StopMode::Stop2)
78 }
79
80 /// Create a new DeviceBusy.
81 pub fn new(stop_mode: StopMode) -> Self {
82 critical_section::with(|_| unsafe {
83 match stop_mode {
84 StopMode::Stop1 => {
85 crate::rcc::REFCOUNT_STOP1 += 1;
86 }
87 StopMode::Stop2 => {
88 crate::rcc::REFCOUNT_STOP2 += 1;
89 }
90 }
91 });
92
93 Self(stop_mode)
94 }
95}
96
97impl Drop for DeviceBusy {
98 fn drop(&mut self) {
99 critical_section::with(|_| unsafe {
100 match self.0 {
101 StopMode::Stop1 => {
102 crate::rcc::REFCOUNT_STOP1 -= 1;
103 }
104 StopMode::Stop2 => {
105 crate::rcc::REFCOUNT_STOP2 -= 1;
106 }
107 }
108 });
109 }
110}
111
73#[cfg(not(stm32u0))] 112#[cfg(not(stm32u0))]
74foreach_interrupt! { 113foreach_interrupt! {
75 (RTC, rtc, $block:ident, WKUP, $irq:ident) => { 114 (RTC, rtc, $block:ident, WKUP, $irq:ident) => {
76 #[interrupt] 115 #[interrupt]
77 #[allow(non_snake_case)] 116 #[allow(non_snake_case)]
78 unsafe fn $irq() { 117 unsafe fn $irq() {
79 EXECUTOR.as_mut().unwrap().on_wakeup_irq(); 118 Executor::on_wakeup_irq();
80 } 119 }
81 }; 120 };
82} 121}
@@ -87,31 +126,21 @@ foreach_interrupt! {
87 #[interrupt] 126 #[interrupt]
88 #[allow(non_snake_case)] 127 #[allow(non_snake_case)]
89 unsafe fn $irq() { 128 unsafe fn $irq() {
90 EXECUTOR.as_mut().unwrap().on_wakeup_irq(); 129 Executor::on_wakeup_irq();
91 } 130 }
92 }; 131 };
93} 132}
94 133
95#[allow(dead_code)]
96pub(crate) unsafe fn on_wakeup_irq() {
97 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
98}
99
100/// Configure STOP mode with RTC.
101pub fn stop_with_rtc(rtc: &'static Rtc) {
102 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
103}
104
105/// Get whether the core is ready to enter the given stop mode. 134/// Get whether the core is ready to enter the given stop mode.
106/// 135///
107/// This will return false if some peripheral driver is in use that 136/// This will return false if some peripheral driver is in use that
108/// prevents entering the given stop mode. 137/// prevents entering the given stop mode.
109pub fn stop_ready(stop_mode: StopMode) -> bool { 138pub fn stop_ready(stop_mode: StopMode) -> bool {
110 match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() { 139 critical_section::with(|cs| match Executor::stop_mode(cs) {
111 Some(StopMode::Stop2) => true, 140 Some(StopMode::Stop2) => true,
112 Some(StopMode::Stop1) => stop_mode == StopMode::Stop1, 141 Some(StopMode::Stop1) => stop_mode == StopMode::Stop1,
113 None => false, 142 None => false,
114 } 143 })
115} 144}
116 145
117/// Available Stop modes. 146/// Available Stop modes.
@@ -124,10 +153,10 @@ pub enum StopMode {
124 Stop2, 153 Stop2,
125} 154}
126 155
127#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))] 156#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32wlex, stm32u0))]
128use stm32_metapac::pwr::vals::Lpms; 157use stm32_metapac::pwr::vals::Lpms;
129 158
130#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32u0))] 159#[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba, stm32wlex, stm32u0))]
131impl Into<Lpms> for StopMode { 160impl Into<Lpms> for StopMode {
132 fn into(self) -> Lpms { 161 fn into(self) -> Lpms {
133 match self { 162 match self {
@@ -154,7 +183,6 @@ pub struct Executor {
154 inner: raw::Executor, 183 inner: raw::Executor,
155 not_send: PhantomData<*mut ()>, 184 not_send: PhantomData<*mut ()>,
156 scb: SCB, 185 scb: SCB,
157 time_driver: &'static RtcDriver,
158} 186}
159 187
160impl Executor { 188impl Executor {
@@ -167,7 +195,6 @@ impl Executor {
167 inner: raw::Executor::new(THREAD_PENDER as *mut ()), 195 inner: raw::Executor::new(THREAD_PENDER as *mut ()),
168 not_send: PhantomData, 196 not_send: PhantomData,
169 scb: cortex_m::Peripherals::steal().SCB, 197 scb: cortex_m::Peripherals::steal().SCB,
170 time_driver: get_driver(),
171 }); 198 });
172 199
173 let executor = EXECUTOR.as_mut().unwrap(); 200 let executor = EXECUTOR.as_mut().unwrap();
@@ -176,21 +203,31 @@ impl Executor {
176 }) 203 })
177 } 204 }
178 205
179 unsafe fn on_wakeup_irq(&mut self) { 206 pub(crate) unsafe fn on_wakeup_irq() {
180 self.time_driver.resume_time(); 207 critical_section::with(|cs| {
181 trace!("low power: resume"); 208 #[cfg(stm32wlex)]
182 } 209 {
183 210 let extscr = crate::pac::PWR.extscr().read();
184 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { 211 if extscr.c1stop2f() || extscr.c1stopf() {
185 self.time_driver.set_rtc(rtc); 212 // when we wake from any stop mode we need to re-initialize the rcc
186 213 crate::rcc::apply_resume_config();
187 rtc.enable_wakeup_line(); 214 if extscr.c1stop2f() {
188 215 // when we wake from STOP2, we need to re-initialize the time driver
189 trace!("low power: stop with rtc configured"); 216 crate::time_driver::init_timer(cs);
217 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer)
218 // and given that we just woke from STOP2, we can reset them
219 crate::rcc::REFCOUNT_STOP2 = 0;
220 crate::rcc::REFCOUNT_STOP1 = 0;
221 }
222 }
223 }
224 get_driver().resume_time(cs);
225 trace!("low power: resume");
226 });
190 } 227 }
191 228
192 fn stop_mode(&self) -> Option<StopMode> { 229 fn stop_mode(_cs: CriticalSection) -> Option<StopMode> {
193 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { 230 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 && crate::rcc::REFCOUNT_STOP1 == 0 } {
194 Some(StopMode::Stop2) 231 Some(StopMode::Stop2)
195 } else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } { 232 } else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
196 Some(StopMode::Stop1) 233 Some(StopMode::Stop1)
@@ -201,7 +238,7 @@ impl Executor {
201 238
202 #[allow(unused_variables)] 239 #[allow(unused_variables)]
203 fn configure_stop(&mut self, stop_mode: StopMode) { 240 fn configure_stop(&mut self, stop_mode: StopMode) {
204 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0, stm32wba))] 241 #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u0, stm32wba, stm32wlex))]
205 crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into())); 242 crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into()));
206 #[cfg(stm32h5)] 243 #[cfg(stm32h5)]
207 crate::pac::PWR.pmcr().modify(|v| { 244 crate::pac::PWR.pmcr().modify(|v| {
@@ -213,17 +250,22 @@ impl Executor {
213 250
214 fn configure_pwr(&mut self) { 251 fn configure_pwr(&mut self) {
215 self.scb.clear_sleepdeep(); 252 self.scb.clear_sleepdeep();
253 // Clear any previous stop flags
254 #[cfg(stm32wlex)]
255 crate::pac::PWR.extscr().modify(|w| {
256 w.set_c1cssf(true);
257 });
216 258
217 compiler_fence(Ordering::SeqCst); 259 compiler_fence(Ordering::SeqCst);
218 260
219 let stop_mode = self.stop_mode(); 261 let stop_mode = critical_section::with(|cs| Self::stop_mode(cs));
220 262
221 if stop_mode.is_none() { 263 if stop_mode.is_none() {
222 trace!("low power: not ready to stop"); 264 trace!("low power: not ready to stop");
223 return; 265 return;
224 } 266 }
225 267
226 if self.time_driver.pause_time().is_err() { 268 if get_driver().pause_time().is_err() {
227 trace!("low power: failed to pause time"); 269 trace!("low power: failed to pause time");
228 return; 270 return;
229 } 271 }
@@ -266,6 +308,19 @@ impl Executor {
266 executor.inner.poll(); 308 executor.inner.poll();
267 self.configure_pwr(); 309 self.configure_pwr();
268 asm!("wfe"); 310 asm!("wfe");
311 #[cfg(stm32wlex)]
312 {
313 let es = crate::pac::PWR.extscr().read();
314 match (es.c1stopf(), es.c1stop2f()) {
315 (true, false) => debug!("low power: wake from STOP1"),
316 (false, true) => debug!("low power: wake from STOP2"),
317 (true, true) => debug!("low power: wake from STOP1 and STOP2 ???"),
318 (false, false) => trace!("low power: stop mode not entered"),
319 };
320 crate::pac::PWR.extscr().modify(|w| {
321 w.set_c1cssf(false);
322 });
323 }
269 }; 324 };
270 } 325 }
271 } 326 }
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index 3b2a10581..5b367c043 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -1,6 +1,8 @@
1use core::sync::atomic::{Ordering, compiler_fence}; 1use core::sync::atomic::{Ordering, compiler_fence};
2 2
3use crate::pac::common::{RW, Reg}; 3use crate::pac::common::{RW, Reg};
4#[cfg(backup_sram)]
5use crate::pac::pwr::vals::Retention;
4pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; 6pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
5use crate::time::Hertz; 7use crate::time::Hertz;
6 8
@@ -89,6 +91,8 @@ pub struct LsConfig {
89 pub rtc: RtcClockSource, 91 pub rtc: RtcClockSource,
90 pub lsi: bool, 92 pub lsi: bool,
91 pub lse: Option<LseConfig>, 93 pub lse: Option<LseConfig>,
94 #[cfg(backup_sram)]
95 pub enable_backup_sram: bool,
92} 96}
93 97
94impl LsConfig { 98impl LsConfig {
@@ -113,6 +117,8 @@ impl LsConfig {
113 peripherals_clocked: false, 117 peripherals_clocked: false,
114 }), 118 }),
115 lsi: false, 119 lsi: false,
120 #[cfg(backup_sram)]
121 enable_backup_sram: false,
116 } 122 }
117 } 123 }
118 124
@@ -121,6 +127,8 @@ impl LsConfig {
121 rtc: RtcClockSource::LSI, 127 rtc: RtcClockSource::LSI,
122 lsi: true, 128 lsi: true,
123 lse: None, 129 lse: None,
130 #[cfg(backup_sram)]
131 enable_backup_sram: false,
124 } 132 }
125 } 133 }
126 134
@@ -129,6 +137,8 @@ impl LsConfig {
129 rtc: RtcClockSource::DISABLE, 137 rtc: RtcClockSource::DISABLE,
130 lsi: false, 138 lsi: false,
131 lse: None, 139 lse: None,
140 #[cfg(backup_sram)]
141 enable_backup_sram: false,
132 } 142 }
133 } 143 }
134} 144}
@@ -193,6 +203,22 @@ impl LsConfig {
193 while !csr.read().lsi1rdy() {} 203 while !csr.read().lsi1rdy() {}
194 } 204 }
195 205
206 // Enable backup regulator for peristent battery backed sram
207 #[cfg(backup_sram)]
208 {
209 unsafe { super::BKSRAM_RETAINED = crate::pac::PWR.bdcr().read().bren() == Retention::PRESERVED };
210
211 crate::pac::PWR.bdcr().modify(|w| {
212 w.set_bren(match self.enable_backup_sram {
213 true => Retention::PRESERVED,
214 false => Retention::LOST,
215 });
216 });
217
218 // Wait for backup regulator voltage to stabilize
219 while self.enable_backup_sram && !crate::pac::PWR.bdsr().read().brrdy() {}
220 }
221
196 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets. 222 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
197 // once set, changing it requires a backup domain reset. 223 // once set, changing it requires a backup domain reset.
198 // first check if the configuration matches what we want. 224 // first check if the configuration matches what we want.
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 2e1cbd702..584957c6d 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -1,3 +1,6 @@
1#[cfg(all(feature = "low-power", stm32wlex))]
2use core::mem::MaybeUninit;
3
1#[cfg(any(stm32l0, stm32l1))] 4#[cfg(any(stm32l0, stm32l1))]
2pub use crate::pac::pwr::vals::Vos as VoltageScale; 5pub use crate::pac::pwr::vals::Vos as VoltageScale;
3use crate::pac::rcc::regs::Cfgr; 6use crate::pac::rcc::regs::Cfgr;
@@ -11,6 +14,42 @@ use crate::time::Hertz;
11/// HSI speed 14/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000); 15pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13 16
17/// Saved RCC Config
18///
19/// Used when exiting STOP2 to re-enable clocks to their last configured state
20/// for chips that need it.
21#[cfg(all(feature = "low-power", stm32wlex))]
22static mut RESUME_RCC_CONFIG: MaybeUninit<Config> = MaybeUninit::uninit();
23
24/// Set the rcc config to be restored when exiting STOP2
25///
26/// Safety: Sets a mutable global.
27#[cfg(all(feature = "low-power", stm32wlex))]
28pub(crate) unsafe fn set_resume_config(config: Config) {
29 trace!("rcc set_resume_config()");
30 RESUME_RCC_CONFIG = MaybeUninit::new(config);
31}
32
33/// Get the rcc config to be restored when exiting STOP2
34///
35/// Safety: Reads a mutable global.
36#[cfg(all(feature = "low-power", stm32wlex))]
37pub(crate) unsafe fn get_resume_config() -> Config {
38 *(*core::ptr::addr_of_mut!(RESUME_RCC_CONFIG)).assume_init_ref()
39}
40
41#[cfg(all(feature = "low-power", stm32wlex))]
42/// Safety: should only be called from low power executable just after resuming from STOP2
43pub(crate) unsafe fn apply_resume_config() {
44 trace!("rcc apply_resume_config()");
45
46 while RCC.cfgr().read().sws() != Sysclk::MSI {}
47
48 let config = get_resume_config();
49
50 init(config);
51}
52
14#[derive(Clone, Copy, Eq, PartialEq)] 53#[derive(Clone, Copy, Eq, PartialEq)]
15pub enum HseMode { 54pub enum HseMode {
16 /// crystal/ceramic oscillator (HSEBYP=0) 55 /// crystal/ceramic oscillator (HSEBYP=0)
@@ -154,6 +193,10 @@ fn msi_enable(range: MSIRange) {
154} 193}
155 194
156pub(crate) unsafe fn init(config: Config) { 195pub(crate) unsafe fn init(config: Config) {
196 // save the rcc config because if we enter stop 2 we need to re-apply it on wakeup
197 #[cfg(all(feature = "low-power", stm32wlex))]
198 set_resume_config(config);
199
157 // Switch to MSI to prevent problems with PLL configuration. 200 // Switch to MSI to prevent problems with PLL configuration.
158 if !RCC.cr().read().msion() { 201 if !RCC.cr().read().msion() {
159 // Turn on MSI and configure it to 4MHz. 202 // Turn on MSI and configure it to 4MHz.
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index addfca3c3..01fa3a475 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -48,6 +48,9 @@ pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
48/// May be read without a critical section 48/// May be read without a critical section
49pub(crate) static mut REFCOUNT_STOP2: u32 = 0; 49pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
50 50
51#[cfg(backup_sram)]
52pub(crate) static mut BKSRAM_RETAINED: bool = false;
53
51#[cfg(not(feature = "_dual-core"))] 54#[cfg(not(feature = "_dual-core"))]
52/// Frozen clock frequencies 55/// Frozen clock frequencies
53/// 56///
@@ -390,7 +393,7 @@ pub fn disable<T: RccPeripheral>() {
390/// 393///
391/// This should only be called after `init`. 394/// This should only be called after `init`.
392#[cfg(not(feature = "_dual-core"))] 395#[cfg(not(feature = "_dual-core"))]
393pub fn reinit<'a>(config: Config, _rcc: &'a mut crate::Peri<'a, crate::peripherals::RCC>) { 396pub fn reinit(config: Config, _rcc: &'_ mut crate::Peri<'_, crate::peripherals::RCC>) {
394 critical_section::with(|cs| init_rcc(cs, config)) 397 critical_section::with(|cs| init_rcc(cs, config))
395} 398}
396 399
diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs
index 999f24714..e5bf30927 100644
--- a/embassy-stm32/src/rtc/low_power.rs
+++ b/embassy-stm32/src/rtc/low_power.rs
@@ -4,7 +4,7 @@ use embassy_time::{Duration, TICK_HZ};
4use super::{DateTimeError, Rtc, RtcError, bcd2_to_byte}; 4use super::{DateTimeError, Rtc, RtcError, bcd2_to_byte};
5use crate::interrupt::typelevel::Interrupt; 5use crate::interrupt::typelevel::Interrupt;
6use crate::peripherals::RTC; 6use crate::peripherals::RTC;
7use crate::rtc::SealedInstance; 7use crate::rtc::{RtcTimeProvider, SealedInstance};
8 8
9/// Represents an instant in time that can be substracted to compute a duration 9/// Represents an instant in time that can be substracted to compute a duration
10pub(super) struct RtcInstant { 10pub(super) struct RtcInstant {
@@ -68,7 +68,7 @@ pub(crate) enum WakeupPrescaler {
68} 68}
69 69
70#[cfg(any( 70#[cfg(any(
71 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba 71 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba, stm32wlex
72))] 72))]
73impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 73impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
74 fn from(val: WakeupPrescaler) -> Self { 74 fn from(val: WakeupPrescaler) -> Self {
@@ -84,7 +84,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
84} 84}
85 85
86#[cfg(any( 86#[cfg(any(
87 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba 87 stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba, stm32wlex
88))] 88))]
89impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 89impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
90 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { 90 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
@@ -117,7 +117,7 @@ impl WakeupPrescaler {
117impl Rtc { 117impl Rtc {
118 /// Return the current instant. 118 /// Return the current instant.
119 fn instant(&self) -> Result<RtcInstant, RtcError> { 119 fn instant(&self) -> Result<RtcInstant, RtcError> {
120 self.time_provider().read(|_, tr, ss| { 120 RtcTimeProvider::new().read(|_, tr, ss| {
121 let second = bcd2_to_byte((tr.st(), tr.su())); 121 let second = bcd2_to_byte((tr.st(), tr.su()));
122 122
123 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime) 123 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime)
@@ -127,7 +127,7 @@ impl Rtc {
127 /// start the wakeup alarm and with a duration that is as close to but less than 127 /// start the wakeup alarm and with a duration that is as close to but less than
128 /// the requested duration, and record the instant the wakeup alarm was started 128 /// the requested duration, and record the instant the wakeup alarm was started
129 pub(crate) fn start_wakeup_alarm( 129 pub(crate) fn start_wakeup_alarm(
130 &self, 130 &mut self,
131 requested_duration: embassy_time::Duration, 131 requested_duration: embassy_time::Duration,
132 cs: critical_section::CriticalSection, 132 cs: critical_section::CriticalSection,
133 ) { 133 ) {
@@ -179,7 +179,10 @@ impl Rtc {
179 179
180 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` 180 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
181 /// was called, otherwise none 181 /// was called, otherwise none
182 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { 182 pub(crate) fn stop_wakeup_alarm(
183 &mut self,
184 cs: critical_section::CriticalSection,
185 ) -> Option<embassy_time::Duration> {
183 let instant = self.instant().unwrap(); 186 let instant = self.instant().unwrap();
184 if RTC::regs().cr().read().wute() { 187 if RTC::regs().cr().read().wute() {
185 trace!("rtc: stop wakeup alarm at {}", instant); 188 trace!("rtc: stop wakeup alarm at {}", instant);
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index bc6df528b..116b3c7ed 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -5,9 +5,13 @@ mod datetime;
5mod low_power; 5mod low_power;
6 6
7#[cfg(feature = "low-power")] 7#[cfg(feature = "low-power")]
8use core::cell::Cell; 8use core::cell::{Cell, RefCell, RefMut};
9#[cfg(feature = "low-power")]
10use core::ops;
9 11
10#[cfg(feature = "low-power")] 12#[cfg(feature = "low-power")]
13use critical_section::CriticalSection;
14#[cfg(feature = "low-power")]
11use embassy_sync::blocking_mutex::Mutex; 15use embassy_sync::blocking_mutex::Mutex;
12#[cfg(feature = "low-power")] 16#[cfg(feature = "low-power")]
13use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 17use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
@@ -44,11 +48,17 @@ pub enum RtcError {
44} 48}
45 49
46/// Provides immutable access to the current time of the RTC. 50/// Provides immutable access to the current time of the RTC.
51#[derive(Clone)]
47pub struct RtcTimeProvider { 52pub struct RtcTimeProvider {
48 _private: (), 53 _private: (),
49} 54}
50 55
51impl RtcTimeProvider { 56impl RtcTimeProvider {
57 /// Create a new RTC time provider instance.
58 pub(self) const fn new() -> Self {
59 Self { _private: () }
60 }
61
52 /// Return the current datetime. 62 /// Return the current datetime.
53 /// 63 ///
54 /// # Errors 64 /// # Errors
@@ -106,6 +116,50 @@ impl RtcTimeProvider {
106 } 116 }
107} 117}
108 118
119#[cfg(feature = "low-power")]
120/// Contains an RTC driver.
121pub struct RtcContainer {
122 pub(self) mutex: &'static Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>,
123}
124
125#[cfg(feature = "low-power")]
126impl RtcContainer {
127 pub(self) const fn new() -> Self {
128 Self {
129 mutex: &crate::time_driver::get_driver().rtc,
130 }
131 }
132
133 /// Acquire an RTC borrow.
134 pub fn borrow_mut<'a>(&self, cs: CriticalSection<'a>) -> RtcBorrow<'a> {
135 RtcBorrow {
136 ref_mut: self.mutex.borrow(cs).borrow_mut(),
137 }
138 }
139}
140
141#[cfg(feature = "low-power")]
142/// Contains an RTC borrow.
143pub struct RtcBorrow<'a> {
144 pub(self) ref_mut: RefMut<'a, Option<Rtc>>,
145}
146
147#[cfg(feature = "low-power")]
148impl<'a> ops::Deref for RtcBorrow<'a> {
149 type Target = Rtc;
150
151 fn deref(&self) -> &Self::Target {
152 self.ref_mut.as_ref().unwrap()
153 }
154}
155
156#[cfg(feature = "low-power")]
157impl<'a> ops::DerefMut for RtcBorrow<'a> {
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 self.ref_mut.as_mut().unwrap()
160 }
161}
162
109/// RTC driver. 163/// RTC driver.
110pub struct Rtc { 164pub struct Rtc {
111 #[cfg(feature = "low-power")] 165 #[cfg(feature = "low-power")]
@@ -121,13 +175,21 @@ pub struct RtcConfig {
121 /// 175 ///
122 /// A high counter frequency may impact stop power consumption 176 /// A high counter frequency may impact stop power consumption
123 pub frequency: Hertz, 177 pub frequency: Hertz,
178
179 #[cfg(feature = "_allow-disable-rtc")]
180 /// Allow disabling the rtc, even when stop is configured
181 pub _disable_rtc: bool,
124} 182}
125 183
126impl Default for RtcConfig { 184impl Default for RtcConfig {
127 /// LSI with prescalers assuming 32.768 kHz. 185 /// LSI with prescalers assuming 32.768 kHz.
128 /// Raw sub-seconds in 1/256. 186 /// Raw sub-seconds in 1/256.
129 fn default() -> Self { 187 fn default() -> Self {
130 RtcConfig { frequency: Hertz(256) } 188 RtcConfig {
189 frequency: Hertz(256),
190 #[cfg(feature = "_allow-disable-rtc")]
191 _disable_rtc: false,
192 }
131 } 193 }
132} 194}
133 195
@@ -145,8 +207,19 @@ pub enum RtcCalibrationCyclePeriod {
145} 207}
146 208
147impl Rtc { 209impl Rtc {
210 #[cfg(not(feature = "low-power"))]
211 /// Create a new RTC instance.
212 pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> (Self, RtcTimeProvider) {
213 (Self::new_inner(rtc_config), RtcTimeProvider::new())
214 }
215
216 #[cfg(feature = "low-power")]
148 /// Create a new RTC instance. 217 /// Create a new RTC instance.
149 pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { 218 pub fn new(_rtc: Peri<'static, RTC>) -> (RtcContainer, RtcTimeProvider) {
219 (RtcContainer::new(), RtcTimeProvider::new())
220 }
221
222 pub(self) fn new_inner(rtc_config: RtcConfig) -> Self {
150 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 223 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
151 crate::rcc::enable_and_reset::<RTC>(); 224 crate::rcc::enable_and_reset::<RTC>();
152 225
@@ -165,10 +238,13 @@ impl Rtc {
165 // Wait for the clock to update after initialization 238 // Wait for the clock to update after initialization
166 #[cfg(not(rtc_v2_f2))] 239 #[cfg(not(rtc_v2_f2))]
167 { 240 {
168 let now = this.time_provider().read(|_, _, ss| Ok(ss)).unwrap(); 241 let now = RtcTimeProvider::new().read(|_, _, ss| Ok(ss)).unwrap();
169 while now == this.time_provider().read(|_, _, ss| Ok(ss)).unwrap() {} 242 while now == RtcTimeProvider::new().read(|_, _, ss| Ok(ss)).unwrap() {}
170 } 243 }
171 244
245 #[cfg(feature = "low-power")]
246 this.enable_wakeup_line();
247
172 this 248 this
173 } 249 }
174 250
@@ -177,11 +253,6 @@ impl Rtc {
177 freqs.rtc.to_hertz().unwrap() 253 freqs.rtc.to_hertz().unwrap()
178 } 254 }
179 255
180 /// Acquire a [`RtcTimeProvider`] instance.
181 pub const fn time_provider(&self) -> RtcTimeProvider {
182 RtcTimeProvider { _private: () }
183 }
184
185 /// Set the datetime to a new value. 256 /// Set the datetime to a new value.
186 /// 257 ///
187 /// # Errors 258 /// # Errors
@@ -225,15 +296,6 @@ impl Rtc {
225 Ok(()) 296 Ok(())
226 } 297 }
227 298
228 /// Return the current datetime.
229 ///
230 /// # Errors
231 ///
232 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
233 pub fn now(&self) -> Result<DateTime, RtcError> {
234 self.time_provider().now()
235 }
236
237 /// Check if daylight savings time is active. 299 /// Check if daylight savings time is active.
238 pub fn get_daylight_savings(&self) -> bool { 300 pub fn get_daylight_savings(&self) -> bool {
239 let cr = RTC::regs().cr().read(); 301 let cr = RTC::regs().cr().read();
@@ -315,3 +377,15 @@ trait SealedInstance {
315 377
316 // fn apply_config(&mut self, rtc_config: RtcConfig); 378 // fn apply_config(&mut self, rtc_config: RtcConfig);
317} 379}
380
381#[cfg(feature = "low-power")]
382pub(crate) fn init_rtc(cs: CriticalSection, config: RtcConfig) {
383 #[cfg(feature = "_allow-disable-rtc")]
384 if config._disable_rtc {
385 return;
386 }
387
388 crate::time_driver::get_driver().set_rtc(cs, Rtc::new_inner(config));
389
390 trace!("low power: stop with rtc configured");
391}
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 23f6ccb0c..8ac022536 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -93,7 +93,7 @@ impl super::Rtc {
93 }) 93 })
94 } 94 }
95 95
96 pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R 96 pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
97 where 97 where
98 F: FnOnce(crate::pac::rtc::Rtc) -> R, 98 F: FnOnce(crate::pac::rtc::Rtc) -> R,
99 { 99 {
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 01da5d70a..f7ebea73e 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -95,7 +95,7 @@ impl super::Rtc {
95 }) 95 })
96 } 96 }
97 97
98 pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R 98 pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
99 where 99 where
100 F: FnOnce(crate::pac::rtc::Rtc) -> R, 100 F: FnOnce(crate::pac::rtc::Rtc) -> R,
101 { 101 {
@@ -131,7 +131,7 @@ impl SealedInstance for crate::peripherals::RTC {
131 131
132 #[cfg(feature = "low-power")] 132 #[cfg(feature = "low-power")]
133 cfg_if::cfg_if!( 133 cfg_if::cfg_if!(
134 if #[cfg(stm32g4)] { 134 if #[cfg(any(stm32g4, stm32wlex))] {
135 const EXTI_WAKEUP_LINE: usize = 20; 135 const EXTI_WAKEUP_LINE: usize = 20;
136 } else if #[cfg(stm32g0)] { 136 } else if #[cfg(stm32g0)] {
137 const EXTI_WAKEUP_LINE: usize = 19; 137 const EXTI_WAKEUP_LINE: usize = 19;
@@ -142,7 +142,7 @@ impl SealedInstance for crate::peripherals::RTC {
142 142
143 #[cfg(feature = "low-power")] 143 #[cfg(feature = "low-power")]
144 cfg_if::cfg_if!( 144 cfg_if::cfg_if!(
145 if #[cfg(stm32g4)] { 145 if #[cfg(any(stm32g4, stm32wlex))] {
146 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; 146 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
147 } else if #[cfg(any(stm32g0, stm32u0))] { 147 } else if #[cfg(any(stm32g0, stm32u0))] {
148 type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP; 148 type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP;
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 408d1b764..e05131040 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -1032,12 +1032,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1032 1032
1033 /// Wait for a previously started datapath transfer to complete from an interrupt. 1033 /// Wait for a previously started datapath transfer to complete from an interrupt.
1034 #[inline] 1034 #[inline]
1035 #[allow(unused)]
1035 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> { 1036 async fn complete_datapath_transfer(block: bool) -> Result<(), Error> {
1036 let regs = T::regs();
1037
1038 let res = poll_fn(|cx| { 1037 let res = poll_fn(|cx| {
1038 // Compiler might not be sufficiently constrained here
1039 // https://github.com/embassy-rs/embassy/issues/4723
1039 T::state().register(cx.waker()); 1040 T::state().register(cx.waker());
1040 let status = regs.star().read(); 1041 let status = T::regs().star().read();
1041 1042
1042 if status.dcrcfail() { 1043 if status.dcrcfail() {
1043 return Poll::Ready(Err(Error::Crc)); 1044 return Poll::Ready(Err(Error::Crc));
@@ -1052,10 +1053,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1052 if status.stbiterr() { 1053 if status.stbiterr() {
1053 return Poll::Ready(Err(Error::StBitErr)); 1054 return Poll::Ready(Err(Error::StBitErr));
1054 } 1055 }
1056 #[cfg(sdmmc_v1)]
1055 let done = match block { 1057 let done = match block {
1056 true => status.dbckend(), 1058 true => status.dbckend(),
1057 false => status.dataend(), 1059 false => status.dataend(),
1058 }; 1060 };
1061 #[cfg(sdmmc_v2)]
1062 let done = status.dataend();
1059 if done { 1063 if done {
1060 return Poll::Ready(Ok(())); 1064 return Poll::Ready(Ok(()));
1061 } 1065 }
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index c27d09ea7..abb80ed26 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -125,26 +125,69 @@ impl Config {
125 ) 125 )
126 } 126 }
127} 127}
128
129/// SPI communication mode
130pub mod mode {
131 use stm32_metapac::spi::vals;
132
133 trait SealedMode {}
134
135 /// Trait for SPI communication mode operations.
136 #[allow(private_bounds)]
137 pub trait CommunicationMode: SealedMode {
138 /// Spi communication mode
139 #[cfg(not(any(spi_v4, spi_v5, spi_v6)))]
140 const MASTER: vals::Mstr;
141 /// Spi communication mode
142 #[cfg(any(spi_v4, spi_v5, spi_v6))]
143 const MASTER: vals::Master;
144 }
145
146 /// Mode allowing for SPI master operations.
147 pub struct Master;
148 /// Mode allowing for SPI slave operations.
149 pub struct Slave;
150
151 impl SealedMode for Master {}
152 impl CommunicationMode for Master {
153 #[cfg(not(any(spi_v4, spi_v5, spi_v6)))]
154 const MASTER: vals::Mstr = vals::Mstr::MASTER;
155 #[cfg(any(spi_v4, spi_v5, spi_v6))]
156 const MASTER: vals::Master = vals::Master::MASTER;
157 }
158
159 impl SealedMode for Slave {}
160 impl CommunicationMode for Slave {
161 #[cfg(not(any(spi_v4, spi_v5, spi_v6)))]
162 const MASTER: vals::Mstr = vals::Mstr::SLAVE;
163 #[cfg(any(spi_v4, spi_v5, spi_v6))]
164 const MASTER: vals::Master = vals::Master::SLAVE;
165 }
166}
167use mode::{CommunicationMode, Master, Slave};
168
128/// SPI driver. 169/// SPI driver.
129pub struct Spi<'d, M: PeriMode> { 170pub struct Spi<'d, M: PeriMode, CM: CommunicationMode> {
130 pub(crate) info: &'static Info, 171 pub(crate) info: &'static Info,
131 kernel_clock: Hertz, 172 kernel_clock: Hertz,
132 sck: Option<Peri<'d, AnyPin>>, 173 sck: Option<Peri<'d, AnyPin>>,
133 mosi: Option<Peri<'d, AnyPin>>, 174 mosi: Option<Peri<'d, AnyPin>>,
134 miso: Option<Peri<'d, AnyPin>>, 175 miso: Option<Peri<'d, AnyPin>>,
176 nss: Option<Peri<'d, AnyPin>>,
135 tx_dma: Option<ChannelAndRequest<'d>>, 177 tx_dma: Option<ChannelAndRequest<'d>>,
136 rx_dma: Option<ChannelAndRequest<'d>>, 178 rx_dma: Option<ChannelAndRequest<'d>>,
137 _phantom: PhantomData<M>, 179 _phantom: PhantomData<(M, CM)>,
138 current_word_size: word_impl::Config, 180 current_word_size: word_impl::Config,
139 gpio_speed: Speed, 181 gpio_speed: Speed,
140} 182}
141 183
142impl<'d, M: PeriMode> Spi<'d, M> { 184impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> {
143 fn new_inner<T: Instance>( 185 fn new_inner<T: Instance>(
144 _peri: Peri<'d, T>, 186 _peri: Peri<'d, T>,
145 sck: Option<Peri<'d, AnyPin>>, 187 sck: Option<Peri<'d, AnyPin>>,
146 mosi: Option<Peri<'d, AnyPin>>, 188 mosi: Option<Peri<'d, AnyPin>>,
147 miso: Option<Peri<'d, AnyPin>>, 189 miso: Option<Peri<'d, AnyPin>>,
190 nss: Option<Peri<'d, AnyPin>>,
148 tx_dma: Option<ChannelAndRequest<'d>>, 191 tx_dma: Option<ChannelAndRequest<'d>>,
149 rx_dma: Option<ChannelAndRequest<'d>>, 192 rx_dma: Option<ChannelAndRequest<'d>>,
150 config: Config, 193 config: Config,
@@ -155,6 +198,7 @@ impl<'d, M: PeriMode> Spi<'d, M> {
155 sck, 198 sck,
156 mosi, 199 mosi,
157 miso, 200 miso,
201 nss,
158 tx_dma, 202 tx_dma,
159 rx_dma, 203 rx_dma,
160 current_word_size: <u8 as SealedWord>::CONFIG, 204 current_word_size: <u8 as SealedWord>::CONFIG,
@@ -183,12 +227,12 @@ impl<'d, M: PeriMode> Spi<'d, M> {
183 w.set_cpha(cpha); 227 w.set_cpha(cpha);
184 w.set_cpol(cpol); 228 w.set_cpol(cpol);
185 229
186 w.set_mstr(vals::Mstr::MASTER); 230 w.set_mstr(CM::MASTER);
187 w.set_br(br); 231 w.set_br(br);
188 w.set_spe(true); 232 w.set_spe(true);
189 w.set_lsbfirst(lsbfirst); 233 w.set_lsbfirst(lsbfirst);
190 w.set_ssi(true); 234 w.set_ssi(CM::MASTER == vals::Mstr::MASTER);
191 w.set_ssm(true); 235 w.set_ssm(CM::MASTER == vals::Mstr::MASTER);
192 w.set_crcen(false); 236 w.set_crcen(false);
193 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); 237 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
194 // we're doing "fake rxonly", by actually writing one 238 // we're doing "fake rxonly", by actually writing one
@@ -210,11 +254,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
210 w.set_cpha(cpha); 254 w.set_cpha(cpha);
211 w.set_cpol(cpol); 255 w.set_cpol(cpol);
212 256
213 w.set_mstr(vals::Mstr::MASTER); 257 w.set_mstr(CM::MASTER);
214 w.set_br(br); 258 w.set_br(br);
215 w.set_lsbfirst(lsbfirst); 259 w.set_lsbfirst(lsbfirst);
216 w.set_ssi(true); 260 w.set_ssi(CM::MASTER == vals::Mstr::MASTER);
217 w.set_ssm(true); 261 w.set_ssm(CM::MASTER == vals::Mstr::MASTER);
218 w.set_crcen(false); 262 w.set_crcen(false);
219 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); 263 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
220 w.set_spe(true); 264 w.set_spe(true);
@@ -229,8 +273,8 @@ impl<'d, M: PeriMode> Spi<'d, M> {
229 w.set_cpha(cpha); 273 w.set_cpha(cpha);
230 w.set_cpol(cpol); 274 w.set_cpol(cpol);
231 w.set_lsbfirst(lsbfirst); 275 w.set_lsbfirst(lsbfirst);
232 w.set_ssm(true); 276 w.set_ssm(CM::MASTER == vals::Master::MASTER);
233 w.set_master(vals::Master::MASTER); 277 w.set_master(CM::MASTER);
234 w.set_comm(vals::Comm::FULL_DUPLEX); 278 w.set_comm(vals::Comm::FULL_DUPLEX);
235 w.set_ssom(vals::Ssom::ASSERTED); 279 w.set_ssom(vals::Ssom::ASSERTED);
236 w.set_midi(0); 280 w.set_midi(0);
@@ -469,7 +513,30 @@ impl<'d, M: PeriMode> Spi<'d, M> {
469 } 513 }
470} 514}
471 515
472impl<'d> Spi<'d, Blocking> { 516impl<'d> Spi<'d, Blocking, Slave> {
517 /// Create a new blocking SPI slave driver.
518 pub fn new_blocking_slave<T: Instance, #[cfg(afio)] A>(
519 peri: Peri<'d, T>,
520 sck: Peri<'d, if_afio!(impl SckPin<T, A>)>,
521 mosi: Peri<'d, if_afio!(impl MosiPin<T, A>)>,
522 miso: Peri<'d, if_afio!(impl MisoPin<T, A>)>,
523 cs: Peri<'d, if_afio!(impl CsPin<T, A>)>,
524 config: Config,
525 ) -> Self {
526 Self::new_inner(
527 peri,
528 new_pin!(sck, config.sck_af()),
529 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
530 new_pin!(miso, AfType::input(config.miso_pull)),
531 new_pin!(cs, AfType::input(Pull::None)),
532 None,
533 None,
534 config,
535 )
536 }
537}
538
539impl<'d> Spi<'d, Blocking, Master> {
473 /// Create a new blocking SPI driver. 540 /// Create a new blocking SPI driver.
474 pub fn new_blocking<T: Instance, #[cfg(afio)] A>( 541 pub fn new_blocking<T: Instance, #[cfg(afio)] A>(
475 peri: Peri<'d, T>, 542 peri: Peri<'d, T>,
@@ -485,6 +552,7 @@ impl<'d> Spi<'d, Blocking> {
485 new_pin!(miso, AfType::input(config.miso_pull)), 552 new_pin!(miso, AfType::input(config.miso_pull)),
486 None, 553 None,
487 None, 554 None,
555 None,
488 config, 556 config,
489 ) 557 )
490 } 558 }
@@ -503,6 +571,7 @@ impl<'d> Spi<'d, Blocking> {
503 new_pin!(miso, AfType::input(config.miso_pull)), 571 new_pin!(miso, AfType::input(config.miso_pull)),
504 None, 572 None,
505 None, 573 None,
574 None,
506 config, 575 config,
507 ) 576 )
508 } 577 }
@@ -521,6 +590,7 @@ impl<'d> Spi<'d, Blocking> {
521 None, 590 None,
522 None, 591 None,
523 None, 592 None,
593 None,
524 config, 594 config,
525 ) 595 )
526 } 596 }
@@ -540,12 +610,38 @@ impl<'d> Spi<'d, Blocking> {
540 None, 610 None,
541 None, 611 None,
542 None, 612 None,
613 None,
614 config,
615 )
616 }
617}
618
619impl<'d> Spi<'d, Async, Slave> {
620 /// Create a new SPI slave driver.
621 pub fn new_slave<T: Instance, #[cfg(afio)] A>(
622 peri: Peri<'d, T>,
623 sck: Peri<'d, if_afio!(impl SckPin<T, A>)>,
624 mosi: Peri<'d, if_afio!(impl MosiPin<T, A>)>,
625 miso: Peri<'d, if_afio!(impl MisoPin<T, A>)>,
626 cs: Peri<'d, if_afio!(impl CsPin<T, A>)>,
627 tx_dma: Peri<'d, impl TxDma<T>>,
628 rx_dma: Peri<'d, impl RxDma<T>>,
629 config: Config,
630 ) -> Self {
631 Self::new_inner(
632 peri,
633 new_pin!(sck, config.sck_af()),
634 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
635 new_pin!(miso, AfType::input(config.miso_pull)),
636 new_pin!(cs, AfType::input(Pull::None)),
637 new_dma!(tx_dma),
638 new_dma!(rx_dma),
543 config, 639 config,
544 ) 640 )
545 } 641 }
546} 642}
547 643
548impl<'d> Spi<'d, Async> { 644impl<'d> Spi<'d, Async, Master> {
549 /// Create a new SPI driver. 645 /// Create a new SPI driver.
550 pub fn new<T: Instance, #[cfg(afio)] A>( 646 pub fn new<T: Instance, #[cfg(afio)] A>(
551 peri: Peri<'d, T>, 647 peri: Peri<'d, T>,
@@ -561,6 +657,7 @@ impl<'d> Spi<'d, Async> {
561 new_pin!(sck, config.sck_af()), 657 new_pin!(sck, config.sck_af()),
562 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), 658 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
563 new_pin!(miso, AfType::input(config.miso_pull)), 659 new_pin!(miso, AfType::input(config.miso_pull)),
660 None,
564 new_dma!(tx_dma), 661 new_dma!(tx_dma),
565 new_dma!(rx_dma), 662 new_dma!(rx_dma),
566 config, 663 config,
@@ -581,6 +678,7 @@ impl<'d> Spi<'d, Async> {
581 new_pin!(sck, config.sck_af()), 678 new_pin!(sck, config.sck_af()),
582 None, 679 None,
583 new_pin!(miso, AfType::input(config.miso_pull)), 680 new_pin!(miso, AfType::input(config.miso_pull)),
681 None,
584 #[cfg(any(spi_v1, spi_v2, spi_v3))] 682 #[cfg(any(spi_v1, spi_v2, spi_v3))]
585 new_dma!(tx_dma), 683 new_dma!(tx_dma),
586 #[cfg(any(spi_v4, spi_v5, spi_v6))] 684 #[cfg(any(spi_v4, spi_v5, spi_v6))]
@@ -603,6 +701,7 @@ impl<'d> Spi<'d, Async> {
603 new_pin!(sck, config.sck_af()), 701 new_pin!(sck, config.sck_af()),
604 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), 702 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
605 None, 703 None,
704 None,
606 new_dma!(tx_dma), 705 new_dma!(tx_dma),
607 None, 706 None,
608 config, 707 config,
@@ -623,6 +722,7 @@ impl<'d> Spi<'d, Async> {
623 None, 722 None,
624 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), 723 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
625 None, 724 None,
725 None,
626 new_dma!(tx_dma), 726 new_dma!(tx_dma),
627 None, 727 None,
628 config, 728 config,
@@ -646,7 +746,7 @@ impl<'d> Spi<'d, Async> {
646 config.bit_order = BitOrder::MsbFirst; 746 config.bit_order = BitOrder::MsbFirst;
647 config.frequency = freq; 747 config.frequency = freq;
648 748
649 Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config) 749 Self::new_inner(peri, None, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
650 } 750 }
651 751
652 #[allow(dead_code)] 752 #[allow(dead_code)]
@@ -656,9 +756,11 @@ impl<'d> Spi<'d, Async> {
656 rx_dma: Option<ChannelAndRequest<'d>>, 756 rx_dma: Option<ChannelAndRequest<'d>>,
657 config: Config, 757 config: Config,
658 ) -> Self { 758 ) -> Self {
659 Self::new_inner(peri, None, None, None, tx_dma, rx_dma, config) 759 Self::new_inner(peri, None, None, None, None, tx_dma, rx_dma, config)
660 } 760 }
761}
661 762
763impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> {
662 /// SPI write, using DMA. 764 /// SPI write, using DMA.
663 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> { 765 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> {
664 if data.is_empty() { 766 if data.is_empty() {
@@ -888,11 +990,12 @@ impl<'d> Spi<'d, Async> {
888 } 990 }
889} 991}
890 992
891impl<'d, M: PeriMode> Drop for Spi<'d, M> { 993impl<'d, M: PeriMode, CM: CommunicationMode> Drop for Spi<'d, M, CM> {
892 fn drop(&mut self) { 994 fn drop(&mut self) {
893 self.sck.as_ref().map(|x| x.set_as_disconnected()); 995 self.sck.as_ref().map(|x| x.set_as_disconnected());
894 self.mosi.as_ref().map(|x| x.set_as_disconnected()); 996 self.mosi.as_ref().map(|x| x.set_as_disconnected());
895 self.miso.as_ref().map(|x| x.set_as_disconnected()); 997 self.miso.as_ref().map(|x| x.set_as_disconnected());
998 self.nss.as_ref().map(|x| x.set_as_disconnected());
896 999
897 self.info.rcc.disable(); 1000 self.info.rcc.disable();
898 } 1001 }
@@ -1127,7 +1230,7 @@ fn write_word<W: Word>(regs: Regs, tx_word: W) -> Result<(), Error> {
1127// some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289 1230// some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289
1128macro_rules! impl_blocking { 1231macro_rules! impl_blocking {
1129 ($w:ident) => { 1232 ($w:ident) => {
1130 impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M> { 1233 impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M, CM> {
1131 type Error = Error; 1234 type Error = Error;
1132 1235
1133 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> { 1236 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
@@ -1135,7 +1238,7 @@ macro_rules! impl_blocking {
1135 } 1238 }
1136 } 1239 }
1137 1240
1138 impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M> { 1241 impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M, CM> {
1139 type Error = Error; 1242 type Error = Error;
1140 1243
1141 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> { 1244 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
@@ -1149,11 +1252,11 @@ macro_rules! impl_blocking {
1149impl_blocking!(u8); 1252impl_blocking!(u8);
1150impl_blocking!(u16); 1253impl_blocking!(u16);
1151 1254
1152impl<'d, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, M> { 1255impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_1::spi::ErrorType for Spi<'d, M, CM> {
1153 type Error = Error; 1256 type Error = Error;
1154} 1257}
1155 1258
1156impl<'d, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M> { 1259impl<'d, W: Word, M: PeriMode, CM: CommunicationMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M, CM> {
1157 fn flush(&mut self) -> Result<(), Self::Error> { 1260 fn flush(&mut self) -> Result<(), Self::Error> {
1158 Ok(()) 1261 Ok(())
1159 } 1262 }
@@ -1186,7 +1289,7 @@ impl embedded_hal_1::spi::Error for Error {
1186 } 1289 }
1187} 1290}
1188 1291
1189impl<'d, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async> { 1292impl<'d, W: Word, CM: CommunicationMode> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async, CM> {
1190 async fn flush(&mut self) -> Result<(), Self::Error> { 1293 async fn flush(&mut self) -> Result<(), Self::Error> {
1191 Ok(()) 1294 Ok(())
1192 } 1295 }
@@ -1328,7 +1431,7 @@ foreach_peripheral!(
1328 }; 1431 };
1329); 1432);
1330 1433
1331impl<'d, M: PeriMode> SetConfig for Spi<'d, M> { 1434impl<'d, M: PeriMode, CM: CommunicationMode> SetConfig for Spi<'d, M, CM> {
1332 type Config = Config; 1435 type Config = Config;
1333 type ConfigError = (); 1436 type ConfigError = ();
1334 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 1437 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 74b10a183..7db51d72e 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -1,6 +1,8 @@
1#![allow(non_snake_case)] 1#![allow(non_snake_case)]
2 2
3use core::cell::{Cell, RefCell}; 3use core::cell::{Cell, RefCell};
4#[cfg(all(feature = "low-power", stm32wlex))]
5use core::sync::atomic::AtomicU16;
4use core::sync::atomic::{AtomicU32, Ordering, compiler_fence}; 6use core::sync::atomic::{AtomicU32, Ordering, compiler_fence};
5 7
6use critical_section::CriticalSection; 8use critical_section::CriticalSection;
@@ -213,7 +215,13 @@ pub(crate) struct RtcDriver {
213 period: AtomicU32, 215 period: AtomicU32,
214 alarm: Mutex<CriticalSectionRawMutex, AlarmState>, 216 alarm: Mutex<CriticalSectionRawMutex, AlarmState>,
215 #[cfg(feature = "low-power")] 217 #[cfg(feature = "low-power")]
216 rtc: Mutex<CriticalSectionRawMutex, Cell<Option<&'static Rtc>>>, 218 pub(crate) rtc: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>,
219 #[cfg(feature = "low-power")]
220 /// The minimum pause time beyond which the executor will enter a low-power state.
221 min_stop_pause: Mutex<CriticalSectionRawMutex, Cell<embassy_time::Duration>>,
222 /// Saved count for the timer (its value is lost when entering STOP2)
223 #[cfg(all(feature = "low-power", stm32wlex))]
224 saved_count: AtomicU16,
217 queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>, 225 queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>,
218} 226}
219 227
@@ -221,12 +229,18 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
221 period: AtomicU32::new(0), 229 period: AtomicU32::new(0),
222 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()), 230 alarm: Mutex::const_new(CriticalSectionRawMutex::new(), AlarmState::new()),
223 #[cfg(feature = "low-power")] 231 #[cfg(feature = "low-power")]
224 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 232 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), RefCell::new(None)),
233 #[cfg(feature = "low-power")]
234 min_stop_pause: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(embassy_time::Duration::from_millis(0))),
235 #[cfg(all(feature = "low-power", stm32wlex))]
236 saved_count: AtomicU16::new(0),
225 queue: Mutex::new(RefCell::new(Queue::new())) 237 queue: Mutex::new(RefCell::new(Queue::new()))
226}); 238});
227 239
228impl RtcDriver { 240impl RtcDriver {
229 fn init(&'static self, cs: critical_section::CriticalSection) { 241 /// initialize the timer, but don't start it. Used for chips like stm32wle5
242 /// for low power where the timer config is lost in STOP2.
243 fn init_timer(&'static self, cs: critical_section::CriticalSection) {
230 let r = regs_gp16(); 244 let r = regs_gp16();
231 245
232 rcc::enable_and_reset_with_cs::<T>(cs); 246 rcc::enable_and_reset_with_cs::<T>(cs);
@@ -259,10 +273,16 @@ impl RtcDriver {
259 w.set_ccie(0, true); 273 w.set_ccie(0, true);
260 }); 274 });
261 275
276 #[cfg(all(feature = "low-power", stm32wlex))]
277 r.cnt().write(|w| w.set_cnt(self.saved_count.load(Ordering::SeqCst)));
278
262 <T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend(); 279 <T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend();
263 unsafe { <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable() }; 280 unsafe { <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable() };
281 }
264 282
265 r.cr1().modify(|w| w.set_cen(true)); 283 fn init(&'static self, cs: CriticalSection) {
284 self.init_timer(cs);
285 regs_gp16().cr1().modify(|w| w.set_cen(true));
266 } 286 }
267 287
268 fn on_interrupt(&self) { 288 fn on_interrupt(&self) {
@@ -379,27 +399,26 @@ impl RtcDriver {
379 #[cfg(feature = "low-power")] 399 #[cfg(feature = "low-power")]
380 /// Stop the wakeup alarm, if enabled, and add the appropriate offset 400 /// Stop the wakeup alarm, if enabled, and add the appropriate offset
381 fn stop_wakeup_alarm(&self, cs: CriticalSection) { 401 fn stop_wakeup_alarm(&self, cs: CriticalSection) {
382 if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(cs) { 402 if let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) {
383 self.add_time(offset, cs); 403 self.add_time(offset, cs);
384 } 404 }
385 } 405 }
386 406
387 /* 407 /*
388 Low-power public functions: all create a critical section 408 Low-power public functions: all create or require a critical section
389 */ 409 */
390 #[cfg(feature = "low-power")] 410 #[cfg(feature = "low-power")]
391 /// Set the rtc but panic if it's already been set 411 pub(crate) fn set_min_stop_pause(&self, cs: CriticalSection, min_stop_pause: embassy_time::Duration) {
392 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { 412 self.min_stop_pause.borrow(cs).replace(min_stop_pause);
393 critical_section::with(|cs| {
394 rtc.stop_wakeup_alarm(cs);
395
396 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none())
397 });
398 } 413 }
399 414
400 #[cfg(feature = "low-power")] 415 #[cfg(feature = "low-power")]
401 /// The minimum pause time beyond which the executor will enter a low-power state. 416 /// Set the rtc but panic if it's already been set
402 pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250); 417 pub(crate) fn set_rtc(&self, cs: CriticalSection, mut rtc: Rtc) {
418 rtc.stop_wakeup_alarm(cs);
419
420 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none());
421 }
403 422
404 #[cfg(feature = "low-power")] 423 #[cfg(feature = "low-power")]
405 /// Pause the timer if ready; return err if not 424 /// Pause the timer if ready; return err if not
@@ -413,17 +432,25 @@ impl RtcDriver {
413 self.stop_wakeup_alarm(cs); 432 self.stop_wakeup_alarm(cs);
414 433
415 let time_until_next_alarm = self.time_until_next_alarm(cs); 434 let time_until_next_alarm = self.time_until_next_alarm(cs);
416 if time_until_next_alarm < Self::MIN_STOP_PAUSE { 435 if time_until_next_alarm < self.min_stop_pause.borrow(cs).get() {
436 trace!(
437 "time_until_next_alarm < self.min_stop_pause ({})",
438 time_until_next_alarm
439 );
417 Err(()) 440 Err(())
418 } else { 441 } else {
419 self.rtc 442 self.rtc
420 .borrow(cs) 443 .borrow(cs)
421 .get() 444 .borrow_mut()
445 .as_mut()
422 .unwrap() 446 .unwrap()
423 .start_wakeup_alarm(time_until_next_alarm, cs); 447 .start_wakeup_alarm(time_until_next_alarm, cs);
424 448
425 regs_gp16().cr1().modify(|w| w.set_cen(false)); 449 regs_gp16().cr1().modify(|w| w.set_cen(false));
426 450 // save the count for the timer as its lost in STOP2 for stm32wlex
451 #[cfg(stm32wlex)]
452 self.saved_count
453 .store(regs_gp16().cnt().read().cnt() as u16, Ordering::SeqCst);
427 Ok(()) 454 Ok(())
428 } 455 }
429 }) 456 })
@@ -431,18 +458,16 @@ impl RtcDriver {
431 458
432 #[cfg(feature = "low-power")] 459 #[cfg(feature = "low-power")]
433 /// Resume the timer with the given offset 460 /// Resume the timer with the given offset
434 pub(crate) fn resume_time(&self) { 461 pub(crate) fn resume_time(&self, cs: CriticalSection) {
435 if regs_gp16().cr1().read().cen() { 462 if regs_gp16().cr1().read().cen() {
436 // Time isn't currently stopped 463 // Time isn't currently stopped
437 464
438 return; 465 return;
439 } 466 }
440 467
441 critical_section::with(|cs| { 468 self.stop_wakeup_alarm(cs);
442 self.stop_wakeup_alarm(cs);
443 469
444 regs_gp16().cr1().modify(|w| w.set_cen(true)); 470 regs_gp16().cr1().modify(|w| w.set_cen(true));
445 })
446 } 471 }
447 472
448 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { 473 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
@@ -514,10 +539,15 @@ impl Driver for RtcDriver {
514} 539}
515 540
516#[cfg(feature = "low-power")] 541#[cfg(feature = "low-power")]
517pub(crate) fn get_driver() -> &'static RtcDriver { 542pub(crate) const fn get_driver() -> &'static RtcDriver {
518 &DRIVER 543 &DRIVER
519} 544}
520 545
521pub(crate) fn init(cs: CriticalSection) { 546pub(crate) fn init(cs: CriticalSection) {
522 DRIVER.init(cs) 547 DRIVER.init(cs)
523} 548}
549
550#[cfg(all(feature = "low-power", stm32wlex))]
551pub(crate) fn init_timer(cs: CriticalSection) {
552 DRIVER.init_timer(cs)
553}
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 75a83629c..9a56a41fb 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -2,7 +2,7 @@
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
5pub use stm32_metapac::timer::vals::{Ckd, Ossi, Ossr}; 5pub use stm32_metapac::timer::vals::{Ckd, Mms2, Ossi, Ossr};
6 6
7use super::low_level::{CountingMode, OutputPolarity, Timer}; 7use super::low_level::{CountingMode, OutputPolarity, Timer};
8use super::simple_pwm::PwmPin; 8use super::simple_pwm::PwmPin;
@@ -136,6 +136,16 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
136 self.inner.get_moe() 136 self.inner.get_moe()
137 } 137 }
138 138
139 /// Set Master Slave Mode 2
140 pub fn set_mms2(&mut self, mms2: Mms2) {
141 self.inner.set_mms2_selection(mms2);
142 }
143
144 /// Set Repetition Counter
145 pub fn set_repetition_counter(&mut self, val: u16) {
146 self.inner.set_repetition_counter(val);
147 }
148
139 /// Enable the given channel. 149 /// Enable the given channel.
140 pub fn enable(&mut self, channel: Channel) { 150 pub fn enable(&mut self, channel: Channel) {
141 self.inner.enable_channel(channel, true); 151 self.inner.enable_channel(channel, true);
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index ac039bb0d..0122fe4f7 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -10,7 +10,7 @@ use core::mem::ManuallyDrop;
10 10
11use embassy_hal_internal::Peri; 11use embassy_hal_internal::Peri;
12// Re-export useful enums 12// Re-export useful enums
13pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; 13pub use stm32_metapac::timer::vals::{FilterValue, Mms as MasterMode, Sms as SlaveMode, Ts as TriggerSource};
14 14
15use super::*; 15use super::*;
16use crate::pac::timer::vals; 16use crate::pac::timer::vals;
@@ -143,20 +143,69 @@ pub enum OutputCompareMode {
143 /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as 143 /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
144 /// TIMx_CNT>TIMx_CCRx else inactive. 144 /// TIMx_CNT>TIMx_CCRx else inactive.
145 PwmMode2, 145 PwmMode2,
146 // TODO: there's more modes here depending on the chip family. 146
147 #[cfg(timer_v2)]
148 /// In up-counting mode, the channel is active until a trigger
149 /// event is detected (on tim_trgi signal). Then, a comparison is performed as in PWM
150 /// mode 1 and the channels becomes active again at the next update. In down-counting
151 /// mode, the channel is inactive until a trigger event is detected (on tim_trgi signal).
152 /// Then, a comparison is performed as in PWM mode 1 and the channels becomes
153 /// inactive again at the next update.
154 OnePulseMode1,
155
156 #[cfg(timer_v2)]
157 /// In up-counting mode, the channel is inactive until a
158 /// trigger event is detected (on tim_trgi signal). Then, a comparison is performed as in
159 /// PWM mode 2 and the channels becomes inactive again at the next update. In down
160 /// counting mode, the channel is active until a trigger event is detected (on tim_trgi
161 /// signal). Then, a comparison is performed as in PWM mode 1 and the channels
162 /// becomes active again at the next update.
163 OnePulseMode2,
164
165 #[cfg(timer_v2)]
166 /// Combined PWM mode 1 - tim_oc1ref has the same behavior as in PWM mode 1.
167 /// tim_oc1refc is the logical OR between tim_oc1ref and tim_oc2ref.
168 CombinedPwmMode1,
169
170 #[cfg(timer_v2)]
171 /// Combined PWM mode 2 - tim_oc1ref has the same behavior as in PWM mode 2.
172 /// tim_oc1refc is the logical AND between tim_oc1ref and tim_oc2ref.
173 CombinedPwmMode2,
174
175 #[cfg(timer_v2)]
176 /// tim_oc1ref has the same behavior as in PWM mode 1. tim_oc1refc outputs tim_oc1ref
177 /// when the counter is counting up, tim_oc2ref when it is counting down.
178 AsymmetricPwmMode1,
179
180 #[cfg(timer_v2)]
181 /// tim_oc1ref has the same behavior as in PWM mode 2. tim_oc1refc outputs tim_oc1ref
182 /// when the counter is counting up, tim_oc2ref when it is counting down.
183 AsymmetricPwmMode2,
147} 184}
148 185
149impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { 186impl From<OutputCompareMode> for crate::pac::timer::vals::Ocm {
150 fn from(mode: OutputCompareMode) -> Self { 187 fn from(mode: OutputCompareMode) -> Self {
151 match mode { 188 match mode {
152 OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, 189 OutputCompareMode::Frozen => crate::pac::timer::vals::Ocm::FROZEN,
153 OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVE_ON_MATCH, 190 OutputCompareMode::ActiveOnMatch => crate::pac::timer::vals::Ocm::ACTIVE_ON_MATCH,
154 OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVE_ON_MATCH, 191 OutputCompareMode::InactiveOnMatch => crate::pac::timer::vals::Ocm::INACTIVE_ON_MATCH,
155 OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, 192 OutputCompareMode::Toggle => crate::pac::timer::vals::Ocm::TOGGLE,
156 OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCE_INACTIVE, 193 OutputCompareMode::ForceInactive => crate::pac::timer::vals::Ocm::FORCE_INACTIVE,
157 OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCE_ACTIVE, 194 OutputCompareMode::ForceActive => crate::pac::timer::vals::Ocm::FORCE_ACTIVE,
158 OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWM_MODE1, 195 OutputCompareMode::PwmMode1 => crate::pac::timer::vals::Ocm::PWM_MODE1,
159 OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWM_MODE2, 196 OutputCompareMode::PwmMode2 => crate::pac::timer::vals::Ocm::PWM_MODE2,
197 #[cfg(timer_v2)]
198 OutputCompareMode::OnePulseMode1 => crate::pac::timer::vals::Ocm::RETRIGERRABLE_OPM_MODE_1,
199 #[cfg(timer_v2)]
200 OutputCompareMode::OnePulseMode2 => crate::pac::timer::vals::Ocm::RETRIGERRABLE_OPM_MODE_2,
201 #[cfg(timer_v2)]
202 OutputCompareMode::CombinedPwmMode1 => crate::pac::timer::vals::Ocm::COMBINED_PWM_MODE_1,
203 #[cfg(timer_v2)]
204 OutputCompareMode::CombinedPwmMode2 => crate::pac::timer::vals::Ocm::COMBINED_PWM_MODE_2,
205 #[cfg(timer_v2)]
206 OutputCompareMode::AsymmetricPwmMode1 => crate::pac::timer::vals::Ocm::ASYMMETRIC_PWM_MODE_1,
207 #[cfg(timer_v2)]
208 OutputCompareMode::AsymmetricPwmMode2 => crate::pac::timer::vals::Ocm::ASYMMETRIC_PWM_MODE_2,
160 } 209 }
161 } 210 }
162} 211}
@@ -640,6 +689,11 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
640 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) 689 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
641 } 690 }
642 691
692 /// Set Timer Master Mode
693 pub fn set_master_mode(&self, mms: MasterMode) {
694 self.regs_gp16().cr2().modify(|w| w.set_mms(mms));
695 }
696
643 /// Set Timer Slave Mode 697 /// Set Timer Slave Mode
644 pub fn set_slave_mode(&self, sms: SlaveMode) { 698 pub fn set_slave_mode(&self, sms: SlaveMode) {
645 self.regs_gp16().smcr().modify(|r| r.set_sms(sms)); 699 self.regs_gp16().smcr().modify(|r| r.set_sms(sms));
@@ -760,6 +814,16 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
760 self.regs_advanced().cr2().modify(|w| w.set_oisn(channel.index(), val)); 814 self.regs_advanced().cr2().modify(|w| w.set_oisn(channel.index(), val));
761 } 815 }
762 816
817 /// Set master mode selection 2
818 pub fn set_mms2_selection(&self, mms2: vals::Mms2) {
819 self.regs_advanced().cr2().modify(|w| w.set_mms2(mms2));
820 }
821
822 /// Set repetition counter
823 pub fn set_repetition_counter(&self, val: u16) {
824 self.regs_advanced().rcr().modify(|w| w.set_rep(val));
825 }
826
763 /// Trigger software break 1 or 2 827 /// Trigger software break 1 or 2
764 /// Setting this bit generates a break event. This bit is automatically cleared by the hardware. 828 /// Setting this bit generates a break event. This bit is automatically cleared by the hardware.
765 pub fn trigger_software_break(&self, n: usize) { 829 pub fn trigger_software_break(&self, n: usize) {
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index b09bc7166..804d1ef37 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -399,7 +399,7 @@ pub struct UpdateInterruptHandler<T: CoreInstance> {
399impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> { 399impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
400 unsafe fn on_interrupt() { 400 unsafe fn on_interrupt() {
401 #[cfg(feature = "low-power")] 401 #[cfg(feature = "low-power")]
402 crate::low_power::on_wakeup_irq(); 402 crate::low_power::Executor::on_wakeup_irq();
403 403
404 let regs = crate::pac::timer::TimCore::from_ptr(T::regs()); 404 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
405 405
@@ -429,7 +429,7 @@ impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompare
429{ 429{
430 unsafe fn on_interrupt() { 430 unsafe fn on_interrupt() {
431 #[cfg(feature = "low-power")] 431 #[cfg(feature = "low-power")]
432 crate::low_power::on_wakeup_irq(); 432 crate::low_power::Executor::on_wakeup_irq();
433 433
434 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs()); 434 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
435 435
diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs
index 5e38532bd..2d3e2b972 100644
--- a/embassy-stm32/src/uid.rs
+++ b/embassy-stm32/src/uid.rs
@@ -1,8 +1,8 @@
1//! Unique ID (UID) 1//! Unique ID (UID)
2 2
3/// Get this device's unique 96-bit ID. 3/// Get this device's unique 96-bit ID.
4pub fn uid() -> &'static [u8; 12] { 4pub fn uid() -> [u8; 12] {
5 unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() } 5 unsafe { *crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() }
6} 6}
7 7
8/// Get this device's unique 96-bit ID, encoded into a string of 24 hexadecimal ASCII digits. 8/// Get this device's unique 96-bit ID, encoded into a string of 24 hexadecimal ASCII digits.
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index 20bfefd9e..bac570d27 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -7,7 +7,9 @@ use embassy_embedded_hal::SetConfig;
7use embedded_io_async::ReadReady; 7use embedded_io_async::ReadReady;
8use futures_util::future::{Either, select}; 8use futures_util::future::{Either, select};
9 9
10use super::{Config, ConfigError, Error, Info, State, UartRx, rdr, reconfigure, set_baudrate, sr}; 10use super::{
11 Config, ConfigError, Error, Info, State, UartRx, clear_interrupt_flags, rdr, reconfigure, set_baudrate, sr,
12};
11use crate::Peri; 13use crate::Peri;
12use crate::dma::ReadableRingBuffer; 14use crate::dma::ReadableRingBuffer;
13use crate::gpio::{AnyPin, SealedPin as _}; 15use crate::gpio::{AnyPin, SealedPin as _};
@@ -338,26 +340,16 @@ impl Drop for RingBufferedUartRx<'_> {
338/// For usart_v1 and usart_v2, all status flags must be handled together anyway because all flags 340/// For usart_v1 and usart_v2, all status flags must be handled together anyway because all flags
339/// are cleared by a single read to the RDR register. 341/// are cleared by a single read to the RDR register.
340fn check_idle_and_errors(r: Regs) -> Result<bool, Error> { 342fn check_idle_and_errors(r: Regs) -> Result<bool, Error> {
341 // Critical section is required so that the flags aren't set after read and before clear 343 // SAFETY: read only and we only use Rx related flags
342 let sr = critical_section::with(|_| { 344 let sr = sr(r).read();
343 // SAFETY: read only and we only use Rx related flags 345
344 let sr = sr(r).read(); 346 #[cfg(not(any(usart_v3, usart_v4)))]
345 347 unsafe {
346 #[cfg(any(usart_v3, usart_v4))] 348 // This read also clears the error and idle interrupt flags on v1 (TODO and v2?)
347 r.icr().write(|w| { 349 rdr(r).read_volatile()
348 w.set_idle(true); 350 };
349 w.set_pe(true); 351 clear_interrupt_flags(r, sr);
350 w.set_fe(true); 352
351 w.set_ne(true);
352 w.set_ore(true);
353 });
354 #[cfg(not(any(usart_v3, usart_v4)))]
355 unsafe {
356 // This read also clears the error and idle interrupt flags on v1 (TODO and v2?)
357 rdr(r).read_volatile()
358 };
359 sr
360 });
361 if sr.pe() { 353 if sr.pe() {
362 Err(Error::Parity) 354 Err(Error::Parity)
363 } else if sr.fe() { 355 } else if sr.fe() {
diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs
index b061306a0..43dd9c800 100644
--- a/embassy-stm32/src/vrefbuf/mod.rs
+++ b/embassy-stm32/src/vrefbuf/mod.rs
@@ -14,10 +14,10 @@ pub struct VoltageReferenceBuffer<'d, T: Instance> {
14#[cfg(rcc_wba)] 14#[cfg(rcc_wba)]
15fn get_refbuf_trim(voltage_scale: Vrs) -> usize { 15fn get_refbuf_trim(voltage_scale: Vrs) -> usize {
16 match voltage_scale { 16 match voltage_scale {
17 Vrs::VREF0 => 0x0BFA_07A8usize, 17 Vrs::VREF0 => 0x0BFA_07ABusize,
18 Vrs::VREF1 => 0x0BFA_07A9usize, 18 Vrs::VREF1 => 0x0BFA_07AAusize,
19 Vrs::VREF2 => 0x0BFA_07AAusize, 19 Vrs::VREF2 => 0x0BFA_07A9usize,
20 Vrs::VREF3 => 0x0BFA_07ABusize, 20 Vrs::VREF3 => 0x0BFA_07A8usize,
21 _ => panic!("Incorrect Vrs setting!"), 21 _ => panic!("Incorrect Vrs setting!"),
22 } 22 }
23} 23}
diff --git a/embassy-usb-logger/CHANGELOG.md b/embassy-usb-logger/CHANGELOG.md
index 4ea0e8871..3ba140b1f 100644
--- a/embassy-usb-logger/CHANGELOG.md
+++ b/embassy-usb-logger/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- Fixed panic in `UsbLogger` when usb is disconnected
12
11## 0.5.1 - 2025-08-26 13## 0.5.1 - 2025-08-26
12 14
13## 0.5.0 - 2025-07-22 15## 0.5.0 - 2025-07-22
diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs
index de25abce1..7c3c5e709 100644
--- a/embassy-usb-logger/src/lib.rs
+++ b/embassy-usb-logger/src/lib.rs
@@ -8,7 +8,7 @@ use core::future::Future;
8use embassy_futures::join::join; 8use embassy_futures::join::join;
9use embassy_sync::pipe::Pipe; 9use embassy_sync::pipe::Pipe;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State};
11use embassy_usb::driver::Driver; 11use embassy_usb::driver::{Driver, EndpointError};
12use embassy_usb::{Builder, Config}; 12use embassy_usb::{Builder, Config};
13use log::{Metadata, Record}; 13use log::{Metadata, Record};
14 14
@@ -133,17 +133,25 @@ impl<const N: usize, T: ReceiverHandler + Send + Sync> UsbLogger<N, T> {
133 sender.wait_connection().await; 133 sender.wait_connection().await;
134 loop { 134 loop {
135 let len = self.buffer.read(&mut rx[..]).await; 135 let len = self.buffer.read(&mut rx[..]).await;
136 let _ = sender.write_packet(&rx[..len]).await; 136 if Err(EndpointError::Disabled) == sender.write_packet(&rx[..len]).await
137 if len as u8 == MAX_PACKET_SIZE { 137 || len as u8 == MAX_PACKET_SIZE && Err(EndpointError::Disabled) == sender.write_packet(&[]).await
138 let _ = sender.write_packet(&[]).await; 138 {
139 } 139 sender.wait_connection().await;
140 };
140 } 141 }
141 }; 142 };
142 let reciever_fut = async { 143 let reciever_fut = async {
143 let mut reciever_buf: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize]; 144 let mut reciever_buf: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize];
144 receiver.wait_connection().await; 145 receiver.wait_connection().await;
145 loop { 146 loop {
146 let n = receiver.read_packet(&mut reciever_buf).await.unwrap(); 147 let n = match receiver.read_packet(&mut reciever_buf).await {
148 Err(EndpointError::Disabled) => {
149 receiver.wait_connection().await;
150 continue;
151 }
152 Err(_) => continue,
153 Ok(n) => n,
154 };
147 match &self.recieve_handler { 155 match &self.recieve_handler {
148 Some(handler) => { 156 Some(handler) => {
149 let data = &reciever_buf[..n]; 157 let data = &reciever_buf[..n];
diff --git a/examples/lpc55s69/src/bin/pwm.rs b/examples/lpc55s69/src/bin/pwm.rs
new file mode 100644
index 000000000..93b898b9d
--- /dev/null
+++ b/examples/lpc55s69/src/bin/pwm.rs
@@ -0,0 +1,18 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nxp::pwm::{Config, Pwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_halt as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nxp::init(Default::default());
13 let pwm = Pwm::new_output(p.PWM_OUTPUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000));
14 loop {
15 info!("Counter: {}", pwm.counter());
16 Timer::after_millis(50).await;
17 }
18}
diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs
new file mode 100644
index 000000000..5dd718eaf
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/i2c_target.rs
@@ -0,0 +1,63 @@
1//! Example of using async I2C target
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0G3507 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::i2c::Config;
11use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus};
12use embassy_mspm0::peripherals::I2C1;
13use embassy_mspm0::{bind_interrupts, i2c};
14use {defmt_rtt as _, panic_halt as _};
15
16bind_interrupts!(struct Irqs {
17 I2C1 => i2c::InterruptHandler<I2C1>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let p = embassy_mspm0::init(Default::default());
23
24 let instance = p.I2C1;
25 let scl = p.PB2;
26 let sda = p.PB3;
27
28 let config = Config::default();
29 let mut target_config = TargetConfig::default();
30 target_config.target_addr = 0x48;
31 target_config.general_call = true;
32 let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap();
33
34 let mut read = [0u8; 8];
35 let data = [8u8; 2];
36 let data_wr = [9u8; 2];
37
38 loop {
39 match i2c.listen(&mut read).await {
40 Ok(Command::GeneralCall(_)) => info!("General call received"),
41 Ok(Command::Read) => {
42 info!("Read command received");
43 match i2c.respond_to_read(&data).await.unwrap() {
44 ReadStatus::Done => info!("Finished reading"),
45 ReadStatus::NeedMoreBytes => {
46 info!("Read needs more bytes - will reset");
47 i2c.reset().unwrap();
48 }
49 ReadStatus::LeftoverBytes(_) => {
50 info!("Leftover bytes received");
51 i2c.flush_tx_fifo();
52 }
53 }
54 }
55 Ok(Command::Write(_)) => info!("Write command received"),
56 Ok(Command::WriteRead(_)) => {
57 info!("Write-Read command received");
58 i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap();
59 }
60 Err(e) => info!("Got error {}", e),
61 }
62 }
63}
diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs
new file mode 100644
index 000000000..4d147d08b
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c_target.rs
@@ -0,0 +1,63 @@
1//! Example of using async I2C target
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::i2c::Config;
11use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus};
12use embassy_mspm0::peripherals::I2C0;
13use embassy_mspm0::{bind_interrupts, i2c};
14use {defmt_rtt as _, panic_halt as _};
15
16bind_interrupts!(struct Irqs {
17 I2C0 => i2c::InterruptHandler<I2C0>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let p = embassy_mspm0::init(Default::default());
23
24 let instance = p.I2C0;
25 let scl = p.PA1;
26 let sda = p.PA0;
27
28 let config = Config::default();
29 let mut target_config = TargetConfig::default();
30 target_config.target_addr = 0x48;
31 target_config.general_call = true;
32 let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap();
33
34 let mut read = [0u8; 8];
35 let data = [8u8; 2];
36 let data_wr = [9u8; 2];
37
38 loop {
39 match i2c.listen(&mut read).await {
40 Ok(Command::GeneralCall(_)) => info!("General call received"),
41 Ok(Command::Read) => {
42 info!("Read command received");
43 match i2c.respond_to_read(&data).await.unwrap() {
44 ReadStatus::Done => info!("Finished reading"),
45 ReadStatus::NeedMoreBytes => {
46 info!("Read needs more bytes - will reset");
47 i2c.reset().unwrap();
48 }
49 ReadStatus::LeftoverBytes(_) => {
50 info!("Leftover bytes received");
51 i2c.flush_tx_fifo();
52 }
53 }
54 }
55 Ok(Command::Write(_)) => info!("Write command received"),
56 Ok(Command::WriteRead(_)) => {
57 info!("Write-Read command received");
58 i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap();
59 }
60 Err(e) => info!("Got error {}", e),
61 }
62 }
63}
diff --git a/examples/nrf52840/src/bin/egu.rs b/examples/nrf52840/src/bin/egu.rs
index 8bf712697..36eba8084 100644
--- a/examples/nrf52840/src/bin/egu.rs
+++ b/examples/nrf52840/src/bin/egu.rs
@@ -6,7 +6,7 @@
6 6
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::egu::{Egu, TriggerNumber}; 8use embassy_nrf::egu::{Egu, TriggerNumber};
9use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 9use embassy_nrf::gpio::{Level, OutputDrive, Pull};
10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; 10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity};
11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; 11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2};
12use embassy_nrf::ppi::Ppi; 12use embassy_nrf::ppi::Ppi;
@@ -17,12 +17,15 @@ use {defmt_rtt as _, panic_probe as _};
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
19 19
20 let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard);
21 let btn1 = Input::new(p.P0_11, Pull::Up);
22
23 let mut egu1 = Egu::new(p.EGU0); 20 let mut egu1 = Egu::new(p.EGU0);
24 let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle); 21 let led1 = OutputChannel::new(
25 let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi); 22 p.GPIOTE_CH0,
23 p.P0_13,
24 Level::High,
25 OutputDrive::Standard,
26 OutputChannelPolarity::Toggle,
27 );
28 let btn1 = InputChannel::new(p.GPIOTE_CH1, p.P0_11, Pull::Up, InputChannelPolarity::LoToHi);
26 29
27 let trigger0 = egu1.trigger(TriggerNumber::Trigger0); 30 let trigger0 = egu1.trigger(TriggerNumber::Trigger0);
28 let trigger1 = egu1.trigger(TriggerNumber::Trigger1); 31 let trigger1 = egu1.trigger(TriggerNumber::Trigger1);
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs
index dcfe7723a..c7ddc1d8d 100644
--- a/examples/nrf52840/src/bin/gpiote_channel.rs
+++ b/examples/nrf52840/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!"); 13 info!("Starting!");
14 14
15 let ch1 = InputChannel::new( 15 let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_11, Pull::Up), 17 let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_12, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_24, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_25, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs
index 66b429b09..a54659101 100644
--- a/examples/nrf52840/src/bin/i2s_monitor.rs
+++ b/examples/nrf52840/src/bin/i2s_monitor.rs
@@ -4,7 +4,7 @@
4use defmt::{debug, error, info}; 4use defmt::{debug, error, info};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth}; 6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth};
7use embassy_nrf::pwm::{Prescaler, SimplePwm}; 7use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
8use embassy_nrf::{bind_interrupts, peripherals}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) {
34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); 34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
35 35
36 // Configure the PWM to use the pins corresponding to the RGB leds 36 // Configure the PWM to use the pins corresponding to the RGB leds
37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); 37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default());
38 pwm.set_prescaler(Prescaler::Div1); 38 pwm.set_prescaler(Prescaler::Div1);
39 pwm.set_max_duty(255); 39 pwm.set_max_duty(255);
40 40
@@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) {
47 let rgb = rgb_from_rms(rms); 47 let rgb = rgb_from_rms(rms);
48 48
49 debug!("RMS: {}, RGB: {:?}", rms, rgb); 49 debug!("RMS: {}, RGB: {:?}", rms, rgb);
50 for i in 0..3 { 50 let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte)));
51 pwm.set_duty(i, rgb[i].into()); 51 pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]);
52 }
53 52
54 if let Err(err) = input_stream.receive().await { 53 if let Err(err) = input_stream.receive().await {
55 error!("{}", err); 54 error!("{}", err);
diff --git a/examples/nrf52840/src/bin/ppi.rs b/examples/nrf52840/src/bin/ppi.rs
index 129ad06e7..177f6a06d 100644
--- a/examples/nrf52840/src/bin/ppi.rs
+++ b/examples/nrf52840/src/bin/ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::info; 6use defmt::info;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 8use embassy_nrf::gpio::{Level, OutputDrive, Pull};
9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use gpiote::{OutputChannel, OutputChannelPolarity}; 11use gpiote::{OutputChannel, OutputChannelPolarity};
@@ -16,36 +16,24 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_nrf::init(Default::default()); 16 let p = embassy_nrf::init(Default::default());
17 info!("Starting!"); 17 info!("Starting!");
18 18
19 let button1 = InputChannel::new( 19 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
20 p.GPIOTE_CH0, 20 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
21 Input::new(p.P0_11, Pull::Up), 21 let button3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::HiToLo);
22 InputChannelPolarity::HiToLo, 22 let button4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::HiToLo);
23 );
24 let button2 = InputChannel::new(
25 p.GPIOTE_CH1,
26 Input::new(p.P0_12, Pull::Up),
27 InputChannelPolarity::HiToLo,
28 );
29 let button3 = InputChannel::new(
30 p.GPIOTE_CH2,
31 Input::new(p.P0_24, Pull::Up),
32 InputChannelPolarity::HiToLo,
33 );
34 let button4 = InputChannel::new(
35 p.GPIOTE_CH3,
36 Input::new(p.P0_25, Pull::Up),
37 InputChannelPolarity::HiToLo,
38 );
39 23
40 let led1 = OutputChannel::new( 24 let led1 = OutputChannel::new(
41 p.GPIOTE_CH4, 25 p.GPIOTE_CH4,
42 Output::new(p.P0_13, Level::Low, OutputDrive::Standard), 26 p.P0_13,
27 Level::Low,
28 OutputDrive::Standard,
43 OutputChannelPolarity::Toggle, 29 OutputChannelPolarity::Toggle,
44 ); 30 );
45 31
46 let led2 = OutputChannel::new( 32 let led2 = OutputChannel::new(
47 p.GPIOTE_CH5, 33 p.GPIOTE_CH5,
48 Output::new(p.P0_14, Level::Low, OutputDrive::Standard), 34 p.P0_14,
35 Level::Low,
36 OutputDrive::Standard,
49 OutputChannelPolarity::Toggle, 37 OutputChannelPolarity::Toggle,
50 ); 38 );
51 39
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs
index a5bb1347a..02f9b4191 100644
--- a/examples/nrf52840/src/bin/pwm.rs
+++ b/examples/nrf52840/src/bin/pwm.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [
71#[embassy_executor::main] 71#[embassy_executor::main]
72async fn main(_spawner: Spawner) { 72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default()); 73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); 74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1); 75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767); 76 pwm.set_max_duty(32767);
77 info!("pwm initialized!"); 77 info!("pwm initialized!");
@@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) {
79 let mut i = 0; 79 let mut i = 0;
80 loop { 80 loop {
81 i += 1; 81 i += 1;
82 pwm.set_duty(0, DUTY[i % 1024]); 82 pwm.set_all_duties([
83 pwm.set_duty(1, DUTY[(i + 256) % 1024]); 83 DutyCycle::normal(DUTY[i % 1024]),
84 pwm.set_duty(2, DUTY[(i + 512) % 1024]); 84 DutyCycle::normal(DUTY[(i + 256) % 1024]),
85 pwm.set_duty(3, DUTY[(i + 768) % 1024]); 85 DutyCycle::normal(DUTY[(i + 512) % 1024]),
86 DutyCycle::normal(DUTY[(i + 768) % 1024]),
87 ]);
86 Timer::after_millis(3).await; 88 Timer::after_millis(3).await;
87 } 89 }
88} 90}
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
index 60ea712b5..fff7decb2 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Pull}; 8use embassy_nrf::gpio::Pull;
9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; 11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer};
@@ -30,17 +30,9 @@ async fn main(_spawner: Spawner) {
30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
31 // so its going to have to start running in order load the configuration 31 // so its going to have to start running in order load the configuration
32 32
33 let button1 = InputChannel::new( 33 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
34 p.GPIOTE_CH0,
35 Input::new(p.P0_11, Pull::Up),
36 InputChannelPolarity::HiToLo,
37 );
38 34
39 let button2 = InputChannel::new( 35 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
40 p.GPIOTE_CH1,
41 Input::new(p.P0_12, Pull::Up),
42 InputChannelPolarity::HiToLo,
43 );
44 36
45 // messing with the pwm tasks is ill advised 37 // messing with the pwm tasks is ill advised
46 // Times::Ininite and Times even are seq0, Times odd is seq1 38 // Times::Ininite and Times even are seq0, Times odd is seq1
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs
index d772d2f5d..93cb984e6 100644
--- a/examples/nrf52840/src/bin/pwm_servo.rs
+++ b/examples/nrf52840/src/bin/pwm_servo.rs
@@ -3,14 +3,14 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); 13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default());
14 // sg90 microervo requires 50hz or 20ms period 14 // sg90 microervo requires 50hz or 20ms period
15 // set_period can only set down to 125khz so we cant use it directly 15 // set_period can only set down to 125khz so we cant use it directly
16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top 16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top
@@ -24,23 +24,23 @@ async fn main(_spawner: Spawner) {
24 loop { 24 loop {
25 info!("45 deg"); 25 info!("45 deg");
26 // poor mans inverting, subtract our value from max_duty 26 // poor mans inverting, subtract our value from max_duty
27 pwm.set_duty(0, 2500 - 156); 27 pwm.set_duty(0, DutyCycle::normal(2500 - 156));
28 Timer::after_millis(5000).await; 28 Timer::after_millis(5000).await;
29 29
30 info!("90 deg"); 30 info!("90 deg");
31 pwm.set_duty(0, 2500 - 187); 31 pwm.set_duty(0, DutyCycle::normal(2500 - 187));
32 Timer::after_millis(5000).await; 32 Timer::after_millis(5000).await;
33 33
34 info!("135 deg"); 34 info!("135 deg");
35 pwm.set_duty(0, 2500 - 218); 35 pwm.set_duty(0, DutyCycle::normal(2500 - 218));
36 Timer::after_millis(5000).await; 36 Timer::after_millis(5000).await;
37 37
38 info!("180 deg"); 38 info!("180 deg");
39 pwm.set_duty(0, 2500 - 250); 39 pwm.set_duty(0, DutyCycle::normal(2500 - 250));
40 Timer::after_millis(5000).await; 40 Timer::after_millis(5000).await;
41 41
42 info!("0 deg"); 42 info!("0 deg");
43 pwm.set_duty(0, 2500 - 125); 43 pwm.set_duty(0, DutyCycle::normal(2500 - 125));
44 Timer::after_millis(5000).await; 44 Timer::after_millis(5000).await;
45 } 45 }
46} 46}
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
index 07752ffc4..2f9c06b56 100644
--- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs
+++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
@@ -27,14 +27,12 @@ bind_interrupts!(struct Irqs {
27async fn wifi_task( 27async fn wifi_task(
28 runner: hosted::Runner< 28 runner: hosted::Runner<
29 'static, 29 'static,
30 ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, 30 hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>,
31 Input<'static>,
32 Output<'static>, 31 Output<'static>,
33 >, 32 >,
34) -> ! { 33) -> ! {
35 runner.run().await 34 runner.run().await
36} 35}
37
38#[embassy_executor::task] 36#[embassy_executor::task]
39async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { 37async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! {
40 runner.run().await 38 runner.run().await
@@ -60,15 +58,11 @@ async fn main(spawner: Spawner) {
60 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); 58 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
61 let spi = ExclusiveDevice::new(spi, cs, Delay); 59 let spi = ExclusiveDevice::new(spi, cs, Delay);
62 60
61 let iface = hosted::SpiInterface::new(spi, handshake, ready);
62
63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); 63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
64 let (device, mut control, runner) = embassy_net_esp_hosted::new( 64 let (device, mut control, runner) =
65 ESP_STATE.init(embassy_net_esp_hosted::State::new()), 65 embassy_net_esp_hosted::new(ESP_STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await;
66 spi,
67 handshake,
68 ready,
69 reset,
70 )
71 .await;
72 66
73 spawner.spawn(unwrap!(wifi_task(runner))); 67 spawner.spawn(unwrap!(wifi_task(runner)));
74 68
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs
index 23f6fca98..a085310ce 100644
--- a/examples/nrf5340/src/bin/gpiote_channel.rs
+++ b/examples/nrf5340/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!"); 13 info!("Starting!");
14 14
15 let ch1 = InputChannel::new( 15 let ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_23, Pull::Up), 17 let ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_24, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_08, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_09, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index a053dd0ec..4ef77279f 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -6,9 +6,15 @@ license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
16
17rand = { version = "0.9.0", default-features = false }
12 18
13defmt = "1.0.1" 19defmt = "1.0.1"
14defmt-rtt = "1.0.0" 20defmt-rtt = "1.0.0"
@@ -18,6 +24,9 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
18cortex-m-rt = "0.7.0" 24cortex-m-rt = "0.7.0"
19 25
20embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
27portable-atomic = "1"
28
29static_cell = "2"
21 30
22[profile.release] 31[profile.release]
23debug = 2 32debug = 2
diff --git a/examples/nrf54l15/src/bin/buffered_uart.rs b/examples/nrf54l15/src/bin/buffered_uart.rs
new file mode 100644
index 000000000..41fa1ca4e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/buffered_uart.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::buffered_uarte::{self, BufferedUarte};
7use embassy_nrf::{bind_interrupts, peripherals, uarte};
8use embedded_io_async::Write;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SERIAL20 => buffered_uarte::InterruptHandler<peripherals::SERIAL20>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD115200;
21
22 let mut tx_buffer = [0u8; 4096];
23 let mut rx_buffer = [0u8; 4096];
24
25 let mut u = BufferedUarte::new(
26 p.SERIAL20,
27 p.P1_12,
28 p.P1_13,
29 Irqs,
30 config,
31 &mut rx_buffer,
32 &mut tx_buffer,
33 );
34
35 info!("uarte initialized!");
36
37 unwrap!(u.write_all(b"Hello!\r\n").await);
38 info!("wrote hello in uart!");
39
40 loop {
41 info!("reading...");
42 let buf = unwrap!(u.fill_buf().await);
43 info!("read done, got {}", buf);
44
45 // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again
46 let n = buf.len();
47 u.consume(n);
48 }
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs
new file mode 100644
index 000000000..6333250ba
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_channel.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!");
14
15 let ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo);
16 let ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi);
17 let ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle);
18 let ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle);
19
20 let button1 = async {
21 loop {
22 ch1.wait().await;
23 info!("Button 1 pressed")
24 }
25 };
26
27 let button2 = async {
28 loop {
29 ch2.wait().await;
30 info!("Button 2 released")
31 }
32 };
33
34 let button3 = async {
35 loop {
36 ch3.wait().await;
37 info!("Button 3 toggled")
38 }
39 };
40
41 let button4 = async {
42 loop {
43 ch4.wait().await;
44 info!("Button 4 toggled")
45 }
46 };
47
48 embassy_futures::join::join4(button1, button2, button3, button4).await;
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_port.rs b/examples/nrf54l15/src/bin/gpiote_port.rs
new file mode 100644
index 000000000..620cb2435
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_port.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task(pool_size = 4)]
10async fn button_task(n: usize, mut pin: Input<'static>) {
11 loop {
12 pin.wait_for_low().await;
13 info!("Button {:?} pressed!", n);
14 pin.wait_for_high().await;
15 info!("Button {:?} released!", n);
16 }
17}
18
19#[embassy_executor::main]
20async fn main(spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default());
22 info!("Starting!");
23
24 let btn1 = Input::new(p.P1_13, Pull::Up);
25 let btn2 = Input::new(p.P1_09, Pull::Up);
26 let btn3 = Input::new(p.P1_08, Pull::Up);
27 let btn4 = Input::new(p.P0_04, Pull::Up);
28
29 spawner.spawn(unwrap!(button_task(1, btn1)));
30 spawner.spawn(unwrap!(button_task(2, btn2)));
31 spawner.spawn(unwrap!(button_task(3, btn3)));
32 spawner.spawn(unwrap!(button_task(4, btn4)));
33}
diff --git a/examples/nrf54l15/src/bin/pwm.rs b/examples/nrf54l15/src/bin/pwm.rs
new file mode 100644
index 000000000..b438978f1
--- /dev/null
+++ b/examples/nrf54l15/src/bin/pwm.rs
@@ -0,0 +1,86 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='')
11static DUTY: [u16; 1024] = [
12 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, 9526, 9613, 9700,
13 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, 10766, 10857, 10948, 11039, 11131, 11223,
14 11315, 11407, 11500, 11592, 11685, 11779, 11872, 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723,
15 12818, 12914, 13010, 13106, 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266,
16 14364, 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, 15730, 15828,
17 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, 16995, 17091, 17188, 17284, 17380,
18 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896,
19 18989, 19082, 19174, 19266, 19358, 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346,
20 20434, 20521, 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, 21701,
21 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, 22714, 22788, 22861, 22934,
22 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, 23631, 23698, 23763, 23828, 23892, 23956, 24019,
23 24081, 24143, 24204, 24264, 24324, 24383, 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933,
24 24983, 25034, 25083, 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655,
25 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, 26117, 26144, 26170,
26 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, 26397, 26413, 26427, 26441, 26454, 26466,
27 26477, 26487, 26496, 26505, 26512, 26519, 26525, 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537,
28 26534, 26530, 26525, 26519, 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381,
29 26364, 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, 26032, 26002,
30 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, 25575, 25535, 25493, 25451, 25407,
31 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611,
32 24555, 24499, 24441, 24383, 24324, 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631,
33 23564, 23497, 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, 22488,
34 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, 21456, 21373, 21290, 21206,
35 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, 20346, 20258, 20169, 20081, 19991, 19902, 19812,
36 19722, 19631, 19540, 19449, 19358, 19266, 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334,
37 18239, 18145, 18050, 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801,
38 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, 15437, 15339, 15242,
39 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, 14169, 14072, 13975, 13878, 13781, 13684,
40 13587, 13491, 13394, 13298, 13202, 13106, 13010, 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154,
41 12060, 11966, 11872, 11779, 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675,
42 10585, 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, 9184, 9099,
43 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, 7873, 7794, 7716, 7638, 7561,
44 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172,
45 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947,
46 4888, 4828, 4769, 4711, 4653, 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892,
47 3841, 3791, 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, 3005,
48 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, 2382, 2347, 2312, 2278,
49 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, 1867, 1838, 1810, 1781, 1754, 1726, 1699,
50 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252,
51 1232, 1212, 1192, 1173, 1154, 1135, 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903,
52 888, 874, 860, 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, 627,
53 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, 479, 473, 467, 461, 455,
54 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, 386, 383, 379, 376, 373, 370, 367, 364, 361,
55 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328,
56 327, 327, 327, 327, 327, 328, 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347,
57 349, 351, 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, 419, 424,
58 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, 534, 541, 549, 557, 565, 574,
59 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, 710, 721, 733, 744, 756, 768, 781, 793, 806, 819,
60 833, 846, 860, 874, 888, 903, 918, 933, 948, 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154,
61 1173, 1192, 1212, 1232, 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570,
62 1595, 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, 2080, 2112,
63 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, 2641, 2680, 2719, 2758, 2798,
64 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642,
65 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653,
66 4711, 4769, 4828, 4888, 4947, 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834,
67 5901, 5968, 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, 7180,
68 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111,
69];
70
71#[embassy_executor::main]
72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_2ch(p.PWM20, p.P1_10, p.P1_14, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767);
77 info!("pwm initialized!");
78
79 let mut i = 0;
80 loop {
81 i += 1;
82 pwm.set_duty(0, DutyCycle::normal(DUTY[i % 1024]));
83 pwm.set_duty(1, DutyCycle::normal(DUTY[(i + 512) % 1024]));
84 Timer::after_millis(3).await;
85 }
86}
diff --git a/examples/nrf54l15/src/bin/rng.rs b/examples/nrf54l15/src/bin/rng.rs
new file mode 100644
index 000000000..b2d7f906b
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rng.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::cracen::Cracen;
6use rand::Rng as _;
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_nrf::init(Default::default());
12 let mut rng = Cracen::new_blocking(p.CRACEN);
13
14 // Async API
15 let mut bytes = [0; 4];
16 rng.blocking_fill_bytes(&mut bytes);
17 defmt::info!("Some random bytes: {:?}", bytes);
18
19 // Sync API with `rand`
20 defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10));
21
22 let mut bytes = [0; 1024];
23 rng.blocking_fill_bytes(&mut bytes);
24 let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros());
25 let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones());
26 defmt::info!("Chance of zero: {}%", zero_count * 100 / (bytes.len() as u32 * 8));
27 defmt::info!("Chance of one: {}%", one_count * 100 / (bytes.len() as u32 * 8));
28}
diff --git a/examples/nrf54l15/src/bin/rtc.rs b/examples/nrf54l15/src/bin/rtc.rs
new file mode 100644
index 000000000..a45aaca52
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rtc.rs
@@ -0,0 +1,56 @@
1#![no_std]
2#![no_main]
3
4use core::cell::RefCell;
5
6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_nrf::interrupt;
9use embassy_nrf::rtc::Rtc;
10use embassy_sync::blocking_mutex::Mutex;
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
12use portable_atomic::AtomicU64;
13use {defmt_rtt as _, panic_probe as _};
14
15// 64 bit counter which will never overflow.
16static TICK_COUNTER: AtomicU64 = AtomicU64::new(0);
17static RTC: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc<'static>>>> = Mutex::new(RefCell::new(None));
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 defmt::println!("nRF54L15 RTC example");
22 let p = embassy_nrf::init(Default::default());
23 let mut led = Output::new(p.P2_09, Level::High, OutputDrive::Standard);
24 // Counter resolution is 125 ms.
25 let mut rtc = Rtc::new(p.RTC10, (1 << 12) - 1).unwrap();
26 rtc.enable_interrupt(embassy_nrf::rtc::Interrupt::Tick, true);
27 rtc.enable_event(embassy_nrf::rtc::Interrupt::Tick);
28 rtc.enable();
29 RTC.lock(|r| {
30 let mut rtc_borrow = r.borrow_mut();
31 *rtc_borrow = Some(rtc);
32 });
33
34 let mut last_counter_val = 0;
35 loop {
36 let current = TICK_COUNTER.load(core::sync::atomic::Ordering::Relaxed);
37 if current != last_counter_val {
38 led.toggle();
39 last_counter_val = current;
40 }
41 }
42}
43
44#[interrupt]
45fn RTC10() {
46 // For 64-bit, we do not need to worry about overflowing, at least not for realistic program
47 // lifetimes.
48 TICK_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
49 RTC.lock(|r| {
50 let mut rtc_borrow = r.borrow_mut();
51 rtc_borrow
52 .as_mut()
53 .unwrap()
54 .reset_event(embassy_nrf::rtc::Interrupt::Tick);
55 });
56}
diff --git a/examples/nrf54l15/src/bin/saadc.rs b/examples/nrf54l15/src/bin/saadc.rs
new file mode 100644
index 000000000..567177894
--- /dev/null
+++ b/examples/nrf54l15/src/bin/saadc.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
7use embassy_nrf::{bind_interrupts, saadc};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SAADC => saadc::InterruptHandler;
13});
14
15#[embassy_executor::main]
16async fn main(_p: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let config = Config::default();
19 let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow());
20 let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
21
22 loop {
23 let mut buf = [0; 1];
24 saadc.sample(&mut buf).await;
25 info!("sample: {=i16}", &buf[0]);
26 Timer::after_millis(100).await;
27 }
28}
diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs
new file mode 100644
index 000000000..3f5980647
--- /dev/null
+++ b/examples/nrf54l15/src/bin/spim.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::{bind_interrupts, peripherals, spim};
6use {defmt_rtt as _, panic_probe as _};
7
8bind_interrupts!(struct Irqs {
9 SERIAL00 => spim::InterruptHandler<peripherals::SERIAL00>;
10});
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default());
15 let mut config = spim::Config::default();
16 config.frequency = spim::Frequency::M32;
17 let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone());
18 let data = [
19 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
20 ];
21 let mut buf = [0u8; 16];
22
23 buf.fill(0);
24 spim.blocking_transfer(&mut buf, &data).unwrap();
25 assert_eq!(data, buf);
26
27 buf.fill(0);
28 spim.transfer(&mut buf, &data).await.unwrap();
29 assert_eq!(data, buf);
30}
diff --git a/examples/nrf54l15/src/bin/twim.rs b/examples/nrf54l15/src/bin/twim.rs
new file mode 100644
index 000000000..53b85034e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twim.rs
@@ -0,0 +1,37 @@
1//! Example on how to read a 24C/24LC i2c eeprom.
2//!
3//! Connect SDA to P0.03, SCL to P0.04
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_nrf::twim::{self, Twim};
11use embassy_nrf::{bind_interrupts, peripherals};
12use static_cell::ConstStaticCell;
13use {defmt_rtt as _, panic_probe as _};
14
15const ADDRESS: u8 = 0x18;
16const WHOAMI: u8 = 0x0F;
17
18bind_interrupts!(struct Irqs {
19 SERIAL20 => twim::InterruptHandler<peripherals::SERIAL20>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default());
25 info!("Initializing TWI...");
26 let config = twim::Config::default();
27 static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
28 let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take());
29
30 info!("Reading...");
31
32 let mut data = [0u8; 1];
33 match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await {
34 Ok(()) => info!("Whoami: {}", data[0]),
35 Err(e) => error!("I2c Error: {:?}", e),
36 }
37}
diff --git a/examples/nrf54l15/src/bin/twis.rs b/examples/nrf54l15/src/bin/twis.rs
new file mode 100644
index 000000000..34c04aee3
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twis.rs
@@ -0,0 +1,47 @@
1//! TWIS example
2
3#![no_std]
4#![no_main]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_nrf::twis::{self, Command, Twis};
9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 SERIAL20 => twis::InterruptHandler<peripherals::SERIAL20>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default());
19
20 let mut config = twis::Config::default();
21 config.address0 = 0x55; // Set i2c address
22 let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config);
23
24 info!("Listening...");
25 loop {
26 let response = [1, 2, 3, 4, 5, 6, 7, 8];
27 // This buffer is used if the i2c master performs a Write or WriteRead
28 let mut buf = [0u8; 16];
29 match i2c.listen(&mut buf).await {
30 Ok(Command::Read) => {
31 info!("Got READ command. Respond with data:\n{:?}\n", response);
32 if let Err(e) = i2c.respond_to_read(&response).await {
33 error!("{:?}", e);
34 }
35 }
36 Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]),
37 Ok(Command::WriteRead(n)) => {
38 info!("Got WRITE/READ command with data:\n{:?}", buf[..n]);
39 info!("Respond with data:\n{:?}\n", response);
40 if let Err(e) = i2c.respond_to_read(&response).await {
41 error!("{:?}", e);
42 }
43 }
44 Err(e) => error!("{:?}", e),
45 }
46 }
47}
diff --git a/examples/nrf54l15/src/bin/uart.rs b/examples/nrf54l15/src/bin/uart.rs
new file mode 100644
index 000000000..cc6528a6f
--- /dev/null
+++ b/examples/nrf54l15/src/bin/uart.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::{bind_interrupts, peripherals, uarte};
7use {defmt_rtt as _, panic_probe as _};
8
9bind_interrupts!(struct Irqs {
10 SERIAL20 => uarte::InterruptHandler<peripherals::SERIAL20>;
11});
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16 let mut config = uarte::Config::default();
17 config.parity = uarte::Parity::EXCLUDED;
18 config.baudrate = uarte::Baudrate::BAUD115200;
19
20 let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config);
21
22 info!("uarte initialized!");
23
24 // Message must be in SRAM
25 let mut buf = [0; 8];
26 buf.copy_from_slice(b"Hello!\r\n");
27
28 unwrap!(uart.write(&buf).await);
29 info!("wrote hello in uart!");
30
31 loop {
32 info!("reading...");
33 unwrap!(uart.read(&mut buf).await);
34 info!("writing...");
35 unwrap!(uart.write(&buf).await);
36 }
37}
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp/src/bin/pio_onewire.rs
+++ b/examples/rp/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp235x/src/bin/pio_onewire.rs
+++ b/examples/rp235x/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp235x/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs
index feb27f6d9..5ff705ca2 100644
--- a/examples/stm32c0/src/bin/rtc.rs
+++ b/examples/stm32c0/src/bin/rtc.rs
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs
index c24f01753..f8da91336 100644
--- a/examples/stm32f4/src/bin/adc_dma.rs
+++ b/examples/stm32f4/src/bin/adc_dma.rs
@@ -4,7 +4,7 @@ use cortex_m::singleton;
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Peripherals; 6use embassy_stm32::Peripherals;
7use embassy_stm32::adc::{Adc, RingBufferedAdc, SampleTime, Sequence}; 7use embassy_stm32::adc::{Adc, AdcChannel, RingBufferedAdc, SampleTime};
8use embassy_time::Instant; 8use embassy_time::Instant;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -15,7 +15,7 @@ async fn main(spawner: Spawner) {
15} 15}
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn adc_task(mut p: Peripherals) { 18async fn adc_task(p: Peripherals) {
19 const ADC_BUF_SIZE: usize = 1024; 19 const ADC_BUF_SIZE: usize = 1024;
20 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); 20 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
21 let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); 21 let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
@@ -23,13 +23,24 @@ async fn adc_task(mut p: Peripherals) {
23 let adc = Adc::new(p.ADC1); 23 let adc = Adc::new(p.ADC1);
24 let adc2 = Adc::new(p.ADC2); 24 let adc2 = Adc::new(p.ADC2);
25 25
26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data); 26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(
27 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(p.DMA2_CH2, adc_data2); 27 p.DMA2_CH0,
28 28 adc_data,
29 adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112); 29 [
30 adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112); 30 (&mut p.PA0.degrade_adc(), SampleTime::CYCLES112),
31 adc2.set_sample_sequence(Sequence::One, &mut p.PA1, SampleTime::CYCLES112); 31 (&mut p.PA2.degrade_adc(), SampleTime::CYCLES112),
32 adc2.set_sample_sequence(Sequence::Two, &mut p.PA3, SampleTime::CYCLES112); 32 ]
33 .into_iter(),
34 );
35 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(
36 p.DMA2_CH2,
37 adc_data2,
38 [
39 (&mut p.PA1.degrade_adc(), SampleTime::CYCLES112),
40 (&mut p.PA3.degrade_adc(), SampleTime::CYCLES112),
41 ]
42 .into_iter(),
43 );
33 44
34 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around 45 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around
35 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of 46 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs
index cccf20949..0adcda614 100644
--- a/examples/stm32f4/src/bin/eth_w5500.rs
+++ b/examples/stm32f4/src/bin/eth_w5500.rs
@@ -12,6 +12,7 @@ use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::mode::Async; 12use embassy_stm32::mode::Async;
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::spi::mode::Master;
15use embassy_stm32::time::Hertz; 16use embassy_stm32::time::Hertz;
16use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi}; 17use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi};
17use embassy_time::{Delay, Timer}; 18use embassy_time::{Delay, Timer};
@@ -24,7 +25,7 @@ bind_interrupts!(struct Irqs {
24 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
25}); 26});
26 27
27type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; 28type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>;
28#[embassy_executor::task] 29#[embassy_executor::task]
29async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { 30async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! {
30 runner.run().await 31 runner.run().await
diff --git a/examples/stm32f4/src/bin/i2c_slave_async.rs b/examples/stm32f4/src/bin/i2c_slave_async.rs
new file mode 100644
index 000000000..5065bcdd8
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_async.rs
@@ -0,0 +1,135 @@
1//! I2C slave example using async operations with DMA
2//!
3//! This example demonstrates DMA-accelerated I2C slave operations,
4//! which provide better performance and lower CPU overhead for
5//! high-frequency I2C transactions.
6
7#![no_std]
8#![no_main]
9
10use defmt::{error, info};
11use embassy_executor::Spawner;
12use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, peripherals};
15use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
16use embassy_sync::mutex::Mutex;
17use embassy_time::{Duration, Timer};
18use {defmt_rtt as _, panic_probe as _};
19
20pub const I2C_SLAVE_ADDR: u8 = 0x42;
21pub const BUFFER_SIZE: usize = 8;
22static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
23
24bind_interrupts!(struct Irqs {
25 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
26 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
27});
28
29#[embassy_executor::main]
30async fn main(spawner: Spawner) {
31 let p = embassy_stm32::init(Default::default());
32
33 // Configure I2C
34 let mut i2c_config = i2c::Config::default();
35 i2c_config.sda_pullup = false;
36 i2c_config.scl_pullup = false;
37 i2c_config.frequency = Hertz(100_000); // 100kHz I2C speed
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 Irqs, p.DMA1_CH6, // TX DMA
44 p.DMA1_CH0, // RX DMA
45 i2c_config,
46 );
47
48 // Convert to MultiMaster mode
49 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
50 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
51
52 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
53}
54
55#[embassy_executor::task]
56pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Async, i2c::mode::MultiMaster>) {
57 info!("Async I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
58
59 loop {
60 match i2c_slave.listen().await {
61 Ok(SlaveCommand {
62 kind: SlaveCommandKind::Write,
63 address,
64 }) => {
65 let addr_val = match address {
66 Address::SevenBit(addr) => addr,
67 Address::TenBit(addr) => (addr & 0xFF) as u8,
68 };
69
70 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
71
72 let mut data_buffer = I2C_BUFFER.lock().await;
73
74 match i2c_slave.respond_to_write(&mut *data_buffer).await {
75 Ok(_) => {
76 info!(
77 "I2C: Data received - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
78 data_buffer[0],
79 data_buffer[1],
80 data_buffer[2],
81 data_buffer[3],
82 data_buffer[4],
83 data_buffer[5],
84 data_buffer[6],
85 data_buffer[7]
86 );
87 }
88 Err(e) => {
89 error!("I2C: Write error: {}", format_i2c_error(&e));
90 }
91 }
92 }
93
94 Ok(SlaveCommand {
95 kind: SlaveCommandKind::Read,
96 address,
97 }) => {
98 let addr_val = match address {
99 Address::SevenBit(addr) => addr,
100 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
101 };
102
103 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
104
105 let data_buffer = I2C_BUFFER.lock().await;
106
107 match i2c_slave.respond_to_read(&data_buffer[..BUFFER_SIZE]).await {
108 Ok(_) => {
109 info!("I2C: Responded to read command");
110 }
111 Err(e) => {
112 error!("I2C: Read error: {}", format_i2c_error(&e));
113 }
114 }
115 }
116
117 Err(e) => {
118 error!("I2C: Listen error: {}", format_i2c_error(&e));
119 Timer::after(Duration::from_millis(100)).await;
120 }
121 }
122 }
123}
124
125fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
126 match e {
127 embassy_stm32::i2c::Error::Bus => "Bus",
128 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
129 embassy_stm32::i2c::Error::Nack => "Nack",
130 embassy_stm32::i2c::Error::Timeout => "Timeout",
131 embassy_stm32::i2c::Error::Crc => "Crc",
132 embassy_stm32::i2c::Error::Overrun => "Overrun",
133 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
134 }
135}
diff --git a/examples/stm32f4/src/bin/i2c_slave_blocking.rs b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
new file mode 100644
index 000000000..ee06d4ac4
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
@@ -0,0 +1,132 @@
1//! Complete I2C slave example using blocking operations
2//!
3//! This example shows how to set up an STM32F4 as an I2C slave device
4//! that can handle both read and write transactions from master devices.
5
6#![no_std]
7#![no_main]
8
9use defmt::{error, info};
10use embassy_executor::Spawner;
11use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
12use embassy_stm32::time::Hertz;
13use embassy_stm32::{bind_interrupts, peripherals};
14use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
15use embassy_sync::mutex::Mutex;
16use embassy_time::{Duration, Timer};
17use {defmt_rtt as _, panic_probe as _};
18
19pub const I2C_SLAVE_ADDR: u8 = 0x42;
20pub const BUFFER_SIZE: usize = 8;
21static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
22
23bind_interrupts!(struct Irqs {
24 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
25 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
26});
27
28#[embassy_executor::main]
29async fn main(spawner: Spawner) {
30 let p = embassy_stm32::init(Default::default());
31
32 // Configure I2C
33 let mut i2c_config = i2c::Config::default();
34 i2c_config.sda_pullup = false;
35 i2c_config.scl_pullup = false;
36 i2c_config.frequency = Hertz(100_000);
37 i2c_config.timeout = embassy_time::Duration::from_millis(30000);
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new_blocking(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 i2c_config,
44 );
45
46 // Convert to slave+master mode
47 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
48 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
49
50 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
51}
52
53#[embassy_executor::task]
54pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Blocking, i2c::mode::MultiMaster>) {
55 info!("Blocking I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
56
57 loop {
58 match i2c_slave.blocking_listen() {
59 Ok(SlaveCommand {
60 kind: SlaveCommandKind::Write,
61 address,
62 }) => {
63 let addr_val = match address {
64 Address::SevenBit(addr) => addr,
65 Address::TenBit(addr) => (addr & 0xFF) as u8,
66 };
67
68 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
69 let mut data_buffer = I2C_BUFFER.lock().await;
70
71 match i2c_slave.blocking_respond_to_write(&mut *data_buffer) {
72 Ok(bytes_received) => {
73 info!(
74 "I2C: Received {} bytes - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
75 bytes_received,
76 data_buffer[0],
77 data_buffer[1],
78 data_buffer[2],
79 data_buffer[3],
80 data_buffer[4],
81 data_buffer[5],
82 data_buffer[6],
83 data_buffer[7]
84 );
85 }
86 Err(e) => {
87 error!("I2C: Write error: {}", format_i2c_error(&e));
88 }
89 }
90 }
91
92 Ok(SlaveCommand {
93 kind: SlaveCommandKind::Read,
94 address,
95 }) => {
96 let addr_val = match address {
97 Address::SevenBit(addr) => addr,
98 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
99 };
100
101 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
102 let data_buffer = I2C_BUFFER.lock().await;
103
104 match i2c_slave.blocking_respond_to_read(&data_buffer[..BUFFER_SIZE]) {
105 Ok(bytes_sent) => {
106 info!("I2C: Responded to read - {} bytes sent", bytes_sent);
107 }
108 Err(e) => {
109 error!("I2C: Read error: {}", format_i2c_error(&e));
110 }
111 }
112 }
113
114 Err(e) => {
115 error!("I2C: Listen error: {}", format_i2c_error(&e));
116 Timer::after(Duration::from_millis(100)).await;
117 }
118 }
119 }
120}
121
122fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
123 match e {
124 embassy_stm32::i2c::Error::Bus => "Bus",
125 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
126 embassy_stm32::i2c::Error::Nack => "Nack",
127 embassy_stm32::i2c::Error::Timeout => "Timeout",
128 embassy_stm32::i2c::Error::Crc => "Crc",
129 embassy_stm32::i2c::Error::Overrun => "Overrun",
130 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
131 }
132}
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs
index feb27f6d9..5ff705ca2 100644
--- a/examples/stm32f4/src/bin/rtc.rs
+++ b/examples/stm32f4/src/bin/rtc.rs
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
diff --git a/examples/stm32g0/src/bin/onewire_ds18b20.rs b/examples/stm32g0/src/bin/onewire_ds18b20.rs
index 62f8711a6..43ecca8c4 100644
--- a/examples/stm32g0/src/bin/onewire_ds18b20.rs
+++ b/examples/stm32g0/src/bin/onewire_ds18b20.rs
@@ -267,7 +267,7 @@ where
267 } 267 }
268 268
269 match Self::crc8(&data) == 0 { 269 match Self::crc8(&data) == 0 {
270 true => Ok(((data[1] as u16) << 8 | data[0] as u16) as f32 / 16.), 270 true => Ok(((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.),
271 false => Err(()), 271 false => Err(()),
272 } 272 }
273 } 273 }
diff --git a/examples/stm32g0/src/bin/rtc.rs b/examples/stm32g0/src/bin/rtc.rs
index 21da204cc..d8b58de22 100644
--- a/examples/stm32g0/src/bin/rtc.rs
+++ b/examples/stm32g0/src/bin/rtc.rs
@@ -17,12 +17,12 @@ async fn main(_spawner: Spawner) {
17 17
18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0); 18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0);
19 19
20 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 20 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
21 21
22 rtc.set_datetime(now.unwrap()).expect("datetime not set"); 22 rtc.set_datetime(now.unwrap()).expect("datetime not set");
23 23
24 loop { 24 loop {
25 let now: DateTime = rtc.now().unwrap().into(); 25 let now: DateTime = time_provider.now().unwrap().into();
26 26
27 info!("{}:{}:{}", now.hour(), now.minute(), now.second()); 27 info!("{}:{}:{}", now.hour(), now.minute(), now.second());
28 28
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 6fd282d6d..8bbeb594c 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -7,12 +7,12 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32g491re to your chip name, if necessary. 9# Change stm32g491re to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 15embassy-futures = { path = "../../embassy-futures" }
16usbd-hid = "0.8.1" 16usbd-hid = "0.8.1"
17 17
18defmt = "1.0.1" 18defmt = "1.0.1"
@@ -25,6 +25,7 @@ embedded-can = { version = "0.4" }
25panic-probe = { version = "1.0.0", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27static_cell = "2.0.0" 27static_cell = "2.0.0"
28critical-section = "1.1"
28 29
29[profile.release] 30[profile.release]
30debug = 2 31debug = 2
diff --git a/examples/stm32g4/src/bin/adc_dma.rs b/examples/stm32g4/src/bin/adc_dma.rs
index a82067049..ef8b0c3c2 100644
--- a/examples/stm32g4/src/bin/adc_dma.rs
+++ b/examples/stm32g4/src/bin/adc_dma.rs
@@ -12,7 +12,7 @@ static mut DMA_BUF: [u16; 2] = [0; 2];
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
15 let mut read_buffer = unsafe { &mut DMA_BUF[..] }; 15 let read_buffer = unsafe { &mut DMA_BUF[..] };
16 16
17 let mut config = Config::default(); 17 let mut config = Config::default();
18 { 18 {
@@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) {
47 (&mut pa0, SampleTime::CYCLES247_5), 47 (&mut pa0, SampleTime::CYCLES247_5),
48 ] 48 ]
49 .into_iter(), 49 .into_iter(),
50 &mut read_buffer, 50 read_buffer,
51 ) 51 )
52 .await; 52 .await;
53 53
diff --git a/examples/stm32g4/src/bin/adc_injected_and_regular.rs b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
new file mode 100644
index 000000000..3ae2ff064
--- /dev/null
+++ b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
@@ -0,0 +1,154 @@
1//! adc injected and regular conversions
2//!
3//! This example both regular and injected ADC conversions at the same time
4//! p:pa0 n:pa2
5
6#![no_std]
7#![no_main]
8
9use core::cell::RefCell;
10
11use defmt::info;
12use embassy_stm32::adc::{
13 Adc, AdcChannel as _, ConversionTrigger, Exten, InjectedAdc, RegularConversionMode, SampleTime,
14};
15use embassy_stm32::interrupt::typelevel::{ADC1_2, Interrupt};
16use embassy_stm32::peripherals::ADC1;
17use embassy_stm32::time::Hertz;
18use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, Mms2};
19use embassy_stm32::timer::low_level::CountingMode;
20use embassy_stm32::{Config, interrupt};
21use embassy_sync::blocking_mutex::CriticalSectionMutex;
22use {defmt_rtt as _, panic_probe as _};
23
24static ADC1_HANDLE: CriticalSectionMutex<RefCell<Option<InjectedAdc<ADC1, 1>>>> =
25 CriticalSectionMutex::new(RefCell::new(None));
26
27/// This example showcases how to use both regular ADC conversions with DMA and injected ADC
28/// conversions with ADC interrupt simultaneously. Both conversion types can be configured with
29/// different triggers and thanks to DMA it is possible to use the measurements in different task
30/// without needing to access the ADC peripheral.
31///
32/// If you don't need both regular and injected conversions the example code can easily be reworked
33/// to only include one of the ADC conversion types.
34#[embassy_executor::main]
35async fn main(_spawner: embassy_executor::Spawner) {
36 // See Table 166 and 167 in RM0440 Rev 9 for ADC1/2 External triggers
37 // Note: Regular and Injected channels use different tables!!
38 const ADC1_INJECTED_TRIGGER_TIM1_TRGO2: u8 = 8;
39 const ADC1_REGULAR_TRIGGER_TIM1_TRGO2: u8 = 10;
40
41 // --- RCC config ---
42 let mut config = Config::default();
43 {
44 use embassy_stm32::rcc::*;
45 config.rcc.pll = Some(Pll {
46 source: PllSource::HSI,
47 prediv: PllPreDiv::DIV4,
48 mul: PllMul::MUL85,
49 divp: None,
50 divq: None,
51 divr: Some(PllRDiv::DIV2),
52 });
53 config.rcc.mux.adc12sel = mux::Adcsel::SYS;
54 config.rcc.sys = Sysclk::PLL1_R;
55 }
56 let p = embassy_stm32::init(config);
57
58 // In this example we use tim1_trgo2 event to trigger the ADC conversions
59 let tim1 = p.TIM1;
60 let pwm_freq = 1;
61 let mut pwm = ComplementaryPwm::new(
62 tim1,
63 None,
64 None,
65 None,
66 None,
67 None,
68 None,
69 None,
70 None,
71 Hertz::hz(pwm_freq),
72 CountingMode::EdgeAlignedUp,
73 );
74 pwm.set_master_output_enable(false);
75 // Mms2 is used to configure which timer event that is connected to tim1_trgo2.
76 // In this case we use the update event of the timer.
77 pwm.set_mms2(Mms2::UPDATE);
78
79 // Configure regular conversions with DMA
80 let adc1 = Adc::new(p.ADC1);
81
82 let vrefint_channel = adc1.enable_vrefint().degrade_adc();
83 let pa0 = p.PC1.degrade_adc();
84 let regular_sequence = [
85 (vrefint_channel, SampleTime::CYCLES247_5),
86 (pa0, SampleTime::CYCLES247_5),
87 ]
88 .into_iter();
89
90 // Configurations of Injected ADC measurements
91 let pa2 = p.PA2.degrade_adc();
92 let injected_sequence = [(pa2, SampleTime::CYCLES247_5)];
93
94 // Configure DMA for retrieving regular ADC measurements
95 let dma1_ch1 = p.DMA1_CH1;
96 // Using buffer of double size means the half-full interrupts will generate at the expected rate
97 let mut readings = [0u16; 4];
98
99 let injected_trigger = ConversionTrigger {
100 channel: ADC1_INJECTED_TRIGGER_TIM1_TRGO2,
101 edge: Exten::RISING_EDGE,
102 };
103 let regular_trigger = ConversionTrigger {
104 channel: ADC1_REGULAR_TRIGGER_TIM1_TRGO2,
105 edge: Exten::RISING_EDGE,
106 };
107
108 let (mut ring_buffered_adc, injected_adc) = adc1.into_ring_buffered_and_injected(
109 dma1_ch1,
110 &mut readings,
111 regular_sequence,
112 RegularConversionMode::Triggered(regular_trigger),
113 injected_sequence,
114 injected_trigger,
115 true,
116 );
117
118 // Store ADC globally to allow access from ADC interrupt
119 critical_section::with(|cs| {
120 ADC1_HANDLE.borrow(cs).replace(Some(injected_adc));
121 });
122 // Enable interrupt for ADC1_2
123 unsafe { ADC1_2::enable() };
124
125 // Main loop for reading regular ADC measurements periodically
126 let mut data = [0u16; 2];
127 loop {
128 {
129 match ring_buffered_adc.read(&mut data).await {
130 Ok(n) => {
131 defmt::info!("Regular ADC reading, VrefInt: {}, PA0: {}", data[0], data[1]);
132 defmt::info!("Remaining samples: {}", n,);
133 }
134 Err(e) => {
135 defmt::error!("DMA error: {:?}", e);
136 ring_buffered_adc.clear();
137 }
138 }
139 }
140 }
141}
142
143/// Use ADC1_2 interrupt to retrieve injected ADC measurements
144/// Interrupt must be unsafe as hardware can invoke it any-time. Critical sections ensure safety
145/// within the interrupt.
146#[interrupt]
147unsafe fn ADC1_2() {
148 critical_section::with(|cs| {
149 if let Some(injected_adc) = ADC1_HANDLE.borrow(cs).borrow_mut().as_mut() {
150 let injected_data = injected_adc.read_injected_samples();
151 info!("Injected reading of PA2: {}", injected_data[0]);
152 }
153 });
154}
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 475ba7e8a..512186c3d 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35 35
diff --git a/examples/stm32h5/src/bin/backup_sram.rs b/examples/stm32h5/src/bin/backup_sram.rs
new file mode 100644
index 000000000..f8db1853e
--- /dev/null
+++ b/examples/stm32h5/src/bin/backup_sram.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::backup_sram::BackupMemory;
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut config = Config::default();
14 config.rcc.ls.enable_backup_sram = true;
15
16 let p = embassy_stm32::init(config);
17 info!("Started!");
18
19 let (bytes, status) = BackupMemory::new(p.BKPSRAM);
20
21 match status {
22 false => info!("BKPSRAM just enabled"),
23 true => info!("BKPSRAM already enabled"),
24 }
25
26 loop {
27 info!("byte0: {}", bytes[0]);
28 bytes[0] = bytes[0].wrapping_add(1);
29 Timer::after_millis(500).await;
30 }
31}
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 3c4f49f64..caebc9daf 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -9,10 +9,8 @@ use embassy_executor::Spawner;
9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
10use embassy_stm32::low_power::Executor; 10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; 11use embassy_stm32::rcc::{HSIPrescaler, LsConfig};
12use embassy_stm32::rtc::{Rtc, RtcConfig};
13use embassy_stm32::{Config, Peri}; 12use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 13use embassy_time::Timer;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
17 15
18#[cortex_m_rt::entry] 16#[cortex_m_rt::entry]
@@ -37,12 +35,6 @@ async fn async_main(spawner: Spawner) {
37 // config.enable_debug_during_sleep = false; 35 // config.enable_debug_during_sleep = false;
38 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
39 37
40 // give the RTC to the executor...
41 let rtc = Rtc::new(p.RTC, RtcConfig::default());
42 static RTC: StaticCell<Rtc> = StaticCell::new();
43 let rtc = RTC.init(rtc);
44 embassy_stm32::low_power::stop_with_rtc(rtc);
45
46 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 38 spawner.spawn(unwrap!(blinky(p.PB4.into())));
47 spawner.spawn(unwrap!(timeout())); 39 spawner.spawn(unwrap!(timeout()));
48} 40}
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 5993110de..09b734054 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs
index 1bd71637b..965716d23 100644
--- a/examples/stm32h7/src/bin/rtc.rs
+++ b/examples/stm32h7/src/bin/rtc.rs
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index 61f31be24..f7ab20cdd 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
index be6a26d82..cd9d6c789 100644
--- a/examples/stm32h7/src/bin/spi_bdma.rs
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -20,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _};
20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); 20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit();
21 21
22#[embassy_executor::task] 22#[embassy_executor::task]
23async fn main_task(mut spi: spi::Spi<'static, Async>) { 23async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
24 let (read_buffer, write_buffer) = unsafe { 24 let (read_buffer, write_buffer) = unsafe {
25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); 25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3);
26 ram.initialize_all_copied(0); 26 ram.initialize_all_copied(0);
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 20cb67ba0..3d3c2f43e 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index b5c313523..d69f0228e 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml
index 7a1519aae..f4e1e53b7 100644
--- a/examples/stm32h755cm7/Cargo.toml
+++ b/examples/stm32h755cm7/Cargo.toml
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml
index 4cd7b84e5..0509d394d 100644
--- a/examples/stm32h7b0/Cargo.toml
+++ b/examples/stm32h7b0/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml
index 445916972..ab525ad91 100644
--- a/examples/stm32h7rs/Cargo.toml
+++ b/examples/stm32h7rs/Cargo.toml
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7rs/src/bin/rtc.rs b/examples/stm32h7rs/src/bin/rtc.rs
index 1bd71637b..965716d23 100644
--- a/examples/stm32h7rs/src/bin/rtc.rs
+++ b/examples/stm32h7rs/src/bin/rtc.rs
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs
index 8c280fdae..3253304eb 100644
--- a/examples/stm32h7rs/src/bin/spi.rs
+++ b/examples/stm32h7rs/src/bin/spi.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs
index 3fa69fd15..ca644c6a8 100644
--- a/examples/stm32h7rs/src/bin/spi_dma.rs
+++ b/examples/stm32h7rs/src/bin/spi_dma.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs
new file mode 100644
index 000000000..7a9200edd
--- /dev/null
+++ b/examples/stm32l4/src/bin/adc_dma.rs
@@ -0,0 +1,51 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel, SampleTime};
8use {defmt_rtt as _, panic_probe as _};
9
10const DMA_BUF_LEN: usize = 512;
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 info!("Hello World!");
15
16 let mut config = Config::default();
17 {
18 use embassy_stm32::rcc::*;
19 config.rcc.mux.adcsel = mux::Adcsel::SYS;
20 }
21 let p = embassy_stm32::init(config);
22
23 let mut adc = Adc::new(p.ADC1);
24 let mut adc_pin0 = p.PA0.degrade_adc();
25 let mut adc_pin1 = p.PA1.degrade_adc();
26 let mut adc_dma_buf = [0u16; DMA_BUF_LEN];
27 let mut measurements = [0u16; DMA_BUF_LEN / 2];
28 let mut ring_buffered_adc = adc.into_ring_buffered(
29 p.DMA1_CH1,
30 &mut adc_dma_buf,
31 [
32 (&mut adc_pin0, SampleTime::CYCLES640_5),
33 (&mut adc_pin1, SampleTime::CYCLES640_5),
34 ]
35 .into_iter(),
36 );
37
38 info!("starting measurement loop");
39 loop {
40 match ring_buffered_adc.read(&mut measurements).await {
41 Ok(_) => {
42 //note: originally there was a print here showing all the samples,
43 //but even that takes too much time and would cause adc overruns
44 info!("adc1 first 10 samples: {}", measurements[0..10]);
45 }
46 Err(e) => {
47 warn!("Error: {:?}", e);
48 }
49 }
50 }
51}
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index 1d26cd008..8b92075cc 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) {
39 .and_hms_opt(10, 30, 15) 39 .and_hms_opt(10, 30, 15)
40 .unwrap(); 40 .unwrap();
41 41
42 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 42 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
43 info!("Got RTC! {:?}", now.and_utc().timestamp()); 43 info!("Got RTC! {:?}", now.and_utc().timestamp());
44 44
45 rtc.set_datetime(now.into()).expect("datetime not set"); 45 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -47,6 +47,6 @@ async fn main(_spawner: Spawner) {
47 // In reality the delay would be much longer 47 // In reality the delay would be much longer
48 Timer::after_millis(20000).await; 48 Timer::after_millis(20000).await;
49 49
50 let then: NaiveDateTime = rtc.now().unwrap().into(); 50 let then: NaiveDateTime = time_provider.now().unwrap().into();
51 info!("Got RTC! {:?}", then.and_utc().timestamp()); 51 info!("Got RTC! {:?}", then.and_utc().timestamp());
52} 52}
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 8e54938d1..0dbf515cf 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -28,6 +28,7 @@ use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; 28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c};
29use embassy_stm32::mode::Async; 29use embassy_stm32::mode::Async;
30use embassy_stm32::rng::{self, Rng}; 30use embassy_stm32::rng::{self, Rng};
31use embassy_stm32::spi::mode::Master;
31use embassy_stm32::spi::{Config as SPI_Config, Spi}; 32use embassy_stm32::spi::{Config as SPI_Config, Spi};
32use embassy_stm32::time::Hertz; 33use embassy_stm32::time::Hertz;
33use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; 34use embassy_stm32::{bind_interrupts, exti, pac, peripherals};
@@ -54,7 +55,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 5), 24)
54// Listen port for the webserver 55// Listen port for the webserver
55const HTTP_LISTEN_PORT: u16 = 80; 56const HTTP_LISTEN_PORT: u16 = 80;
56 57
57pub type SpeSpi = Spi<'static, Async>; 58pub type SpeSpi = Spi<'static, Async, Master>;
58pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; 59pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
59pub type SpeInt = exti::ExtiInput<'static>; 60pub type SpeInt = exti::ExtiInput<'static>;
60pub type SpeRst = Output<'static>; 61pub type SpeRst = Output<'static>;
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index c34053190..3d119f90f 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -6,10 +6,8 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
7use embassy_stm32::low_power::Executor; 7use embassy_stm32::low_power::Executor;
8use embassy_stm32::rcc::LsConfig; 8use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::{Config, Peri}; 9use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15#[cortex_m_rt::entry] 13#[cortex_m_rt::entry]
@@ -28,12 +26,6 @@ async fn async_main(spawner: Spawner) {
28 // config.enable_debug_during_sleep = false; 26 // config.enable_debug_during_sleep = false;
29 let p = embassy_stm32::init(config); 27 let p = embassy_stm32::init(config);
30 28
31 // give the RTC to the executor...
32 let rtc = Rtc::new(p.RTC, RtcConfig::default());
33 static RTC: StaticCell<Rtc> = StaticCell::new();
34 let rtc = RTC.init(rtc);
35 embassy_stm32::low_power::stop_with_rtc(rtc);
36
37 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 29 spawner.spawn(unwrap!(blinky(p.PC7.into())));
38 spawner.spawn(unwrap!(timeout())); 30 spawner.spawn(unwrap!(timeout()));
39} 31}
diff --git a/examples/stm32u0/src/bin/rtc.rs b/examples/stm32u0/src/bin/rtc.rs
index d071cfbc7..56d16ccf7 100644
--- a/examples/stm32u0/src/bin/rtc.rs
+++ b/examples/stm32u0/src/bin/rtc.rs
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
36 .and_hms_opt(10, 30, 15) 36 .and_hms_opt(10, 30, 15)
37 .unwrap(); 37 .unwrap();
38 38
39 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 39 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
40 info!("Got RTC! {:?}", now.and_utc().timestamp()); 40 info!("Got RTC! {:?}", now.and_utc().timestamp());
41 41
42 rtc.set_datetime(now.into()).expect("datetime not set"); 42 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -44,6 +44,6 @@ async fn main(_spawner: Spawner) {
44 // In reality the delay would be much longer 44 // In reality the delay would be much longer
45 Timer::after_millis(20000).await; 45 Timer::after_millis(20000).await;
46 46
47 let then: NaiveDateTime = rtc.now().unwrap().into(); 47 let then: NaiveDateTime = time_provider.now().unwrap().into();
48 info!("Got RTC! {:?}", then.and_utc().timestamp()); 48 info!("Got RTC! {:?}", then.and_utc().timestamp());
49} 49}
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index d3709120f..2185142c9 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
44 .and_hms_opt(10, 30, 15) 44 .and_hms_opt(10, 30, 15)
45 .unwrap(); 45 .unwrap();
46 46
47 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 47 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
48 info!("Got RTC! {:?}", now.and_utc().timestamp()); 48 info!("Got RTC! {:?}", now.and_utc().timestamp());
49 49
50 rtc.set_datetime(now.into()).expect("datetime not set"); 50 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -52,6 +52,6 @@ async fn main(_spawner: Spawner) {
52 // In reality the delay would be much longer 52 // In reality the delay would be much longer
53 Timer::after_millis(20000).await; 53 Timer::after_millis(20000).await;
54 54
55 let then: NaiveDateTime = rtc.now().unwrap().into(); 55 let then: NaiveDateTime = time_provider.now().unwrap().into();
56 info!("Got RTC! {:?}", then.and_utc().timestamp()); 56 info!("Got RTC! {:?}", then.and_utc().timestamp());
57} 57}
diff --git a/examples/stm32wle5/.cargo/config.toml b/examples/stm32wle5/.cargo/config.toml
new file mode 100644
index 000000000..0178d377c
--- /dev/null
+++ b/examples/stm32wle5/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip STM32WLE5JCIx --connect-under-reset"
4
5[build]
6target = "thumbv7em-none-eabi"
7
8[env]
9DEFMT_LOG = "info"
diff --git a/examples/stm32wle5/Cargo.toml b/examples/stm32wle5/Cargo.toml
new file mode 100644
index 000000000..f2fc4dd3d
--- /dev/null
+++ b/examples/stm32wle5/Cargo.toml
@@ -0,0 +1,38 @@
1[package]
2edition = "2024"
3name = "embassy-stm32wl-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# Change stm32wl55jc-cm4 to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wle5jc", "time-driver-any", "memory-x", "unstable-pac", "exti", "low-power"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-1_000"] }
14embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
15
16defmt = "1.0.1"
17defmt-rtt = { version = "1.1.0", optional = true }
18defmt-serial = { version = "0.10.0", optional = true }
19
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0"
22embedded-hal = "1.0.0"
23embedded-storage = "0.3.1"
24panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25static_cell = { version = "2.1.1", default-features = false }
26
27[profile.release]
28debug = 2
29
30[package.metadata.embassy]
31build = [
32 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" }
33]
34
35[features]
36default = ["defmt-serial"]
37defmt-rtt = ["dep:defmt-rtt"]
38defmt-serial = ["dep:defmt-serial"]
diff --git a/examples/stm32wle5/README.md b/examples/stm32wle5/README.md
new file mode 100644
index 000000000..18c3b5071
--- /dev/null
+++ b/examples/stm32wle5/README.md
@@ -0,0 +1,52 @@
1# Low Power Examples for STM32WLEx family
2
3Examples in this repo should work with [LoRa-E5 Dev Board](https://www.st.com/en/partner-products-and-services/lora-e5-development-kit.html) board.
4
5## Prerequsits
6
7- Connect a usb serial adapter to LPUart1 (this is where ALL logging will go)
8- Optional: Connect an amp meter that ran measure down to 0.1uA to the power test pins
9- `cargo install defmt-print` so you can print log messahes from LPUart1
10
11## Example Notes
12
13All examples will set all pins to analog mode before configuring pins for the example, if any. This saves about 500uA!!!!
14
15- the `adc` example will sleep in STOP1 betwen samples and the chip will only draw about 13uA while sleeping
16- the `blinky` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
17- the `button_exti` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
18- the `i2c` examples will sleep in STOP1 between reads and the chip only draw about 10uA while sleeping
19
20For each example you will need to start `defmt-print` with the example binary and the correct serial port in a seperate terminal. Example:
21```
22defmt-print -w -v -e target/thumbv7em-none-eabi/debug/<module-name> serial --path /dev/cu.usbserial-00000000 --baud 115200
23```
24
25Run individual examples with
26```
27cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin <module-name>
28```
29for example
30```
31cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin blinky
32```
33
34You can also run them with with `run`. However in this case expect probe-rs to be disconnected as soon as flashing is done as all IO pins are set to analog input!
35```
36cargo run --bin blinky
37```
38
39## Checklist before running examples
40You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
41
42* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L432KCU6 it should be `probe-rs run --chip STM32L432KCUx`. (use `probe-rs chip list` to find your chip)
43* [ ] Update Cargo.toml to have the correct `embassy-stm32` feature. For example for L432KCU6 it should be `stm32l432kc`. Look in the `Cargo.toml` file of the `embassy-stm32` project to find the correct feature flag for your chip.
44* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
45* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
46
47If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
48
49* Which example you are trying to run
50* Which chip and board you are using
51
52Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
diff --git a/examples/stm32wle5/build.rs b/examples/stm32wle5/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32wle5/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs
new file mode 100644
index 000000000..8b830a1e6
--- /dev/null
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -0,0 +1,94 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, SampleTime};
9use embassy_stm32::low_power::Executor;
10use embassy_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 // enable ADC with HSI clock
32 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
33 #[cfg(feature = "defmt-serial")]
34 {
35 // disable debug during sleep to reduce power consumption since we are
36 // using defmt-serial on LPUART1.
37 config.enable_debug_during_sleep = false;
38 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
39 // so that its registers are preserved during STOP modes.
40 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
41 }
42 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
43 let p = embassy_stm32::init(config);
44
45 // start with all GPIOs as analog to reduce power consumption
46 for r in [
47 embassy_stm32::pac::GPIOA,
48 embassy_stm32::pac::GPIOB,
49 embassy_stm32::pac::GPIOC,
50 embassy_stm32::pac::GPIOH,
51 ] {
52 r.moder().modify(|w| {
53 for i in 0..16 {
54 // don't reset these if probe-rs should stay connected!
55 #[cfg(feature = "defmt-rtt")]
56 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
57 continue;
58 }
59 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
60 }
61 });
62 }
63 #[cfg(feature = "defmt-serial")]
64 {
65 use embassy_stm32::mode::Blocking;
66 use embassy_stm32::usart::Uart;
67 let config = embassy_stm32::usart::Config::default();
68 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
69 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
70 defmt_serial::defmt_serial(SERIAL.init(uart));
71 }
72
73 info!("Hello World!");
74
75 let mut adc = Adc::new(p.ADC1);
76 adc.set_sample_time(SampleTime::CYCLES79_5);
77 let mut pin = p.PA10;
78
79 let mut vrefint = adc.enable_vrefint();
80 let vrefint_sample = adc.blocking_read(&mut vrefint);
81 let convert_to_millivolts = |sample| {
82 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
83 // 6.3.3 Embedded internal reference voltage
84 const VREFINT_MV: u32 = 1212; // mV
85
86 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
87 };
88
89 loop {
90 let v = adc.blocking_read(&mut pin);
91 info!("--> {} - {} mV", v, convert_to_millivolts(v));
92 Timer::after_secs(1).await;
93 }
94}
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
new file mode 100644
index 000000000..b2745fdaf
--- /dev/null
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -0,0 +1,84 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::low_power::Executor;
10use embassy_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 #[cfg(feature = "defmt-serial")]
32 {
33 // disable debug during sleep to reduce power consumption since we are
34 // using defmt-serial on LPUART1.
35 config.enable_debug_during_sleep = false;
36 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
37 // so that its registers are preserved during STOP modes.
38 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
39 }
40 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
41 let p = embassy_stm32::init(config);
42
43 // start with all GPIOs as analog to reduce power consumption
44 for r in [
45 embassy_stm32::pac::GPIOA,
46 embassy_stm32::pac::GPIOB,
47 embassy_stm32::pac::GPIOC,
48 embassy_stm32::pac::GPIOH,
49 ] {
50 r.moder().modify(|w| {
51 for i in 0..16 {
52 // don't reset these if probe-rs should stay connected!
53 #[cfg(feature = "defmt-rtt")]
54 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
55 continue;
56 }
57 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
58 }
59 });
60 }
61 #[cfg(feature = "defmt-serial")]
62 {
63 use embassy_stm32::mode::Blocking;
64 use embassy_stm32::usart::Uart;
65 let config = embassy_stm32::usart::Config::default();
66 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
67 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
68 defmt_serial::defmt_serial(SERIAL.init(uart));
69 }
70
71 info!("Hello World!");
72
73 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
74
75 loop {
76 info!("low");
77 led.set_low();
78 Timer::after_millis(500).await;
79
80 info!("high");
81 led.set_high();
82 Timer::after_millis(500).await;
83 }
84}
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
new file mode 100644
index 000000000..db1bff0be
--- /dev/null
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -0,0 +1,85 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::Pull;
10use embassy_stm32::low_power::Executor;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[cortex_m_rt::entry]
15fn main() -> ! {
16 info!("main: Starting!");
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 });
20}
21
22#[embassy_executor::task]
23async fn async_main(_spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default();
25 // enable HSI clock
26 config.rcc.hsi = true;
27 // enable LSI clock for RTC
28 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
29 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
30 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
31 // enable ADC with HSI clock
32 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
33 #[cfg(feature = "defmt-serial")]
34 {
35 // disable debug during sleep to reduce power consumption since we are
36 // using defmt-serial on LPUART1.
37 config.enable_debug_during_sleep = false;
38 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
39 // so that its registers are preserved during STOP modes.
40 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
41 }
42 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
43 let p = embassy_stm32::init(config);
44
45 // start with all GPIOs as analog to reduce power consumption
46 for r in [
47 embassy_stm32::pac::GPIOA,
48 embassy_stm32::pac::GPIOB,
49 embassy_stm32::pac::GPIOC,
50 embassy_stm32::pac::GPIOH,
51 ] {
52 r.moder().modify(|w| {
53 for i in 0..16 {
54 // don't reset these if probe-rs should stay connected!
55 #[cfg(feature = "defmt-rtt")]
56 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
57 continue;
58 }
59 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
60 }
61 });
62 }
63 #[cfg(feature = "defmt-serial")]
64 {
65 use embassy_stm32::mode::Blocking;
66 use embassy_stm32::usart::Uart;
67 let config = embassy_stm32::usart::Config::default();
68 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
69 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
70 defmt_serial::defmt_serial(SERIAL.init(uart));
71 }
72
73 info!("Hello World!");
74
75 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up);
76
77 info!("Press the USER button...");
78
79 loop {
80 button.wait_for_falling_edge().await;
81 info!("Pressed!");
82 button.wait_for_rising_edge().await;
83 info!("Released!");
84 }
85}
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
new file mode 100644
index 000000000..c31c673c9
--- /dev/null
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -0,0 +1,104 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::i2c::I2c;
9use embassy_stm32::low_power::Executor;
10use embassy_stm32::time::Hertz;
11use embassy_stm32::{bind_interrupts, i2c, peripherals};
12use embassy_time::{Duration, Timer};
13use panic_probe as _;
14use static_cell::StaticCell;
15
16bind_interrupts!(struct IrqsI2C{
17 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
18 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
19});
20
21#[cortex_m_rt::entry]
22fn main() -> ! {
23 info!("main: Starting!");
24 Executor::take().run(|spawner| {
25 spawner.spawn(unwrap!(async_main(spawner)));
26 });
27}
28
29#[embassy_executor::task]
30async fn async_main(_spawner: Spawner) {
31 let mut config = embassy_stm32::Config::default();
32 // enable HSI clock
33 config.rcc.hsi = true;
34 // enable LSI clock for RTC
35 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
36 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
37 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
38 // enable ADC with HSI clock
39 config.rcc.mux.i2c2sel = embassy_stm32::pac::rcc::vals::I2c2sel::HSI;
40 #[cfg(feature = "defmt-serial")]
41 {
42 // disable debug during sleep to reduce power consumption since we are
43 // using defmt-serial on LPUART1.
44 config.enable_debug_during_sleep = false;
45 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
46 // so that its registers are preserved during STOP modes.
47 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
48 }
49 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
50 let p = embassy_stm32::init(config);
51
52 // start with all GPIOs as analog to reduce power consumption
53 for r in [
54 embassy_stm32::pac::GPIOA,
55 embassy_stm32::pac::GPIOB,
56 embassy_stm32::pac::GPIOC,
57 embassy_stm32::pac::GPIOH,
58 ] {
59 r.moder().modify(|w| {
60 for i in 0..16 {
61 // don't reset these if probe-rs should stay connected!
62 #[cfg(feature = "defmt-rtt")]
63 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
64 continue;
65 }
66 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
67 }
68 });
69 }
70 #[cfg(feature = "defmt-serial")]
71 {
72 use embassy_stm32::mode::Blocking;
73 use embassy_stm32::usart::Uart;
74 let config = embassy_stm32::usart::Config::default();
75 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
76 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
77 defmt_serial::defmt_serial(SERIAL.init(uart));
78 }
79
80 info!("Hello World!");
81 let en3v3 = embassy_stm32::gpio::Output::new(
82 p.PA9,
83 embassy_stm32::gpio::Level::High,
84 embassy_stm32::gpio::Speed::High,
85 );
86 core::mem::forget(en3v3); // keep the output pin enabled
87
88 let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, {
89 let mut config = i2c::Config::default();
90 config.frequency = Hertz::khz(100);
91 config.timeout = Duration::from_millis(500);
92 config
93 });
94
95 loop {
96 let mut buffer = [0; 2];
97 // read the temperature register of the onboard lm75
98 match i2c.read(0x48, &mut buffer).await {
99 Ok(_) => info!("--> {:?}", buffer),
100 Err(e) => info!("--> Error: {:?}", e),
101 }
102 Timer::after_secs(5).await;
103 }
104}
diff --git a/examples/stm32wle5/stm32wle5.code-workspace b/examples/stm32wle5/stm32wle5.code-workspace
new file mode 100644
index 000000000..a7c4a0ebd
--- /dev/null
+++ b/examples/stm32wle5/stm32wle5.code-workspace
@@ -0,0 +1,13 @@
1{
2 "folders": [
3 {
4 "path": "."
5 }
6 ],
7 "settings": {
8 "rust-analyzer.cargo.target": "thumbv7em-none-eabi",
9 "rust-analyzer.cargo.allTargets": false,
10 "rust-analyzer.cargo.targetDir": "target/rust-analyzer",
11 "rust-analyzer.checkOnSave": true,
12 }
13}
diff --git a/tests/nrf/.cargo/config.toml b/tests/nrf/.cargo/config.toml
index 8f9bccbc0..0192c10ae 100644
--- a/tests/nrf/.cargo/config.toml
+++ b/tests/nrf/.cargo/config.toml
@@ -1,6 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))'] 1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2#runner = "teleprobe local run --chip nRF52840_xxAA --elf" 2runner = "teleprobe local run --chip nRF52840_xxAA --elf"
3runner = "teleprobe client run" 3#runner = "teleprobe client run"
4 4
5[build] 5[build]
6#target = "thumbv6m-none-eabi" 6#target = "thumbv6m-none-eabi"
diff --git a/tests/nrf/src/bin/buffered_uart_spam.rs b/tests/nrf/src/bin/buffered_uart_spam.rs
index 24ddd06f3..6d862e19d 100644
--- a/tests/nrf/src/bin/buffered_uart_spam.rs
+++ b/tests/nrf/src/bin/buffered_uart_spam.rs
@@ -55,14 +55,14 @@ async fn main(_spawner: Spawner) {
55 static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 55 static mut TX_BUF: [u8; NSPAM] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
56 let _spam = UarteTx::new(peri!(p, UART1), irqs!(UART1), peri!(p, PIN_A), config.clone()); 56 let _spam = UarteTx::new(peri!(p, UART1), irqs!(UART1), peri!(p, PIN_A), config.clone());
57 let spam_peri = pac::UARTE1; 57 let spam_peri = pac::UARTE1;
58 let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(spam_peri.events_endtx().as_ptr())) }; 58 let event = unsafe { Event::new_unchecked(NonNull::new_unchecked(spam_peri.events_dma().tx().end().as_ptr())) };
59 let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(spam_peri.tasks_starttx().as_ptr())) }; 59 let task = unsafe { Task::new_unchecked(NonNull::new_unchecked(spam_peri.tasks_dma().tx().start().as_ptr())) };
60 let mut spam_ppi = Ppi::new_one_to_one(p.PPI_CH2, event, task); 60 let mut spam_ppi = Ppi::new_one_to_one(p.PPI_CH2, event, task);
61 spam_ppi.enable(); 61 spam_ppi.enable();
62 let p = (&raw mut TX_BUF) as *mut u8; 62 let p = (&raw mut TX_BUF) as *mut u8;
63 spam_peri.txd().ptr().write_value(p as u32); 63 spam_peri.dma().tx().ptr().write_value(p as u32);
64 spam_peri.txd().maxcnt().write(|w| w.set_maxcnt(NSPAM as _)); 64 spam_peri.dma().tx().maxcnt().write(|w| w.set_maxcnt(NSPAM as _));
65 spam_peri.tasks_starttx().write_value(1); 65 spam_peri.tasks_dma().tx().start().write_value(1);
66 66
67 let mut i = 0; 67 let mut i = 0;
68 let mut total = 0; 68 let mut total = 0;
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
index 091a70ce9..ac082dbb8 100644
--- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
+++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
@@ -29,8 +29,7 @@ const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
29async fn wifi_task( 29async fn wifi_task(
30 runner: hosted::Runner< 30 runner: hosted::Runner<
31 'static, 31 'static,
32 ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, 32 hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>,
33 Input<'static>,
34 Output<'static>, 33 Output<'static>,
35 >, 34 >,
36) -> ! { 35) -> ! {
@@ -64,15 +63,11 @@ async fn main(spawner: Spawner) {
64 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); 63 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
65 let spi = ExclusiveDevice::new(spi, cs, Delay); 64 let spi = ExclusiveDevice::new(spi, cs, Delay);
66 65
66 let iface = hosted::SpiInterface::new(spi, handshake, ready);
67
67 static STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); 68 static STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
68 let (device, mut control, runner) = embassy_net_esp_hosted::new( 69 let (device, mut control, runner) =
69 STATE.init(embassy_net_esp_hosted::State::new()), 70 embassy_net_esp_hosted::new(STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await;
70 spi,
71 handshake,
72 ready,
73 reset,
74 )
75 .await;
76 71
77 spawner.spawn(unwrap!(wifi_task(runner))); 72 spawner.spawn(unwrap!(wifi_task(runner)));
78 73
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 1161e827b..b92b47be2 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -73,7 +73,7 @@ teleprobe-meta = "1"
73embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 73embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
74embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 74embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
75embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] } 75embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] }
76embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any"] } 76embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "memory-x", "time-driver-any", "_allow-disable-rtc"] }
77embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 77embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
78embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } 78embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] }
79embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } 79embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
@@ -94,6 +94,7 @@ rand_core = { version = "0.9.1", default-features = false }
94rand_chacha = { version = "0.9.0", default-features = false } 94rand_chacha = { version = "0.9.0", default-features = false }
95static_cell = "2" 95static_cell = "2"
96portable-atomic = { version = "1.5", features = [] } 96portable-atomic = { version = "1.5", features = [] }
97critical-section = "1.1"
97 98
98chrono = { version = "^0.4", default-features = false, optional = true} 99chrono = { version = "^0.4", default-features = false, optional = true}
99sha2 = { version = "0.10.8", default-features = false } 100sha2 = { version = "0.10.8", default-features = false }
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs
index 5fe98d807..eb27af4ca 100644
--- a/tests/stm32/src/bin/rtc.rs
+++ b/tests/stm32/src/bin/rtc.rs
@@ -10,13 +10,19 @@ use common::*;
10use defmt::assert; 10use defmt::assert;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_stm32::rcc::LsConfig; 12use embassy_stm32::rcc::LsConfig;
13#[cfg(feature = "stop")]
14use embassy_stm32::rtc::Rtc;
15#[cfg(not(feature = "stop"))]
13use embassy_stm32::rtc::{Rtc, RtcConfig}; 16use embassy_stm32::rtc::{Rtc, RtcConfig};
14use embassy_time::Timer; 17use embassy_time::Timer;
15
16#[embassy_executor::main] 18#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
18 let mut config = config(); 20 let mut config = config();
19 config.rcc.ls = LsConfig::default_lse(); 21 config.rcc.ls = LsConfig::default_lse();
22 #[cfg(feature = "stop")]
23 {
24 config.rtc._disable_rtc = false;
25 }
20 26
21 let p = init_with_config(config); 27 let p = init_with_config(config);
22 info!("Hello World!"); 28 info!("Hello World!");
@@ -26,14 +32,25 @@ async fn main(_spawner: Spawner) {
26 .and_hms_opt(10, 30, 15) 32 .and_hms_opt(10, 30, 15)
27 .unwrap(); 33 .unwrap();
28 34
29 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 35 #[cfg(not(feature = "stop"))]
36 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
37
38 #[cfg(feature = "stop")]
39 let (rtc, time_provider) = Rtc::new(p.RTC);
30 40
41 #[cfg(not(feature = "stop"))]
31 rtc.set_datetime(now.into()).expect("datetime not set"); 42 rtc.set_datetime(now.into()).expect("datetime not set");
32 43
44 #[cfg(feature = "stop")]
45 critical_section::with(|cs| {
46 rtc.borrow_mut(cs).set_datetime(now.into()).expect("datetime not set");
47 });
48
33 info!("Waiting 5 seconds"); 49 info!("Waiting 5 seconds");
34 Timer::after_millis(5000).await; 50 Timer::after_millis(5000).await;
35 51
36 let then: NaiveDateTime = rtc.now().unwrap().into(); 52 let then: NaiveDateTime = time_provider.now().unwrap().into();
53
37 let seconds = (then - now).num_seconds(); 54 let seconds = (then - now).num_seconds();
38 55
39 info!("measured = {}", seconds); 56 info!("measured = {}", seconds);
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index e8310866a..cedff772c 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -8,6 +8,7 @@ use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::gpio::{Level, Output, Speed}; 9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::mode::Blocking; 10use embassy_stm32::mode::Blocking;
11use embassy_stm32::spi::mode::Master;
11use embassy_stm32::spi::{self, Spi, Word}; 12use embassy_stm32::spi::{self, Spi, Word};
12use embassy_stm32::time::Hertz; 13use embassy_stm32::time::Hertz;
13 14
@@ -65,7 +66,7 @@ async fn main(_spawner: Spawner) {
65 cortex_m::asm::bkpt(); 66 cortex_m::asm::bkpt();
66} 67}
67 68
68fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>) 69fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>)
69where 70where
70 W: core::ops::Not<Output = W>, 71 W: core::ops::Not<Output = W>,
71{ 72{
@@ -109,7 +110,7 @@ where
109 spi.blocking_write::<u8>(&[]).unwrap(); 110 spi.blocking_write::<u8>(&[]).unwrap();
110} 111}
111 112
112fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>, mosi_out: &mut Output<'_>) 113fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>, mosi_out: &mut Output<'_>)
113where 114where
114 W: core::ops::Not<Output = W>, 115 W: core::ops::Not<Output = W>,
115{ 116{
@@ -125,7 +126,7 @@ where
125 spi.blocking_read::<u8>(&mut []).unwrap(); 126 spi.blocking_read::<u8>(&mut []).unwrap();
126} 127}
127 128
128fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>) 129fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>)
129where 130where
130 W: core::ops::Not<Output = W>, 131 W: core::ops::Not<Output = W>,
131{ 132{
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs
index b4fdb8faa..c8cd92401 100644
--- a/tests/stm32/src/bin/spi_dma.rs
+++ b/tests/stm32/src/bin/spi_dma.rs
@@ -8,6 +8,7 @@ use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::gpio::{Level, Output, Speed}; 9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::mode::Async; 10use embassy_stm32::mode::Async;
11use embassy_stm32::spi::mode::Master;
11use embassy_stm32::spi::{self, Spi, Word}; 12use embassy_stm32::spi::{self, Spi, Word};
12use embassy_stm32::time::Hertz; 13use embassy_stm32::time::Hertz;
13 14
@@ -78,7 +79,7 @@ async fn main(_spawner: Spawner) {
78 cortex_m::asm::bkpt(); 79 cortex_m::asm::bkpt();
79} 80}
80 81
81async fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>) 82async fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>)
82where 83where
83 W: core::ops::Not<Output = W>, 84 W: core::ops::Not<Output = W>,
84{ 85{
@@ -142,7 +143,7 @@ where
142 spi.write(&buf).await.unwrap(); 143 spi.write(&buf).await.unwrap();
143} 144}
144 145
145async fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>, mosi_out: &mut Output<'_>) 146async fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>, mosi_out: &mut Output<'_>)
146where 147where
147 W: core::ops::Not<Output = W>, 148 W: core::ops::Not<Output = W>,
148{ 149{
@@ -168,7 +169,7 @@ where
168 spi.blocking_read::<u8>(&mut []).unwrap(); 169 spi.blocking_read::<u8>(&mut []).unwrap();
169} 170}
170 171
171async fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>) 172async fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>)
172where 173where
173 W: core::ops::Not<Output = W>, 174 W: core::ops::Not<Output = W>,
174{ 175{
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs
index 833ca05d0..1fe65d867 100644
--- a/tests/stm32/src/bin/stop.rs
+++ b/tests/stm32/src/bin/stop.rs
@@ -10,11 +10,10 @@ use common::*;
10use cortex_m_rt::entry; 10use cortex_m_rt::entry;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_stm32::Config; 12use embassy_stm32::Config;
13use embassy_stm32::low_power::{Executor, StopMode, stop_ready, stop_with_rtc}; 13use embassy_stm32::low_power::{Executor, StopMode, stop_ready};
14use embassy_stm32::rcc::LsConfig; 14use embassy_stm32::rcc::LsConfig;
15use embassy_stm32::rtc::{Rtc, RtcConfig}; 15use embassy_stm32::rtc::Rtc;
16use embassy_time::Timer; 16use embassy_time::Timer;
17use static_cell::StaticCell;
18 17
19#[entry] 18#[entry]
20fn main() -> ! { 19fn main() -> ! {
@@ -50,6 +49,7 @@ async fn async_main(spawner: Spawner) {
50 49
51 let mut config = Config::default(); 50 let mut config = Config::default();
52 config.rcc.ls = LsConfig::default_lse(); 51 config.rcc.ls = LsConfig::default_lse();
52 config.rtc._disable_rtc = false;
53 53
54 // System Clock seems cannot be greater than 16 MHz 54 // System Clock seems cannot be greater than 16 MHz
55 #[cfg(any(feature = "stm32h563zi", feature = "stm32h503rb"))] 55 #[cfg(any(feature = "stm32h563zi", feature = "stm32h503rb"))]
@@ -66,14 +66,11 @@ async fn async_main(spawner: Spawner) {
66 .and_hms_opt(10, 30, 15) 66 .and_hms_opt(10, 30, 15)
67 .unwrap(); 67 .unwrap();
68 68
69 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 69 let (rtc, _time_provider) = Rtc::new(p.RTC);
70 70
71 rtc.set_datetime(now.into()).expect("datetime not set"); 71 critical_section::with(|cs| {
72 72 rtc.borrow_mut(cs).set_datetime(now.into()).expect("datetime not set");
73 static RTC: StaticCell<Rtc> = StaticCell::new(); 73 });
74 let rtc = RTC.init(rtc);
75
76 stop_with_rtc(rtc);
77 74
78 spawner.spawn(task_1().unwrap()); 75 spawner.spawn(task_1().unwrap());
79 spawner.spawn(task_2().unwrap()); 76 spawner.spawn(task_2().unwrap());
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 2bd934d6f..096cce947 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -468,6 +468,8 @@ pub fn config() -> Config {
468 config.rcc.apb3_pre = APBPrescaler::DIV1; 468 config.rcc.apb3_pre = APBPrescaler::DIV1;
469 config.rcc.sys = Sysclk::PLL1_P; 469 config.rcc.sys = Sysclk::PLL1_P;
470 config.rcc.voltage_scale = VoltageScale::Scale0; 470 config.rcc.voltage_scale = VoltageScale::Scale0;
471
472 config.rtc._disable_rtc = true;
471 } 473 }
472 474
473 #[cfg(feature = "stm32h503rb")] 475 #[cfg(feature = "stm32h503rb")]