aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreZio Pan <[email protected]>2023-12-22 00:19:00 +0800
committerGitHub <[email protected]>2023-12-22 00:19:00 +0800
commitd7e517e2d32c590e62e3e3339e191d19ce764c12 (patch)
tree3862995264a953b224557353bd37c38e83f92f95
parent05b8818de01866fa988a8f65a395690f02176b34 (diff)
parent87c03037e320ce30c0cd34fe97e0365e1b11aa9a (diff)
Merge branch 'main' into stm32f4-example-ws2812-spi
-rwxr-xr-x.github/ci/build-nightly.sh (renamed from .github/ci/build-stable.sh)5
-rwxr-xr-x.github/ci/rustfmt.sh12
-rwxr-xr-x.github/ci/test-nightly.sh13
-rwxr-xr-x.github/ci/test.sh3
-rw-r--r--.vscode/settings.json8
-rwxr-xr-xci-nightly.sh30
-rwxr-xr-xci.sh41
-rwxr-xr-xci_stable.sh77
-rw-r--r--cyw43-pio/README.md17
-rw-r--r--cyw43-pio/src/lib.rs26
-rw-r--r--cyw43/README.md4
-rw-r--r--cyw43/src/control.rs16
-rw-r--r--cyw43/src/lib.rs10
-rw-r--r--cyw43/src/runner.rs2
-rw-r--r--cyw43/src/structs.rs14
-rw-r--r--docs/modules/ROOT/examples/basic/src/main.rs1
-rw-r--r--docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml2
-rw-r--r--docs/modules/ROOT/examples/layer-by-layer/blinky-async/src/main.rs1
-rw-r--r--docs/modules/ROOT/pages/faq.adoc2
-rw-r--r--embassy-boot/boot/Cargo.toml13
-rw-r--r--embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs4
-rw-r--r--embassy-boot/boot/src/firmware_updater/asynch.rs17
-rw-r--r--embassy-boot/boot/src/firmware_updater/blocking.rs17
-rw-r--r--embassy-boot/boot/src/lib.rs8
-rw-r--r--embassy-boot/nrf/Cargo.toml8
-rw-r--r--embassy-boot/rp/Cargo.toml6
-rw-r--r--embassy-boot/stm32/Cargo.toml6
-rw-r--r--embassy-executor/Cargo.toml4
-rw-r--r--embassy-net-adin1110/Cargo.toml3
-rw-r--r--embassy-net-adin1110/src/crc32.rs8
-rw-r--r--embassy-net-adin1110/src/lib.rs7
-rw-r--r--embassy-net-adin1110/src/mdio.rs1
-rw-r--r--embassy-net-adin1110/src/regs.rs1
-rw-r--r--embassy-net-driver-channel/src/lib.rs58
-rw-r--r--embassy-net-esp-hosted/Cargo.toml7
-rw-r--r--embassy-net-esp-hosted/README.md27
-rw-r--r--embassy-net-esp-hosted/src/control.rs20
-rw-r--r--embassy-net-esp-hosted/src/lib.rs11
-rw-r--r--embassy-net-esp-hosted/src/proto.rs108
-rw-r--r--embassy-net-tuntap/Cargo.toml3
-rw-r--r--embassy-net-tuntap/src/lib.rs13
-rw-r--r--embassy-net-wiznet/Cargo.toml1
-rw-r--r--embassy-net-wiznet/src/chip/mod.rs2
-rw-r--r--embassy-net-wiznet/src/chip/w5100s.rs1
-rw-r--r--embassy-net-wiznet/src/chip/w5500.rs1
-rw-r--r--embassy-net-wiznet/src/lib.rs2
-rw-r--r--embassy-net/src/lib.rs6
-rw-r--r--embassy-nrf/Cargo.toml5
-rw-r--r--embassy-nrf/README.md2
-rw-r--r--embassy-nrf/src/gpio.rs25
-rw-r--r--embassy-nrf/src/lib.rs6
-rwxr-xr-xembassy-nrf/src/qspi.rs3
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-rp/README.md23
-rw-r--r--embassy-rp/src/adc.rs24
-rw-r--r--embassy-rp/src/clocks.rs119
-rw-r--r--embassy-rp/src/dma.rs20
-rw-r--r--embassy-rp/src/flash.rs42
-rw-r--r--embassy-rp/src/gpio.rs68
-rw-r--r--embassy-rp/src/i2c.rs22
-rw-r--r--embassy-rp/src/i2c_slave.rs3
-rw-r--r--embassy-rp/src/lib.rs14
-rw-r--r--embassy-rp/src/multicore.rs1
-rw-r--r--embassy-rp/src/pio/instr.rs (renamed from embassy-rp/src/pio_instr_util.rs)11
-rw-r--r--embassy-rp/src/pio/mod.rs (renamed from embassy-rp/src/pio.rs)152
-rw-r--r--embassy-rp/src/pwm.rs25
-rw-r--r--embassy-rp/src/rtc/mod.rs2
-rw-r--r--embassy-rp/src/spi.rs31
-rw-r--r--embassy-rp/src/timer.rs1
-rw-r--r--embassy-rp/src/uart/buffered.rs21
-rw-r--r--embassy-rp/src/uart/mod.rs61
-rw-r--r--embassy-rp/src/usb.rs11
-rw-r--r--embassy-stm32-wpan/Cargo.toml2
-rw-r--r--embassy-stm32/Cargo.toml5
-rw-r--r--embassy-stm32/build.rs20
-rw-r--r--embassy-stm32/src/adc/mod.rs8
-rw-r--r--embassy-stm32/src/adc/resolution.rs7
-rw-r--r--embassy-stm32/src/adc/v4.rs11
-rw-r--r--embassy-stm32/src/can/bxcan.rs97
-rw-r--r--embassy-stm32/src/can/fdcan.rs15
-rw-r--r--embassy-stm32/src/can/mod.rs1
-rw-r--r--embassy-stm32/src/crc/mod.rs1
-rw-r--r--embassy-stm32/src/crc/v1.rs4
-rw-r--r--embassy-stm32/src/crc/v2v3.rs13
-rw-r--r--embassy-stm32/src/dac/mod.rs23
-rw-r--r--embassy-stm32/src/dac/tsel.rs2
-rw-r--r--embassy-stm32/src/dcmi.rs25
-rw-r--r--embassy-stm32/src/dma/bdma.rs86
-rw-r--r--embassy-stm32/src/dma/dma.rs110
-rw-r--r--embassy-stm32/src/dma/dmamux.rs4
-rw-r--r--embassy-stm32/src/dma/gpdma.rs18
-rw-r--r--embassy-stm32/src/dma/mod.rs9
-rw-r--r--embassy-stm32/src/dma/word.rs10
-rw-r--r--embassy-stm32/src/eth/generic_smi.rs1
-rw-r--r--embassy-stm32/src/eth/mod.rs26
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs2
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs3
-rw-r--r--embassy-stm32/src/exti.rs51
-rw-r--r--embassy-stm32/src/flash/asynch.rs19
-rw-r--r--embassy-stm32/src/flash/common.rs33
-rw-r--r--embassy-stm32/src/flash/f0.rs4
-rw-r--r--embassy-stm32/src/flash/f3.rs4
-rw-r--r--embassy-stm32/src/flash/f4.rs2
-rw-r--r--embassy-stm32/src/flash/f7.rs4
-rw-r--r--embassy-stm32/src/flash/g.rs4
-rw-r--r--embassy-stm32/src/flash/h7.rs4
-rw-r--r--embassy-stm32/src/flash/l.rs4
-rw-r--r--embassy-stm32/src/flash/mod.rs63
-rw-r--r--embassy-stm32/src/flash/other.rs4
-rw-r--r--embassy-stm32/src/fmc.rs5
-rw-r--r--embassy-stm32/src/gpio.rs83
-rw-r--r--embassy-stm32/src/hrtim/mod.rs77
-rw-r--r--embassy-stm32/src/hrtim/traits.rs6
-rw-r--r--embassy-stm32/src/i2c/mod.rs170
-rw-r--r--embassy-stm32/src/i2c/v1.rs151
-rw-r--r--embassy-stm32/src/i2c/v2.rs460
-rw-r--r--embassy-stm32/src/i2s.rs36
-rw-r--r--embassy-stm32/src/ipcc.rs8
-rw-r--r--embassy-stm32/src/lib.rs26
-rw-r--r--embassy-stm32/src/low_power.rs107
-rw-r--r--embassy-stm32/src/opamp.rs9
-rw-r--r--embassy-stm32/src/qspi/enums.rs43
-rw-r--r--embassy-stm32/src/qspi/mod.rs17
-rw-r--r--embassy-stm32/src/rcc/mod.rs3
-rw-r--r--embassy-stm32/src/rng.rs17
-rw-r--r--embassy-stm32/src/rtc/datetime.rs12
-rw-r--r--embassy-stm32/src/rtc/mod.rs20
-rw-r--r--embassy-stm32/src/sai/mod.rs540
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs92
-rw-r--r--embassy-stm32/src/spi/mod.rs47
-rw-r--r--embassy-stm32/src/time.rs3
-rw-r--r--embassy-stm32/src/time_driver.rs19
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs33
-rw-r--r--embassy-stm32/src/timer/mod.rs161
-rw-r--r--embassy-stm32/src/timer/qei.rs25
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs47
-rw-r--r--embassy-stm32/src/traits.rs30
-rw-r--r--embassy-stm32/src/uid.rs2
-rw-r--r--embassy-stm32/src/usart/buffered.rs12
-rw-r--r--embassy-stm32/src/usart/mod.rs55
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs9
-rw-r--r--embassy-stm32/src/usb/mod.rs4
-rw-r--r--embassy-stm32/src/usb/usb.rs7
-rw-r--r--embassy-stm32/src/usb_otg/mod.rs4
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs13
-rw-r--r--embassy-stm32/src/wdg/mod.rs5
-rw-r--r--embassy-sync/src/signal.rs14
-rw-r--r--embassy-time/src/driver.rs4
-rw-r--r--embassy-time/src/timer.rs7
-rw-r--r--embassy-usb-dfu/README.md20
-rw-r--r--embassy-usb-dfu/src/application.rs1
-rw-r--r--embassy-usb-dfu/src/consts.rs12
-rw-r--r--embassy-usb-dfu/src/dfu.rs (renamed from embassy-usb-dfu/src/bootloader.rs)1
-rw-r--r--embassy-usb-dfu/src/lib.rs11
-rw-r--r--embassy-usb-logger/README.md14
-rw-r--r--examples/boot/application/nrf/Cargo.toml2
-rw-r--r--examples/boot/application/nrf/src/bin/a.rs1
-rw-r--r--examples/boot/application/nrf/src/bin/b.rs1
-rw-r--r--examples/boot/application/rp/Cargo.toml2
-rw-r--r--examples/boot/application/rp/src/bin/a.rs1
-rw-r--r--examples/boot/application/rp/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32f3/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f3/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32f3/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32f7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f7/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32f7/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32h7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32h7/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32h7/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32l0/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l0/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32l0/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32l1/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l1/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32l1/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32l4/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l4/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32l4/src/bin/b.rs1
-rw-r--r--examples/boot/application/stm32wb-dfu/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wb-dfu/src/main.rs1
-rw-r--r--examples/boot/application/stm32wl/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wl/src/bin/a.rs1
-rw-r--r--examples/boot/application/stm32wl/src/bin/b.rs1
-rw-r--r--examples/nrf-rtos-trace/src/bin/rtos_trace.rs1
-rw-r--r--examples/nrf52840/Cargo.toml6
-rw-r--r--examples/nrf52840/src/bin/blinky.rs1
-rw-r--r--examples/nrf52840/src/bin/buffered_uart.rs1
-rw-r--r--examples/nrf52840/src/bin/channel.rs1
-rw-r--r--examples/nrf52840/src/bin/channel_sender_receiver.rs1
-rw-r--r--examples/nrf52840/src/bin/ethernet_enc28j60.rs18
-rw-r--r--examples/nrf52840/src/bin/executor_fairness_test.rs1
-rw-r--r--examples/nrf52840/src/bin/gpiote_channel.rs1
-rw-r--r--examples/nrf52840/src/bin/gpiote_port.rs1
-rw-r--r--examples/nrf52840/src/bin/i2s_effect.rs1
-rw-r--r--examples/nrf52840/src/bin/i2s_monitor.rs1
-rw-r--r--examples/nrf52840/src/bin/i2s_waveform.rs1
-rw-r--r--examples/nrf52840/src/bin/manually_create_executor.rs1
-rw-r--r--examples/nrf52840/src/bin/multiprio.rs1
-rw-r--r--examples/nrf52840/src/bin/mutex.rs1
-rw-r--r--examples/nrf52840/src/bin/nvmc.rs1
-rw-r--r--examples/nrf52840/src/bin/pdm.rs1
-rw-r--r--examples/nrf52840/src/bin/pdm_continuous.rs1
-rw-r--r--examples/nrf52840/src/bin/ppi.rs1
-rw-r--r--examples/nrf52840/src/bin/pubsub.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm_double_sequence.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ppi.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs1
-rw-r--r--examples/nrf52840/src/bin/pwm_servo.rs1
-rw-r--r--examples/nrf52840/src/bin/qdec.rs1
-rw-r--r--examples/nrf52840/src/bin/qspi.rs1
-rw-r--r--examples/nrf52840/src/bin/qspi_lowpower.rs1
-rw-r--r--examples/nrf52840/src/bin/rng.rs1
-rw-r--r--examples/nrf52840/src/bin/saadc.rs1
-rw-r--r--examples/nrf52840/src/bin/saadc_continuous.rs1
-rw-r--r--examples/nrf52840/src/bin/self_spawn.rs1
-rw-r--r--examples/nrf52840/src/bin/self_spawn_current_executor.rs1
-rw-r--r--examples/nrf52840/src/bin/spim.rs1
-rw-r--r--examples/nrf52840/src/bin/spis.rs1
-rw-r--r--examples/nrf52840/src/bin/temp.rs1
-rw-r--r--examples/nrf52840/src/bin/timer.rs1
-rw-r--r--examples/nrf52840/src/bin/twim.rs1
-rw-r--r--examples/nrf52840/src/bin/twim_lowpower.rs1
-rw-r--r--examples/nrf52840/src/bin/twis.rs1
-rw-r--r--examples/nrf52840/src/bin/uart.rs1
-rw-r--r--examples/nrf52840/src/bin/uart_idle.rs1
-rw-r--r--examples/nrf52840/src/bin/uart_split.rs1
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs33
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs1
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs1
-rw-r--r--examples/nrf52840/src/bin/usb_serial.rs1
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs21
-rw-r--r--examples/nrf52840/src/bin/usb_serial_winusb.rs1
-rw-r--r--examples/nrf52840/src/bin/wdt.rs1
-rw-r--r--examples/nrf52840/src/bin/wifi_esp_hosted.rs14
-rw-r--r--examples/nrf5340/Cargo.toml4
-rw-r--r--examples/nrf5340/src/bin/blinky.rs1
-rw-r--r--examples/nrf5340/src/bin/gpiote_channel.rs1
-rw-r--r--examples/nrf5340/src/bin/uart.rs1
-rw-r--r--examples/rp/Cargo.toml4
-rw-r--r--examples/rp/src/bin/adc.rs1
-rw-r--r--examples/rp/src/bin/blinky.rs1
-rw-r--r--examples/rp/src/bin/button.rs1
-rw-r--r--examples/rp/src/bin/ethernet_w5500_multisocket.rs14
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs14
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_server.rs14
-rw-r--r--examples/rp/src/bin/ethernet_w5500_udp.rs14
-rw-r--r--examples/rp/src/bin/flash.rs1
-rw-r--r--examples/rp/src/bin/gpio_async.rs1
-rw-r--r--examples/rp/src/bin/gpout.rs1
-rw-r--r--examples/rp/src/bin/i2c_async.rs1
-rw-r--r--examples/rp/src/bin/i2c_blocking.rs1
-rw-r--r--examples/rp/src/bin/i2c_slave.rs1
-rw-r--r--examples/rp/src/bin/multicore.rs1
-rw-r--r--examples/rp/src/bin/multiprio.rs1
-rw-r--r--examples/rp/src/bin/pio_async.rs1
-rw-r--r--examples/rp/src/bin/pio_dma.rs1
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs1
-rw-r--r--examples/rp/src/bin/pio_rotary_encoder.rs1
-rw-r--r--examples/rp/src/bin/pio_stepper.rs1
-rw-r--r--examples/rp/src/bin/pio_uart.rs1
-rw-r--r--examples/rp/src/bin/pio_ws2812.rs1
-rw-r--r--examples/rp/src/bin/pwm.rs1
-rw-r--r--examples/rp/src/bin/pwm_input.rs1
-rw-r--r--examples/rp/src/bin/rosc.rs1
-rw-r--r--examples/rp/src/bin/rtc.rs1
-rw-r--r--examples/rp/src/bin/spi.rs1
-rw-r--r--examples/rp/src/bin/spi_async.rs1
-rw-r--r--examples/rp/src/bin/spi_display.rs1
-rw-r--r--examples/rp/src/bin/uart.rs1
-rw-r--r--examples/rp/src/bin/uart_buffered_split.rs9
-rw-r--r--examples/rp/src/bin/uart_unidir.rs1
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs29
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs1
-rw-r--r--examples/rp/src/bin/usb_logger.rs1
-rw-r--r--examples/rp/src/bin/usb_midi.rs1
-rw-r--r--examples/rp/src/bin/usb_raw.rs1
-rw-r--r--examples/rp/src/bin/usb_raw_bulk.rs1
-rw-r--r--examples/rp/src/bin/usb_serial.rs1
-rw-r--r--examples/rp/src/bin/watchdog.rs1
-rw-r--r--examples/rp/src/bin/wifi_ap_tcp_server.rs14
-rw-r--r--examples/rp/src/bin/wifi_blinky.rs6
-rw-r--r--examples/rp/src/bin/wifi_scan.rs6
-rw-r--r--examples/rp/src/bin/wifi_tcp_server.rs14
-rw-r--r--examples/std/Cargo.toml4
-rw-r--r--examples/std/src/bin/net.rs12
-rw-r--r--examples/std/src/bin/net_dns.rs12
-rw-r--r--examples/std/src/bin/net_ppp.rs14
-rw-r--r--examples/std/src/bin/net_udp.rs12
-rw-r--r--examples/std/src/bin/serial.rs2
-rw-r--r--examples/std/src/bin/tcp_accept.rs12
-rw-r--r--examples/std/src/bin/tick.rs2
-rw-r--r--examples/stm32c0/Cargo.toml2
-rw-r--r--examples/stm32c0/src/bin/blinky.rs1
-rw-r--r--examples/stm32c0/src/bin/button.rs1
-rw-r--r--examples/stm32c0/src/bin/button_exti.rs1
-rw-r--r--examples/stm32f0/Cargo.toml4
-rw-r--r--examples/stm32f0/src/bin/adc.rs1
-rw-r--r--examples/stm32f0/src/bin/blinky.rs1
-rw-r--r--examples/stm32f0/src/bin/button_controlled_blink.rs1
-rw-r--r--examples/stm32f0/src/bin/button_exti.rs1
-rw-r--r--examples/stm32f0/src/bin/hello.rs1
-rw-r--r--examples/stm32f0/src/bin/multiprio.rs1
-rw-r--r--examples/stm32f0/src/bin/wdg.rs1
-rw-r--r--examples/stm32f1/Cargo.toml2
-rw-r--r--examples/stm32f1/src/bin/adc.rs1
-rw-r--r--examples/stm32f1/src/bin/blinky.rs1
-rw-r--r--examples/stm32f1/src/bin/can.rs1
-rw-r--r--examples/stm32f1/src/bin/hello.rs1
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32f2/Cargo.toml2
-rw-r--r--examples/stm32f2/src/bin/blinky.rs1
-rw-r--r--examples/stm32f2/src/bin/pll.rs1
-rw-r--r--examples/stm32f3/Cargo.toml4
-rw-r--r--examples/stm32f3/src/bin/blinky.rs1
-rw-r--r--examples/stm32f3/src/bin/button.rs1
-rw-r--r--examples/stm32f3/src/bin/button_events.rs1
-rw-r--r--examples/stm32f3/src/bin/button_exti.rs1
-rw-r--r--examples/stm32f3/src/bin/flash.rs1
-rw-r--r--examples/stm32f3/src/bin/hello.rs1
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs1
-rw-r--r--examples/stm32f3/src/bin/spi_dma.rs1
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32f334/Cargo.toml4
-rw-r--r--examples/stm32f334/src/bin/adc.rs1
-rw-r--r--examples/stm32f334/src/bin/button.rs1
-rw-r--r--examples/stm32f334/src/bin/hello.rs1
-rw-r--r--examples/stm32f334/src/bin/opamp.rs1
-rw-r--r--examples/stm32f334/src/bin/pwm.rs1
-rw-r--r--examples/stm32f4/Cargo.toml6
-rw-r--r--examples/stm32f4/src/bin/adc.rs1
-rw-r--r--examples/stm32f4/src/bin/blinky.rs1
-rw-r--r--examples/stm32f4/src/bin/button.rs1
-rw-r--r--examples/stm32f4/src/bin/button_exti.rs1
-rw-r--r--examples/stm32f4/src/bin/can.rs1
-rw-r--r--examples/stm32f4/src/bin/dac.rs1
-rw-r--r--examples/stm32f4/src/bin/eth.rs14
-rw-r--r--examples/stm32f4/src/bin/flash.rs7
-rw-r--r--examples/stm32f4/src/bin/flash_async.rs7
-rw-r--r--examples/stm32f4/src/bin/hello.rs1
-rw-r--r--examples/stm32f4/src/bin/i2c.rs1
-rw-r--r--examples/stm32f4/src/bin/i2c_async.rs1
-rw-r--r--examples/stm32f4/src/bin/i2c_comparison.rs1
-rw-r--r--examples/stm32f4/src/bin/i2s_dma.rs1
-rw-r--r--examples/stm32f4/src/bin/mco.rs1
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs1
-rw-r--r--examples/stm32f4/src/bin/pwm.rs1
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs1
-rw-r--r--examples/stm32f4/src/bin/rtc.rs1
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs1
-rw-r--r--examples/stm32f4/src/bin/spi.rs1
-rw-r--r--examples/stm32f4/src/bin/spi_dma.rs1
-rw-r--r--examples/stm32f4/src/bin/usart.rs1
-rw-r--r--examples/stm32f4/src/bin/usart_buffered.rs1
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs32
-rw-r--r--examples/stm32f4/src/bin/usb_raw.rs1
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32f4/src/bin/wdt.rs1
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm_dma.rs3
-rw-r--r--examples/stm32f7/Cargo.toml4
-rw-r--r--examples/stm32f7/src/bin/adc.rs1
-rw-r--r--examples/stm32f7/src/bin/blinky.rs1
-rw-r--r--examples/stm32f7/src/bin/button.rs1
-rw-r--r--examples/stm32f7/src/bin/button_exti.rs1
-rw-r--r--examples/stm32f7/src/bin/can.rs8
-rw-r--r--examples/stm32f7/src/bin/eth.rs14
-rw-r--r--examples/stm32f7/src/bin/flash.rs1
-rw-r--r--examples/stm32f7/src/bin/hello.rs1
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs1
-rw-r--r--examples/stm32f7/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32g0/Cargo.toml2
-rw-r--r--examples/stm32g0/src/bin/blinky.rs1
-rw-r--r--examples/stm32g0/src/bin/button.rs1
-rw-r--r--examples/stm32g0/src/bin/button_exti.rs1
-rw-r--r--examples/stm32g0/src/bin/flash.rs1
-rw-r--r--examples/stm32g0/src/bin/spi_neopixel.rs1
-rw-r--r--examples/stm32g4/Cargo.toml2
-rw-r--r--examples/stm32g4/src/bin/adc.rs1
-rw-r--r--examples/stm32g4/src/bin/blinky.rs1
-rw-r--r--examples/stm32g4/src/bin/button.rs1
-rw-r--r--examples/stm32g4/src/bin/button_exti.rs1
-rw-r--r--examples/stm32g4/src/bin/pll.rs1
-rw-r--r--examples/stm32g4/src/bin/pwm.rs1
-rw-r--r--examples/stm32g4/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32h5/Cargo.toml4
-rw-r--r--examples/stm32h5/src/bin/blinky.rs1
-rw-r--r--examples/stm32h5/src/bin/button_exti.rs1
-rw-r--r--examples/stm32h5/src/bin/eth.rs14
-rw-r--r--examples/stm32h5/src/bin/i2c.rs1
-rw-r--r--examples/stm32h5/src/bin/rng.rs1
-rw-r--r--examples/stm32h5/src/bin/usart.rs1
-rw-r--r--examples/stm32h5/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32h5/src/bin/usart_split.rs1
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32h7/Cargo.toml4
-rw-r--r--examples/stm32h7/src/bin/adc.rs1
-rw-r--r--examples/stm32h7/src/bin/blinky.rs1
-rw-r--r--examples/stm32h7/src/bin/button_exti.rs1
-rw-r--r--examples/stm32h7/src/bin/camera.rs1
-rw-r--r--examples/stm32h7/src/bin/dac.rs1
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs1
-rw-r--r--examples/stm32h7/src/bin/eth.rs14
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs14
-rw-r--r--examples/stm32h7/src/bin/flash.rs1
-rw-r--r--examples/stm32h7/src/bin/fmc.rs1
-rw-r--r--examples/stm32h7/src/bin/i2c.rs1
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs11
-rw-r--r--examples/stm32h7/src/bin/mco.rs1
-rw-r--r--examples/stm32h7/src/bin/pwm.rs1
-rw-r--r--examples/stm32h7/src/bin/rng.rs1
-rw-r--r--examples/stm32h7/src/bin/rtc.rs1
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs1
-rw-r--r--examples/stm32h7/src/bin/signal.rs1
-rw-r--r--examples/stm32h7/src/bin/spi.rs1
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs1
-rw-r--r--examples/stm32h7/src/bin/usart.rs1
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs1
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32h7/src/bin/wdg.rs1
-rw-r--r--examples/stm32l0/Cargo.toml4
-rw-r--r--examples/stm32l0/src/bin/blinky.rs1
-rw-r--r--examples/stm32l0/src/bin/button.rs1
-rw-r--r--examples/stm32l0/src/bin/button_exti.rs1
-rw-r--r--examples/stm32l0/src/bin/flash.rs1
-rw-r--r--examples/stm32l0/src/bin/spi.rs1
-rw-r--r--examples/stm32l0/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32l0/src/bin/usart_irq.rs1
-rw-r--r--examples/stm32l1/Cargo.toml2
-rw-r--r--examples/stm32l1/src/bin/blinky.rs1
-rw-r--r--examples/stm32l1/src/bin/flash.rs1
-rw-r--r--examples/stm32l1/src/bin/spi.rs1
-rw-r--r--examples/stm32l4/Cargo.toml4
-rw-r--r--examples/stm32l4/src/bin/adc.rs1
-rw-r--r--examples/stm32l4/src/bin/blinky.rs1
-rw-r--r--examples/stm32l4/src/bin/button.rs1
-rw-r--r--examples/stm32l4/src/bin/button_exti.rs1
-rw-r--r--examples/stm32l4/src/bin/dac.rs1
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs1
-rw-r--r--examples/stm32l4/src/bin/i2c.rs1
-rw-r--r--examples/stm32l4/src/bin/i2c_blocking_async.rs1
-rw-r--r--examples/stm32l4/src/bin/i2c_dma.rs1
-rw-r--r--examples/stm32l4/src/bin/mco.rs1
-rw-r--r--examples/stm32l4/src/bin/rng.rs1
-rw-r--r--examples/stm32l4/src/bin/rtc.rs1
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs20
-rw-r--r--examples/stm32l4/src/bin/spi.rs1
-rw-r--r--examples/stm32l4/src/bin/spi_blocking_async.rs1
-rw-r--r--examples/stm32l4/src/bin/spi_dma.rs1
-rw-r--r--examples/stm32l4/src/bin/usart.rs1
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs1
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32l5/Cargo.toml4
-rw-r--r--examples/stm32l5/src/bin/button_exti.rs1
-rw-r--r--examples/stm32l5/src/bin/rng.rs1
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs29
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs1
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32u5/Cargo.toml2
-rw-r--r--examples/stm32u5/src/bin/blinky.rs1
-rw-r--r--examples/stm32u5/src/bin/boot.rs1
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs1
-rw-r--r--examples/stm32wb/Cargo.toml4
-rw-r--r--examples/stm32wb/src/bin/blinky.rs1
-rw-r--r--examples/stm32wb/src/bin/button_exti.rs1
-rw-r--r--examples/stm32wb/src/bin/eddystone_beacon.rs1
-rw-r--r--examples/stm32wb/src/bin/gatt_server.rs1
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs1
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs21
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs1
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs1
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_ble.rs1
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs1
-rw-r--r--examples/stm32wba/Cargo.toml4
-rw-r--r--examples/stm32wba/src/bin/blinky.rs1
-rw-r--r--examples/stm32wba/src/bin/button_exti.rs1
-rw-r--r--examples/stm32wl/Cargo.toml2
-rw-r--r--examples/stm32wl/src/bin/blinky.rs1
-rw-r--r--examples/stm32wl/src/bin/button.rs1
-rw-r--r--examples/stm32wl/src/bin/button_exti.rs1
-rw-r--r--examples/stm32wl/src/bin/flash.rs1
-rw-r--r--examples/stm32wl/src/bin/random.rs1
-rw-r--r--examples/stm32wl/src/bin/rtc.rs1
-rw-r--r--examples/stm32wl/src/bin/uart_async.rs1
-rw-r--r--examples/wasm/Cargo.toml2
-rw-r--r--examples/wasm/src/lib.rs2
-rw-r--r--rust-toolchain-nightly.toml12
-rw-r--r--rust-toolchain.toml8
-rw-r--r--tests/nrf/Cargo.toml2
-rw-r--r--tests/nrf/src/bin/ethernet_enc28j60_perf.rs11
-rw-r--r--tests/nrf/src/bin/wifi_esp_hosted_perf.rs14
-rw-r--r--tests/rp/Cargo.toml2
-rw-r--r--tests/rp/src/bin/cyw43-perf.rs14
-rw-r--r--tests/rp/src/bin/ethernet_w5100s_perf.rs14
-rw-r--r--tests/stm32/Cargo.toml2
-rw-r--r--tests/stm32/src/bin/eth.rs14
-rw-r--r--tests/stm32/src/bin/stop.rs6
502 files changed, 3336 insertions, 2112 deletions
diff --git a/.github/ci/build-stable.sh b/.github/ci/build-nightly.sh
index e0bd77867..95cb4100c 100755
--- a/.github/ci/build-stable.sh
+++ b/.github/ci/build-nightly.sh
@@ -7,6 +7,7 @@ set -euo pipefail
7export RUSTUP_HOME=/ci/cache/rustup 7export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo 8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target 9export CARGO_TARGET_DIR=/ci/cache/target
10mv rust-toolchain-nightly.toml rust-toolchain.toml
10 11
11# needed for "dumb HTTP" transport support 12# needed for "dumb HTTP" transport support
12# used when pointing stm32-metapac to a CI-built one. 13# used when pointing stm32-metapac to a CI-built one.
@@ -21,9 +22,7 @@ fi
21hashtime restore /ci/cache/filetime.json || true 22hashtime restore /ci/cache/filetime.json || true
22hashtime save /ci/cache/filetime.json 23hashtime save /ci/cache/filetime.json
23 24
24sed -i 's/channel.*/channel = "beta"/g' rust-toolchain.toml 25./ci-nightly.sh
25
26./ci_stable.sh
27 26
28# Save lockfiles 27# Save lockfiles
29echo Saving lockfiles... 28echo Saving lockfiles...
diff --git a/.github/ci/rustfmt.sh b/.github/ci/rustfmt.sh
new file mode 100755
index 000000000..369239cfe
--- /dev/null
+++ b/.github/ci/rustfmt.sh
@@ -0,0 +1,12 @@
1#!/bin/bash
2## on push branch~=gh-readonly-queue/main/.*
3## on pull_request
4
5set -euo pipefail
6
7export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target
10mv rust-toolchain-nightly.toml rust-toolchain.toml
11
12find . -name '*.rs' -not -path '*target*' | xargs rustfmt --check --skip-children --unstable-features --edition 2021
diff --git a/.github/ci/test-nightly.sh b/.github/ci/test-nightly.sh
new file mode 100755
index 000000000..d6e5dc574
--- /dev/null
+++ b/.github/ci/test-nightly.sh
@@ -0,0 +1,13 @@
1#!/bin/bash
2## on push branch~=gh-readonly-queue/main/.*
3## on pull_request
4
5set -euo pipefail
6
7export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target
10mv rust-toolchain-nightly.toml rust-toolchain.toml
11
12MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml
13MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly
diff --git a/.github/ci/test.sh b/.github/ci/test.sh
index 0ec65d2a1..369f6d221 100755
--- a/.github/ci/test.sh
+++ b/.github/ci/test.sh
@@ -8,9 +8,6 @@ export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo 8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target 9export CARGO_TARGET_DIR=/ci/cache/target
10 10
11MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml
12MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly
13
14cargo test --manifest-path ./embassy-sync/Cargo.toml 11cargo test --manifest-path ./embassy-sync/Cargo.toml
15cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml 12cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
16cargo test --manifest-path ./embassy-hal-internal/Cargo.toml 13cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d46ce603b..a5b23175a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -15,14 +15,10 @@
15 //"rust-analyzer.cargo.target": "thumbv7m-none-eabi", 15 //"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
16 "rust-analyzer.cargo.target": "thumbv7em-none-eabi", 16 "rust-analyzer.cargo.target": "thumbv7em-none-eabi",
17 //"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf", 17 //"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
18 "rust-analyzer.cargo.features": [
19 // Uncomment if the example has a "nightly" feature.
20 "nightly",
21 ],
22 "rust-analyzer.linkedProjects": [ 18 "rust-analyzer.linkedProjects": [
23 // Uncomment ONE line for the chip you want to work on. 19 // Uncomment ONE line for the chip you want to work on.
24 // This makes rust-analyzer work on the example crate and all its dependencies. 20 // This makes rust-analyzer work on the example crate and all its dependencies.
25 "examples/nrf52840/Cargo.toml", 21 "examples/stm32l4/Cargo.toml",
26 // "examples/nrf52840-rtic/Cargo.toml", 22 // "examples/nrf52840-rtic/Cargo.toml",
27 // "examples/nrf5340/Cargo.toml", 23 // "examples/nrf5340/Cargo.toml",
28 // "examples/nrf-rtos-trace/Cargo.toml", 24 // "examples/nrf-rtos-trace/Cargo.toml",
@@ -49,4 +45,4 @@
49 // "examples/stm32wl/Cargo.toml", 45 // "examples/stm32wl/Cargo.toml",
50 // "examples/wasm/Cargo.toml", 46 // "examples/wasm/Cargo.toml",
51 ], 47 ],
52} \ No newline at end of file 48}
diff --git a/ci-nightly.sh b/ci-nightly.sh
new file mode 100755
index 000000000..1fc9692b5
--- /dev/null
+++ b/ci-nightly.sh
@@ -0,0 +1,30 @@
1#!/bin/bash
2
3set -eo pipefail
4
5export RUSTFLAGS=-Dwarnings
6export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info
7if [[ -z "${CARGO_TARGET_DIR}" ]]; then
8 export CARGO_TARGET_DIR=target_ci
9fi
10
11cargo batch \
12 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly \
13 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \
14 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \
15 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \
16 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
17 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \
18 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \
19 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \
20 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \
21 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \
22 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \
23 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \
24 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
25 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \
26 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \
27 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \
28 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \
29 --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \
30
diff --git a/ci.sh b/ci.sh
index 83c05d1b9..933e54a80 100755
--- a/ci.sh
+++ b/ci.sh
@@ -15,26 +15,24 @@ if [ $TARGET = "x86_64-unknown-linux-gnu" ]; then
15 BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --out-dir out/examples/std" 15 BUILD_EXTRA="--- build --release --manifest-path examples/std/Cargo.toml --target $TARGET --out-dir out/examples/std"
16fi 16fi
17 17
18find . -name '*.rs' -not -path '*target*' | xargs rustfmt --check --skip-children --unstable-features --edition 2021
19
20cargo batch \ 18cargo batch \
21 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly \ 19 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \
22 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \ 20 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \
23 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \ 21 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \
24 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \ 22 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \
25 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \ 23 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
26 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \ 24 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m \
27 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \ 25 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,integrated-timers \
28 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \ 26 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread \
29 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \ 27 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,integrated-timers \
30 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \ 28 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt \
31 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \ 29 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-interrupt,integrated-timers \
32 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \ 30 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt \
33 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \ 31 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
34 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \ 32 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32 \
35 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \ 33 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,integrated-timers \
36 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \ 34 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread \
37 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \ 35 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features arch-riscv32,executor-thread,integrated-timers \
38 --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \ 36 --- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features defmt \
39 --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \ 37 --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \
40 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ 38 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \
@@ -91,12 +89,12 @@ cargo batch \
91 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \ 89 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \
92 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \ 90 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \
93 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \ 91 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \
94 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,embedded-sdmmc,time \ 92 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
95 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \ 93 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \
96 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \ 94 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \
97 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \ 95 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \
98 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \ 96 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \
99 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,embedded-sdmmc,time \ 97 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \
100 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \ 98 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \
101 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \ 99 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \
102 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \ 100 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \
@@ -140,7 +138,6 @@ cargo batch \
140 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \ 138 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-irq/Cargo.toml --target thumbv7em-none-eabi \
141 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \ 139 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml --target thumbv7em-none-eabi \
142 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \ 140 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840 \
143 --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \
144 --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \ 141 --- build --release --manifest-path examples/nrf5340/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/nrf5340 \
145 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ 142 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \
146 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ 143 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \
diff --git a/ci_stable.sh b/ci_stable.sh
deleted file mode 100755
index 66ed8f79d..000000000
--- a/ci_stable.sh
+++ /dev/null
@@ -1,77 +0,0 @@
1#!/bin/bash
2
3set -euo pipefail
4
5export RUSTFLAGS=-Dwarnings
6export DEFMT_LOG=trace
7
8cargo batch \
9 --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \
10 --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns \
11 --- build --release --manifest-path embassy-boot/rp/Cargo.toml --target thumbv6m-none-eabi \
12 --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \
13 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi \
14 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features log \
15 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features defmt \
16 --- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \
17 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \
18 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \
19 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
20 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time-driver-rtc1 \
21 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time-driver-rtc1 \
22 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time-driver-rtc1 \
23 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52820,gpiote,time-driver-rtc1 \
24 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52832,gpiote,time-driver-rtc1 \
25 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52833,gpiote,time-driver-rtc1 \
26 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-s,gpiote,time-driver-rtc1 \
27 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf9160-ns,gpiote,time-driver-rtc1 \
28 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-s,gpiote,time-driver-rtc1 \
29 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-app-ns,gpiote,time-driver-rtc1 \
30 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features nrf5340-net,gpiote,time-driver-rtc1 \
31 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,gpiote,time-driver-rtc1 \
32 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,log,gpiote,time-driver-rtc1 \
33 --- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52840,defmt,gpiote,time-driver-rtc1 \
34 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features defmt \
35 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features log \
36 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi \
37 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features qspi-as-gpio \
38 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any \
39 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any \
40 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any \
41 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any \
42 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any \
43 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any,time \
44 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any,time \
45 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,time \
46 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,time \
47 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,time \
48 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,time \
49 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,time \
50 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,time \
51 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,time \
52 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,time \
53 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,time \
54 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,time \
55 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,time \
56 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,time \
57 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,time \
58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,time \
59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,time \
60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,time \
61 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,time \
62 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \
63 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \
64 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
65 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
66 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
67 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
68 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
69 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
70 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \
71 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \
72 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \
73 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \
74 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \
75 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \
76 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf52840 --bin raw_spawn \
77 --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \
diff --git a/cyw43-pio/README.md b/cyw43-pio/README.md
new file mode 100644
index 000000000..2b22db360
--- /dev/null
+++ b/cyw43-pio/README.md
@@ -0,0 +1,17 @@
1# cyw43-pio
2
3RP2040 PIO driver for the nonstandard half-duplex SPI used in the Pico W. The PIO driver offloads SPI communication with the WiFi chip and improves throughput.
4
5## Minimum supported Rust version (MSRV)
6
7Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
8
9## License
10
11This work is licensed under either of
12
13- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
14 <http://www.apache.org/licenses/LICENSE-2.0>)
15- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
16
17at your option.
diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs
index 41b670324..5efab10e4 100644
--- a/cyw43-pio/src/lib.rs
+++ b/cyw43-pio/src/lib.rs
@@ -1,16 +1,19 @@
1#![no_std] 1#![no_std]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
3 5
4use core::slice; 6use core::slice;
5 7
6use cyw43::SpiBusCyw43; 8use cyw43::SpiBusCyw43;
7use embassy_rp::dma::Channel; 9use embassy_rp::dma::Channel;
8use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate}; 10use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate};
9use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine}; 11use embassy_rp::pio::{instr, Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine};
10use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef}; 12use embassy_rp::{Peripheral, PeripheralRef};
11use fixed::FixedU32; 13use fixed::FixedU32;
12use pio_proc::pio_asm; 14use pio_proc::pio_asm;
13 15
16/// SPI comms driven by PIO.
14pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> { 17pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> {
15 cs: Output<'d, CS>, 18 cs: Output<'d, CS>,
16 sm: StateMachine<'d, PIO, SM>, 19 sm: StateMachine<'d, PIO, SM>,
@@ -25,6 +28,7 @@ where
25 CS: Pin, 28 CS: Pin,
26 PIO: Instance, 29 PIO: Instance,
27{ 30{
31 /// Create a new instance of PioSpi.
28 pub fn new<DIO, CLK>( 32 pub fn new<DIO, CLK>(
29 common: &mut Common<'d, PIO>, 33 common: &mut Common<'d, PIO>,
30 mut sm: StateMachine<'d, PIO, SM>, 34 mut sm: StateMachine<'d, PIO, SM>,
@@ -143,6 +147,7 @@ where
143 } 147 }
144 } 148 }
145 149
150 /// Write data to peripheral and return status.
146 pub async fn write(&mut self, write: &[u32]) -> u32 { 151 pub async fn write(&mut self, write: &[u32]) -> u32 {
147 self.sm.set_enable(false); 152 self.sm.set_enable(false);
148 let write_bits = write.len() * 32 - 1; 153 let write_bits = write.len() * 32 - 1;
@@ -152,10 +157,10 @@ where
152 defmt::trace!("write={} read={}", write_bits, read_bits); 157 defmt::trace!("write={} read={}", write_bits, read_bits);
153 158
154 unsafe { 159 unsafe {
155 pio_instr_util::set_x(&mut self.sm, write_bits as u32); 160 instr::set_x(&mut self.sm, write_bits as u32);
156 pio_instr_util::set_y(&mut self.sm, read_bits as u32); 161 instr::set_y(&mut self.sm, read_bits as u32);
157 pio_instr_util::set_pindir(&mut self.sm, 0b1); 162 instr::set_pindir(&mut self.sm, 0b1);
158 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target); 163 instr::exec_jmp(&mut self.sm, self.wrap_target);
159 } 164 }
160 165
161 self.sm.set_enable(true); 166 self.sm.set_enable(true);
@@ -170,6 +175,7 @@ where
170 status 175 status
171 } 176 }
172 177
178 /// Send command and read response into buffer.
173 pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 { 179 pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 {
174 self.sm.set_enable(false); 180 self.sm.set_enable(false);
175 let write_bits = 31; 181 let write_bits = 31;
@@ -179,10 +185,10 @@ where
179 defmt::trace!("write={} read={}", write_bits, read_bits); 185 defmt::trace!("write={} read={}", write_bits, read_bits);
180 186
181 unsafe { 187 unsafe {
182 pio_instr_util::set_y(&mut self.sm, read_bits as u32); 188 instr::set_y(&mut self.sm, read_bits as u32);
183 pio_instr_util::set_x(&mut self.sm, write_bits as u32); 189 instr::set_x(&mut self.sm, write_bits as u32);
184 pio_instr_util::set_pindir(&mut self.sm, 0b1); 190 instr::set_pindir(&mut self.sm, 0b1);
185 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target); 191 instr::exec_jmp(&mut self.sm, self.wrap_target);
186 } 192 }
187 193
188 // self.cs.set_low(); 194 // self.cs.set_low();
diff --git a/cyw43/README.md b/cyw43/README.md
index 5b8f3cf40..2c24c7d36 100644
--- a/cyw43/README.md
+++ b/cyw43/README.md
@@ -45,6 +45,10 @@ nc 192.168.0.250 1234
45``` 45```
46Send it some data, you should see it echoed back and printed in the firmware's logs. 46Send it some data, you should see it echoed back and printed in the firmware's logs.
47 47
48## Minimum supported Rust version (MSRV)
49
50Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
51
48## License 52## License
49 53
50This work is licensed under either of 54This work is licensed under either of
diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index 826edfe1a..311fcb08c 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -12,17 +12,23 @@ use crate::ioctl::{IoctlState, IoctlType};
12use crate::structs::*; 12use crate::structs::*;
13use crate::{countries, events, PowerManagementMode}; 13use crate::{countries, events, PowerManagementMode};
14 14
15/// Control errors.
15#[derive(Debug)] 16#[derive(Debug)]
16pub struct Error { 17pub struct Error {
18 /// Status code.
17 pub status: u32, 19 pub status: u32,
18} 20}
19 21
22/// Multicast errors.
20#[derive(Debug)] 23#[derive(Debug)]
21pub enum AddMulticastAddressError { 24pub enum AddMulticastAddressError {
25 /// Not a multicast address.
22 NotMulticast, 26 NotMulticast,
27 /// No free address slots.
23 NoFreeSlots, 28 NoFreeSlots,
24} 29}
25 30
31/// Control driver.
26pub struct Control<'a> { 32pub struct Control<'a> {
27 state_ch: ch::StateRunner<'a>, 33 state_ch: ch::StateRunner<'a>,
28 events: &'a Events, 34 events: &'a Events,
@@ -38,6 +44,7 @@ impl<'a> Control<'a> {
38 } 44 }
39 } 45 }
40 46
47 /// Initialize WiFi controller.
41 pub async fn init(&mut self, clm: &[u8]) { 48 pub async fn init(&mut self, clm: &[u8]) {
42 const CHUNK_SIZE: usize = 1024; 49 const CHUNK_SIZE: usize = 1024;
43 50
@@ -154,6 +161,7 @@ impl<'a> Control<'a> {
154 self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; 161 self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
155 } 162 }
156 163
164 /// Set power management mode.
157 pub async fn set_power_management(&mut self, mode: PowerManagementMode) { 165 pub async fn set_power_management(&mut self, mode: PowerManagementMode) {
158 // power save mode 166 // power save mode
159 let mode_num = mode.mode(); 167 let mode_num = mode.mode();
@@ -166,6 +174,7 @@ impl<'a> Control<'a> {
166 self.ioctl_set_u32(86, 0, mode_num).await; 174 self.ioctl_set_u32(86, 0, mode_num).await;
167 } 175 }
168 176
177 /// Join an unprotected network with the provided ssid.
169 pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { 178 pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> {
170 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 179 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
171 180
@@ -183,6 +192,7 @@ impl<'a> Control<'a> {
183 self.wait_for_join(i).await 192 self.wait_for_join(i).await
184 } 193 }
185 194
195 /// Join an protected network with the provided ssid and passphrase.
186 pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> { 196 pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
187 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 197 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
188 198
@@ -250,16 +260,19 @@ impl<'a> Control<'a> {
250 } 260 }
251 } 261 }
252 262
263 /// Set GPIO pin on WiFi chip.
253 pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) { 264 pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) {
254 assert!(gpio_n < 3); 265 assert!(gpio_n < 3);
255 self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 }) 266 self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 })
256 .await 267 .await
257 } 268 }
258 269
270 /// Start open access point.
259 pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) { 271 pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) {
260 self.start_ap(ssid, "", Security::OPEN, channel).await; 272 self.start_ap(ssid, "", Security::OPEN, channel).await;
261 } 273 }
262 274
275 /// Start WPA2 protected access point.
263 pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) { 276 pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) {
264 self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await; 277 self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await;
265 } 278 }
@@ -494,13 +507,14 @@ impl<'a> Control<'a> {
494 } 507 }
495} 508}
496 509
510/// WiFi network scanner.
497pub struct Scanner<'a> { 511pub struct Scanner<'a> {
498 subscriber: EventSubscriber<'a>, 512 subscriber: EventSubscriber<'a>,
499 events: &'a Events, 513 events: &'a Events,
500} 514}
501 515
502impl Scanner<'_> { 516impl Scanner<'_> {
503 /// wait for the next found network 517 /// Wait for the next found network.
504 pub async fn next(&mut self) -> Option<BssInfo> { 518 pub async fn next(&mut self) -> Option<BssInfo> {
505 let event = self.subscriber.next_message_pure().await; 519 let event = self.subscriber.next_message_pure().await;
506 if event.header.status != EStatus::PARTIAL { 520 if event.header.status != EStatus::PARTIAL {
diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs
index 300465e36..19b0cb194 100644
--- a/cyw43/src/lib.rs
+++ b/cyw43/src/lib.rs
@@ -2,6 +2,8 @@
2#![no_main] 2#![no_main]
3#![allow(async_fn_in_trait)] 3#![allow(async_fn_in_trait)]
4#![deny(unused_must_use)] 4#![deny(unused_must_use)]
5#![doc = include_str!("../README.md")]
6#![warn(missing_docs)]
5 7
6// This mod MUST go first, so that the others see its macros. 8// This mod MUST go first, so that the others see its macros.
7pub(crate) mod fmt; 9pub(crate) mod fmt;
@@ -102,6 +104,7 @@ const CHIP: Chip = Chip {
102 chanspec_ctl_sb_mask: 0x0700, 104 chanspec_ctl_sb_mask: 0x0700,
103}; 105};
104 106
107/// Driver state.
105pub struct State { 108pub struct State {
106 ioctl_state: IoctlState, 109 ioctl_state: IoctlState,
107 ch: ch::State<MTU, 4, 4>, 110 ch: ch::State<MTU, 4, 4>,
@@ -109,6 +112,7 @@ pub struct State {
109} 112}
110 113
111impl State { 114impl State {
115 /// Create new driver state holder.
112 pub fn new() -> Self { 116 pub fn new() -> Self {
113 Self { 117 Self {
114 ioctl_state: IoctlState::new(), 118 ioctl_state: IoctlState::new(),
@@ -118,6 +122,7 @@ impl State {
118 } 122 }
119} 123}
120 124
125/// Power management modes.
121#[derive(Debug, Clone, Copy, PartialEq, Eq)] 126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub enum PowerManagementMode { 127pub enum PowerManagementMode {
123 /// Custom, officially unsupported mode. Use at your own risk. 128 /// Custom, officially unsupported mode. Use at your own risk.
@@ -203,8 +208,13 @@ impl PowerManagementMode {
203 } 208 }
204} 209}
205 210
211/// Embassy-net driver.
206pub type NetDriver<'a> = ch::Device<'a, MTU>; 212pub type NetDriver<'a> = ch::Device<'a, MTU>;
207 213
214/// Create a new instance of the CYW43 driver.
215///
216/// Returns a handle to the network device, control handle and a runner for driving the low level
217/// stack.
208pub async fn new<'a, PWR, SPI>( 218pub async fn new<'a, PWR, SPI>(
209 state: &'a mut State, 219 state: &'a mut State,
210 pwr: PWR, 220 pwr: PWR,
diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs
index 83aee6b40..b2a9e3e80 100644
--- a/cyw43/src/runner.rs
+++ b/cyw43/src/runner.rs
@@ -34,6 +34,7 @@ impl Default for LogState {
34 } 34 }
35} 35}
36 36
37/// Driver communicating with the WiFi chip.
37pub struct Runner<'a, PWR, SPI> { 38pub struct Runner<'a, PWR, SPI> {
38 ch: ch::Runner<'a, MTU>, 39 ch: ch::Runner<'a, MTU>,
39 bus: Bus<PWR, SPI>, 40 bus: Bus<PWR, SPI>,
@@ -222,6 +223,7 @@ where
222 } 223 }
223 } 224 }
224 225
226 /// Run the
225 pub async fn run(mut self) -> ! { 227 pub async fn run(mut self) -> ! {
226 let mut buf = [0; 512]; 228 let mut buf = [0; 512];
227 loop { 229 loop {
diff --git a/cyw43/src/structs.rs b/cyw43/src/structs.rs
index 5ba633c74..5ea62d95b 100644
--- a/cyw43/src/structs.rs
+++ b/cyw43/src/structs.rs
@@ -4,13 +4,16 @@ use crate::fmt::Bytes;
4macro_rules! impl_bytes { 4macro_rules! impl_bytes {
5 ($t:ident) => { 5 ($t:ident) => {
6 impl $t { 6 impl $t {
7 /// Bytes consumed by this type.
7 pub const SIZE: usize = core::mem::size_of::<Self>(); 8 pub const SIZE: usize = core::mem::size_of::<Self>();
8 9
10 /// Convert to byte array.
9 #[allow(unused)] 11 #[allow(unused)]
10 pub fn to_bytes(&self) -> [u8; Self::SIZE] { 12 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
11 unsafe { core::mem::transmute(*self) } 13 unsafe { core::mem::transmute(*self) }
12 } 14 }
13 15
16 /// Create from byte array.
14 #[allow(unused)] 17 #[allow(unused)]
15 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self { 18 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self {
16 let alignment = core::mem::align_of::<Self>(); 19 let alignment = core::mem::align_of::<Self>();
@@ -23,6 +26,7 @@ macro_rules! impl_bytes {
23 unsafe { core::mem::transmute(bytes) } 26 unsafe { core::mem::transmute(bytes) }
24 } 27 }
25 28
29 /// Create from mutable byte array.
26 #[allow(unused)] 30 #[allow(unused)]
27 pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self { 31 pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self {
28 let alignment = core::mem::align_of::<Self>(); 32 let alignment = core::mem::align_of::<Self>();
@@ -204,6 +208,7 @@ pub struct EthernetHeader {
204} 208}
205 209
206impl EthernetHeader { 210impl EthernetHeader {
211 /// Swap endianness.
207 pub fn byteswap(&mut self) { 212 pub fn byteswap(&mut self) {
208 self.ether_type = self.ether_type.to_be(); 213 self.ether_type = self.ether_type.to_be();
209 } 214 }
@@ -472,19 +477,26 @@ impl ScanResults {
472#[repr(C, packed(2))] 477#[repr(C, packed(2))]
473#[non_exhaustive] 478#[non_exhaustive]
474pub struct BssInfo { 479pub struct BssInfo {
480 /// Version.
475 pub version: u32, 481 pub version: u32,
482 /// Length.
476 pub length: u32, 483 pub length: u32,
484 /// BSSID.
477 pub bssid: [u8; 6], 485 pub bssid: [u8; 6],
486 /// Beacon period.
478 pub beacon_period: u16, 487 pub beacon_period: u16,
488 /// Capability.
479 pub capability: u16, 489 pub capability: u16,
490 /// SSID length.
480 pub ssid_len: u8, 491 pub ssid_len: u8,
492 /// SSID.
481 pub ssid: [u8; 32], 493 pub ssid: [u8; 32],
482 // there will be more stuff here 494 // there will be more stuff here
483} 495}
484impl_bytes!(BssInfo); 496impl_bytes!(BssInfo);
485 497
486impl BssInfo { 498impl BssInfo {
487 pub fn parse(packet: &mut [u8]) -> Option<&mut Self> { 499 pub(crate) fn parse(packet: &mut [u8]) -> Option<&mut Self> {
488 if packet.len() < BssInfo::SIZE { 500 if packet.len() < BssInfo::SIZE {
489 return None; 501 return None;
490 } 502 }
diff --git a/docs/modules/ROOT/examples/basic/src/main.rs b/docs/modules/ROOT/examples/basic/src/main.rs
index 04170db55..2a4ee5968 100644
--- a/docs/modules/ROOT/examples/basic/src/main.rs
+++ b/docs/modules/ROOT/examples/basic/src/main.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml
index dcdb71e7b..2d47dccf4 100644
--- a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml
+++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8cortex-m = "0.7" 8cortex-m = "0.7"
9cortex-m-rt = "0.7" 9cortex-m-rt = "0.7"
10embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] } 10embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] }
11embassy-executor = { version = "0.4.0", features = ["nightly", "arch-cortex-m", "executor-thread"] } 11embassy-executor = { version = "0.4.0", features = ["arch-cortex-m", "executor-thread"] }
12 12
13defmt = "0.3.0" 13defmt = "0.3.0"
14defmt-rtt = "0.3.0" 14defmt-rtt = "0.3.0"
diff --git a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/src/main.rs b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/src/main.rs
index 8df632240..e6753be28 100644
--- a/docs/modules/ROOT/examples/layer-by-layer/blinky-async/src/main.rs
+++ b/docs/modules/ROOT/examples/layer-by-layer/blinky-async/src/main.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 5use embassy_stm32::exti::ExtiInput;
diff --git a/docs/modules/ROOT/pages/faq.adoc b/docs/modules/ROOT/pages/faq.adoc
index d1a012978..1fe9bde37 100644
--- a/docs/modules/ROOT/pages/faq.adoc
+++ b/docs/modules/ROOT/pages/faq.adoc
@@ -35,7 +35,7 @@ For Cortex-M targets, consider making sure that ALL of the following features ar
35* `executor-thread` 35* `executor-thread`
36* `nightly` 36* `nightly`
37 37
38For Xtensa ESP32, consider using the executors and `#[main]` macro provided by your appropriate link:https://crates.io/crates/esp-hal-common[HAL crate]. 38For ESP32, consider using the executors and `#[main]` macro provided by your appropriate link:https://crates.io/crates/esp-hal-common[HAL crate].
39 39
40== Why is my binary so big? 40== Why is my binary so big?
41 41
diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml
index dd2ff8158..3c84ffcd3 100644
--- a/embassy-boot/boot/Cargo.toml
+++ b/embassy-boot/boot/Cargo.toml
@@ -26,25 +26,22 @@ features = ["defmt"]
26defmt = { version = "0.3", optional = true } 26defmt = { version = "0.3", optional = true }
27digest = "0.10" 27digest = "0.10"
28log = { version = "0.4", optional = true } 28log = { version = "0.4", optional = true }
29ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true } 29ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true }
30embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } 30embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
31embassy-sync = { version = "0.5.0", path = "../../embassy-sync" } 31embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
32embedded-storage = "0.3.1" 32embedded-storage = "0.3.1"
33embedded-storage-async = { version = "0.4.1" } 33embedded-storage-async = { version = "0.4.1" }
34salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true } 34salty = { version = "0.3", optional = true }
35signature = { version = "1.6.4", default-features = false } 35signature = { version = "2.0", default-features = false }
36 36
37[dev-dependencies] 37[dev-dependencies]
38log = "0.4" 38log = "0.4"
39env_logger = "0.9" 39env_logger = "0.9"
40rand = "0.7" # ed25519-dalek v1.0.1 depends on this exact version 40rand = "0.8"
41futures = { version = "0.3", features = ["executor"] } 41futures = { version = "0.3", features = ["executor"] }
42sha1 = "0.10.5" 42sha1 = "0.10.5"
43critical-section = { version = "1.1.1", features = ["std"] } 43critical-section = { version = "1.1.1", features = ["std"] }
44 44ed25519-dalek = { version = "2", default_features = false, features = ["std", "rand_core", "digest"] }
45[dev-dependencies.ed25519-dalek]
46default_features = false
47features = ["rand", "std", "u32_backend"]
48 45
49[features] 46[features]
50ed25519-dalek = ["dep:ed25519-dalek", "_verify"] 47ed25519-dalek = ["dep:ed25519-dalek", "_verify"]
diff --git a/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs b/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs
index a184d1c51..2e4e03da3 100644
--- a/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs
+++ b/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs
@@ -1,6 +1,6 @@
1use digest::typenum::U64; 1use digest::typenum::U64;
2use digest::{FixedOutput, HashMarker, OutputSizeUser, Update}; 2use digest::{FixedOutput, HashMarker, OutputSizeUser, Update};
3use ed25519_dalek::Digest as _; 3use ed25519_dalek::Digest;
4 4
5pub struct Sha512(ed25519_dalek::Sha512); 5pub struct Sha512(ed25519_dalek::Sha512);
6 6
@@ -12,7 +12,7 @@ impl Default for Sha512 {
12 12
13impl Update for Sha512 { 13impl Update for Sha512 {
14 fn update(&mut self, data: &[u8]) { 14 fn update(&mut self, data: &[u8]) {
15 self.0.update(data) 15 Digest::update(&mut self.0, data)
16 } 16 }
17} 17}
18 18
diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/boot/src/firmware_updater/asynch.rs
index d8d85c3d2..64a4b32ec 100644
--- a/embassy-boot/boot/src/firmware_updater/asynch.rs
+++ b/embassy-boot/boot/src/firmware_updater/asynch.rs
@@ -79,8 +79,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
79 #[cfg(feature = "_verify")] 79 #[cfg(feature = "_verify")]
80 pub async fn verify_and_mark_updated( 80 pub async fn verify_and_mark_updated(
81 &mut self, 81 &mut self,
82 _public_key: &[u8], 82 _public_key: &[u8; 32],
83 _signature: &[u8], 83 _signature: &[u8; 64],
84 _update_len: u32, 84 _update_len: u32,
85 ) -> Result<(), FirmwareUpdaterError> { 85 ) -> Result<(), FirmwareUpdaterError> {
86 assert!(_update_len <= self.dfu.capacity() as u32); 86 assert!(_update_len <= self.dfu.capacity() as u32);
@@ -89,14 +89,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
89 89
90 #[cfg(feature = "ed25519-dalek")] 90 #[cfg(feature = "ed25519-dalek")]
91 { 91 {
92 use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; 92 use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
93 93
94 use crate::digest_adapters::ed25519_dalek::Sha512; 94 use crate::digest_adapters::ed25519_dalek::Sha512;
95 95
96 let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); 96 let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
97 97
98 let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; 98 let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
99 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; 99 let signature = Signature::from_bytes(_signature);
100 100
101 let mut chunk_buf = [0; 2]; 101 let mut chunk_buf = [0; 2];
102 let mut message = [0; 64]; 102 let mut message = [0; 64];
@@ -106,7 +106,6 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
106 } 106 }
107 #[cfg(feature = "ed25519-salty")] 107 #[cfg(feature = "ed25519-salty")]
108 { 108 {
109 use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
110 use salty::{PublicKey, Signature}; 109 use salty::{PublicKey, Signature};
111 110
112 use crate::digest_adapters::salty::Sha512; 111 use crate::digest_adapters::salty::Sha512;
@@ -115,10 +114,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
115 FirmwareUpdaterError::Signature(signature::Error::default()) 114 FirmwareUpdaterError::Signature(signature::Error::default())
116 } 115 }
117 116
118 let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; 117 let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
119 let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; 118 let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
120 let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
121 let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
122 119
123 let mut message = [0; 64]; 120 let mut message = [0; 64];
124 let mut chunk_buf = [0; 2]; 121 let mut chunk_buf = [0; 2];
diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs
index c4c142169..f1368540d 100644
--- a/embassy-boot/boot/src/firmware_updater/blocking.rs
+++ b/embassy-boot/boot/src/firmware_updater/blocking.rs
@@ -86,8 +86,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
86 #[cfg(feature = "_verify")] 86 #[cfg(feature = "_verify")]
87 pub fn verify_and_mark_updated( 87 pub fn verify_and_mark_updated(
88 &mut self, 88 &mut self,
89 _public_key: &[u8], 89 _public_key: &[u8; 32],
90 _signature: &[u8], 90 _signature: &[u8; 64],
91 _update_len: u32, 91 _update_len: u32,
92 ) -> Result<(), FirmwareUpdaterError> { 92 ) -> Result<(), FirmwareUpdaterError> {
93 assert!(_update_len <= self.dfu.capacity() as u32); 93 assert!(_update_len <= self.dfu.capacity() as u32);
@@ -96,14 +96,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
96 96
97 #[cfg(feature = "ed25519-dalek")] 97 #[cfg(feature = "ed25519-dalek")]
98 { 98 {
99 use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; 99 use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
100 100
101 use crate::digest_adapters::ed25519_dalek::Sha512; 101 use crate::digest_adapters::ed25519_dalek::Sha512;
102 102
103 let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); 103 let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
104 104
105 let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; 105 let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
106 let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; 106 let signature = Signature::from_bytes(_signature);
107 107
108 let mut message = [0; 64]; 108 let mut message = [0; 64];
109 let mut chunk_buf = [0; 2]; 109 let mut chunk_buf = [0; 2];
@@ -113,7 +113,6 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
113 } 113 }
114 #[cfg(feature = "ed25519-salty")] 114 #[cfg(feature = "ed25519-salty")]
115 { 115 {
116 use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
117 use salty::{PublicKey, Signature}; 116 use salty::{PublicKey, Signature};
118 117
119 use crate::digest_adapters::salty::Sha512; 118 use crate::digest_adapters::salty::Sha512;
@@ -122,10 +121,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
122 FirmwareUpdaterError::Signature(signature::Error::default()) 121 FirmwareUpdaterError::Signature(signature::Error::default())
123 } 122 }
124 123
125 let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; 124 let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
126 let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; 125 let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
127 let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
128 let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
129 126
130 let mut message = [0; 64]; 127 let mut message = [0; 64];
131 let mut chunk_buf = [0; 2]; 128 let mut chunk_buf = [0; 2];
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index 15b69f69d..b4f03e01e 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -275,21 +275,19 @@ mod tests {
275 // The following key setup is based on: 275 // The following key setup is based on:
276 // https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example 276 // https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example
277 277
278 use ed25519_dalek::Keypair; 278 use ed25519_dalek::{Digest, Sha512, Signature, Signer, SigningKey, VerifyingKey};
279 use rand::rngs::OsRng; 279 use rand::rngs::OsRng;
280 280
281 let mut csprng = OsRng {}; 281 let mut csprng = OsRng {};
282 let keypair: Keypair = Keypair::generate(&mut csprng); 282 let keypair = SigningKey::generate(&mut csprng);
283 283
284 use ed25519_dalek::{Digest, Sha512, Signature, Signer};
285 let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU."; 284 let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU.";
286 let mut digest = Sha512::new(); 285 let mut digest = Sha512::new();
287 digest.update(&firmware); 286 digest.update(&firmware);
288 let message = digest.finalize(); 287 let message = digest.finalize();
289 let signature: Signature = keypair.sign(&message); 288 let signature: Signature = keypair.sign(&message);
290 289
291 use ed25519_dalek::PublicKey; 290 let public_key = keypair.verifying_key();
292 let public_key: PublicKey = keypair.public;
293 291
294 // Setup flash 292 // Setup flash
295 let flash = BlockingTestFlash::new(BootLoaderConfig { 293 let flash = BlockingTestFlash::new(BootLoaderConfig {
diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml
index eea29cf2e..9f74fb126 100644
--- a/embassy-boot/nrf/Cargo.toml
+++ b/embassy-boot/nrf/Cargo.toml
@@ -4,6 +4,12 @@ name = "embassy-boot-nrf"
4version = "0.1.0" 4version = "0.1.0"
5description = "Bootloader lib for nRF chips" 5description = "Bootloader lib for nRF chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
7 13
8[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/nrf/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/nrf/src/"
@@ -25,7 +31,7 @@ embedded-storage = "0.3.1"
25embedded-storage-async = { version = "0.4.1" } 31embedded-storage-async = { version = "0.4.1" }
26cfg-if = "1.0.0" 32cfg-if = "1.0.0"
27 33
28nrf-softdevice-mbr = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice.git", branch = "master", optional = true } 34nrf-softdevice-mbr = { version = "0.2.0", optional = true }
29 35
30[features] 36[features]
31defmt = [ 37defmt = [
diff --git a/embassy-boot/rp/Cargo.toml b/embassy-boot/rp/Cargo.toml
index 0f2dc4628..90bab0996 100644
--- a/embassy-boot/rp/Cargo.toml
+++ b/embassy-boot/rp/Cargo.toml
@@ -4,6 +4,12 @@ name = "embassy-boot-rp"
4version = "0.1.0" 4version = "0.1.0"
5description = "Bootloader lib for RP2040 chips" 5description = "Bootloader lib for RP2040 chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
7 13
8[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/"
diff --git a/embassy-boot/stm32/Cargo.toml b/embassy-boot/stm32/Cargo.toml
index bc8da6738..70919b76d 100644
--- a/embassy-boot/stm32/Cargo.toml
+++ b/embassy-boot/stm32/Cargo.toml
@@ -4,6 +4,12 @@ name = "embassy-boot-stm32"
4version = "0.1.0" 4version = "0.1.0"
5description = "Bootloader lib for STM32 chips" 5description = "Bootloader lib for STM32 chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
7 13
8[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/stm32/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/stm32/src/"
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index ec5aca46d..4dcd03b0f 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -14,7 +14,7 @@ categories = [
14[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" 16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
17features = ["nightly", "defmt"] 17features = ["defmt"]
18flavors = [ 18flavors = [
19 { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, 19 { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
20 { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, 20 { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
@@ -25,7 +25,7 @@ flavors = [
25[package.metadata.docs.rs] 25[package.metadata.docs.rs]
26default-target = "thumbv7em-none-eabi" 26default-target = "thumbv7em-none-eabi"
27targets = ["thumbv7em-none-eabi"] 27targets = ["thumbv7em-none-eabi"]
28features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] 28features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
29 29
30[dependencies] 30[dependencies]
31defmt = { version = "0.3", optional = true } 31defmt = { version = "0.3", optional = true }
diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml
index b1582ac9b..f1be52da5 100644
--- a/embassy-net-adin1110/Cargo.toml
+++ b/embassy-net-adin1110/Cargo.toml
@@ -6,8 +6,7 @@ keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethern
6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] 6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
7license = "MIT OR Apache-2.0" 7license = "MIT OR Apache-2.0"
8edition = "2021" 8edition = "2021"
9 9repository = "https://github.com/embassy-rs/embassy"
10# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
11 10
12[dependencies] 11[dependencies]
13heapless = "0.8" 12heapless = "0.8"
diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs
index ec020b70c..4b3c69f23 100644
--- a/embassy-net-adin1110/src/crc32.rs
+++ b/embassy-net-adin1110/src/crc32.rs
@@ -1,3 +1,4 @@
1/// CRC32 lookup table.
1pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ 2pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
2 0x0000_0000, 3 0x0000_0000,
3 0x7707_3096, 4 0x7707_3096,
@@ -263,8 +264,9 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
263pub struct ETH_FCS(pub u32); 264pub struct ETH_FCS(pub u32);
264 265
265impl ETH_FCS { 266impl ETH_FCS {
266 pub const CRC32_OK: u32 = 0x2144_df1c; 267 const CRC32_OK: u32 = 0x2144_df1c;
267 268
269 /// Create a new frame check sequence from `data`.
268 #[must_use] 270 #[must_use]
269 pub fn new(data: &[u8]) -> Self { 271 pub fn new(data: &[u8]) -> Self {
270 let fcs = data.iter().fold(u32::MAX, |crc, byte| { 272 let fcs = data.iter().fold(u32::MAX, |crc, byte| {
@@ -274,6 +276,7 @@ impl ETH_FCS {
274 Self(fcs) 276 Self(fcs)
275 } 277 }
276 278
279 /// Update the frame check sequence with `data`.
277 #[must_use] 280 #[must_use]
278 pub fn update(self, data: &[u8]) -> Self { 281 pub fn update(self, data: &[u8]) -> Self {
279 let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| { 282 let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
@@ -283,16 +286,19 @@ impl ETH_FCS {
283 Self(fcs) 286 Self(fcs)
284 } 287 }
285 288
289 /// Check if the frame check sequence is correct.
286 #[must_use] 290 #[must_use]
287 pub fn crc_ok(&self) -> bool { 291 pub fn crc_ok(&self) -> bool {
288 self.0 == Self::CRC32_OK 292 self.0 == Self::CRC32_OK
289 } 293 }
290 294
295 /// Switch byte order.
291 #[must_use] 296 #[must_use]
292 pub fn hton_bytes(&self) -> [u8; 4] { 297 pub fn hton_bytes(&self) -> [u8; 4] {
293 self.0.to_le_bytes() 298 self.0.to_le_bytes()
294 } 299 }
295 300
301 /// Switch byte order as a u32.
296 #[must_use] 302 #[must_use]
297 pub fn hton(&self) -> u32 { 303 pub fn hton(&self) -> u32 {
298 self.0.to_le() 304 self.0.to_le()
diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs
index 080b3f94d..6ecfa587d 100644
--- a/embassy-net-adin1110/src/lib.rs
+++ b/embassy-net-adin1110/src/lib.rs
@@ -5,6 +5,7 @@
5#![allow(clippy::missing_errors_doc)] 5#![allow(clippy::missing_errors_doc)]
6#![allow(clippy::missing_panics_doc)] 6#![allow(clippy::missing_panics_doc)]
7#![doc = include_str!("../README.md")] 7#![doc = include_str!("../README.md")]
8#![warn(missing_docs)]
8 9
9// must go first! 10// must go first!
10mod fmt; 11mod fmt;
@@ -26,8 +27,9 @@ use embedded_hal_async::digital::Wait;
26use embedded_hal_async::spi::{Error, Operation, SpiDevice}; 27use embedded_hal_async::spi::{Error, Operation, SpiDevice};
27use heapless::Vec; 28use heapless::Vec;
28pub use mdio::MdioBus; 29pub use mdio::MdioBus;
29pub use phy::{Phy10BaseT1x, RegsC22, RegsC45}; 30pub use phy::Phy10BaseT1x;
30pub use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1}; 31use phy::{RegsC22, RegsC45};
32use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1};
31 33
32use crate::fmt::Bytes; 34use crate::fmt::Bytes;
33use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader}; 35use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader};
@@ -446,6 +448,7 @@ pub struct Runner<'d, SPI, INT, RST> {
446} 448}
447 449
448impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> { 450impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> {
451 /// Run the driver.
449 #[allow(clippy::too_many_lines)] 452 #[allow(clippy::too_many_lines)]
450 pub async fn run(mut self) -> ! { 453 pub async fn run(mut self) -> ! {
451 loop { 454 loop {
diff --git a/embassy-net-adin1110/src/mdio.rs b/embassy-net-adin1110/src/mdio.rs
index 1ae5f0043..6fea9370e 100644
--- a/embassy-net-adin1110/src/mdio.rs
+++ b/embassy-net-adin1110/src/mdio.rs
@@ -39,6 +39,7 @@ enum Reg13Op {
39/// 39///
40/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf> 40/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf>
41pub trait MdioBus { 41pub trait MdioBus {
42 /// Error type.
42 type Error; 43 type Error;
43 44
44 /// Read, Clause 22 45 /// Read, Clause 22
diff --git a/embassy-net-adin1110/src/regs.rs b/embassy-net-adin1110/src/regs.rs
index beaf9466e..8780c2b9d 100644
--- a/embassy-net-adin1110/src/regs.rs
+++ b/embassy-net-adin1110/src/regs.rs
@@ -2,6 +2,7 @@ use core::fmt::{Debug, Display};
2 2
3use bitfield::{bitfield, bitfield_bitrange, bitfield_fields}; 3use bitfield::{bitfield, bitfield_bitrange, bitfield_fields};
4 4
5#[allow(missing_docs)]
5#[allow(non_camel_case_types)] 6#[allow(non_camel_case_types)]
6#[derive(Debug, Copy, Clone)] 7#[derive(Debug, Copy, Clone)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))] 8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-net-driver-channel/src/lib.rs b/embassy-net-driver-channel/src/lib.rs
index bfb2c9c03..7ad4d449e 100644
--- a/embassy-net-driver-channel/src/lib.rs
+++ b/embassy-net-driver-channel/src/lib.rs
@@ -1,5 +1,6 @@
1#![no_std] 1#![no_std]
2#![doc = include_str!("../README.md")] 2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
3 4
4// must go first! 5// must go first!
5mod fmt; 6mod fmt;
@@ -15,6 +16,9 @@ use embassy_sync::blocking_mutex::Mutex;
15use embassy_sync::waitqueue::WakerRegistration; 16use embassy_sync::waitqueue::WakerRegistration;
16use embassy_sync::zerocopy_channel; 17use embassy_sync::zerocopy_channel;
17 18
19/// Channel state.
20///
21/// Holds a buffer of packets with size MTU, for both TX and RX.
18pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> { 22pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
19 rx: [PacketBuf<MTU>; N_RX], 23 rx: [PacketBuf<MTU>; N_RX],
20 tx: [PacketBuf<MTU>; N_TX], 24 tx: [PacketBuf<MTU>; N_TX],
@@ -24,6 +28,7 @@ pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
24impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> { 28impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
25 const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new(); 29 const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
26 30
31 /// Create a new channel state.
27 pub const fn new() -> Self { 32 pub const fn new() -> Self {
28 Self { 33 Self {
29 rx: [Self::NEW_PACKET; N_RX], 34 rx: [Self::NEW_PACKET; N_RX],
@@ -39,33 +44,45 @@ struct StateInner<'d, const MTU: usize> {
39 shared: Mutex<NoopRawMutex, RefCell<Shared>>, 44 shared: Mutex<NoopRawMutex, RefCell<Shared>>,
40} 45}
41 46
42/// State of the LinkState
43struct Shared { 47struct Shared {
44 link_state: LinkState, 48 link_state: LinkState,
45 waker: WakerRegistration, 49 waker: WakerRegistration,
46 hardware_address: driver::HardwareAddress, 50 hardware_address: driver::HardwareAddress,
47} 51}
48 52
53/// Channel runner.
54///
55/// Holds the shared state and the lower end of channels for inbound and outbound packets.
49pub struct Runner<'d, const MTU: usize> { 56pub struct Runner<'d, const MTU: usize> {
50 tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, 57 tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
51 rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, 58 rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
52 shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>, 59 shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
53} 60}
54 61
62/// State runner.
63///
64/// Holds the shared state of the channel such as link state.
55#[derive(Clone, Copy)] 65#[derive(Clone, Copy)]
56pub struct StateRunner<'d> { 66pub struct StateRunner<'d> {
57 shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>, 67 shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
58} 68}
59 69
70/// RX runner.
71///
72/// Holds the lower end of the channel for passing inbound packets up the stack.
60pub struct RxRunner<'d, const MTU: usize> { 73pub struct RxRunner<'d, const MTU: usize> {
61 rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, 74 rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
62} 75}
63 76
77/// TX runner.
78///
79/// Holds the lower end of the channel for passing outbound packets down the stack.
64pub struct TxRunner<'d, const MTU: usize> { 80pub struct TxRunner<'d, const MTU: usize> {
65 tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, 81 tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
66} 82}
67 83
68impl<'d, const MTU: usize> Runner<'d, MTU> { 84impl<'d, const MTU: usize> Runner<'d, MTU> {
85 /// Split the runner into separate runners for controlling state, rx and tx.
69 pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) { 86 pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
70 ( 87 (
71 StateRunner { shared: self.shared }, 88 StateRunner { shared: self.shared },
@@ -74,6 +91,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
74 ) 91 )
75 } 92 }
76 93
94 /// Split the runner into separate runners for controlling state, rx and tx borrowing the underlying state.
77 pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) { 95 pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
78 ( 96 (
79 StateRunner { shared: self.shared }, 97 StateRunner { shared: self.shared },
@@ -86,10 +104,12 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
86 ) 104 )
87 } 105 }
88 106
107 /// Create a state runner sharing the state channel.
89 pub fn state_runner(&self) -> StateRunner<'d> { 108 pub fn state_runner(&self) -> StateRunner<'d> {
90 StateRunner { shared: self.shared } 109 StateRunner { shared: self.shared }
91 } 110 }
92 111
112 /// Set the link state.
93 pub fn set_link_state(&mut self, state: LinkState) { 113 pub fn set_link_state(&mut self, state: LinkState) {
94 self.shared.lock(|s| { 114 self.shared.lock(|s| {
95 let s = &mut *s.borrow_mut(); 115 let s = &mut *s.borrow_mut();
@@ -98,6 +118,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
98 }); 118 });
99 } 119 }
100 120
121 /// Set the hardware address.
101 pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) { 122 pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
102 self.shared.lock(|s| { 123 self.shared.lock(|s| {
103 let s = &mut *s.borrow_mut(); 124 let s = &mut *s.borrow_mut();
@@ -106,16 +127,19 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
106 }); 127 });
107 } 128 }
108 129
130 /// Wait until there is space for more inbound packets and return a slice they can be copied into.
109 pub async fn rx_buf(&mut self) -> &mut [u8] { 131 pub async fn rx_buf(&mut self) -> &mut [u8] {
110 let p = self.rx_chan.send().await; 132 let p = self.rx_chan.send().await;
111 &mut p.buf 133 &mut p.buf
112 } 134 }
113 135
136 /// Check if there is space for more inbound packets right now.
114 pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> { 137 pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
115 let p = self.rx_chan.try_send()?; 138 let p = self.rx_chan.try_send()?;
116 Some(&mut p.buf) 139 Some(&mut p.buf)
117 } 140 }
118 141
142 /// Polling the inbound channel if there is space for packets.
119 pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { 143 pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
120 match self.rx_chan.poll_send(cx) { 144 match self.rx_chan.poll_send(cx) {
121 Poll::Ready(p) => Poll::Ready(&mut p.buf), 145 Poll::Ready(p) => Poll::Ready(&mut p.buf),
@@ -123,22 +147,26 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
123 } 147 }
124 } 148 }
125 149
150 /// Mark packet of len bytes as pushed to the inbound channel.
126 pub fn rx_done(&mut self, len: usize) { 151 pub fn rx_done(&mut self, len: usize) {
127 let p = self.rx_chan.try_send().unwrap(); 152 let p = self.rx_chan.try_send().unwrap();
128 p.len = len; 153 p.len = len;
129 self.rx_chan.send_done(); 154 self.rx_chan.send_done();
130 } 155 }
131 156
157 /// Wait until there is space for more outbound packets and return a slice they can be copied into.
132 pub async fn tx_buf(&mut self) -> &mut [u8] { 158 pub async fn tx_buf(&mut self) -> &mut [u8] {
133 let p = self.tx_chan.receive().await; 159 let p = self.tx_chan.receive().await;
134 &mut p.buf[..p.len] 160 &mut p.buf[..p.len]
135 } 161 }
136 162
163 /// Check if there is space for more outbound packets right now.
137 pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> { 164 pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
138 let p = self.tx_chan.try_receive()?; 165 let p = self.tx_chan.try_receive()?;
139 Some(&mut p.buf[..p.len]) 166 Some(&mut p.buf[..p.len])
140 } 167 }
141 168
169 /// Polling the outbound channel if there is space for packets.
142 pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { 170 pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
143 match self.tx_chan.poll_receive(cx) { 171 match self.tx_chan.poll_receive(cx) {
144 Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]), 172 Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
@@ -146,12 +174,14 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
146 } 174 }
147 } 175 }
148 176
177 /// Mark outbound packet as copied.
149 pub fn tx_done(&mut self) { 178 pub fn tx_done(&mut self) {
150 self.tx_chan.receive_done(); 179 self.tx_chan.receive_done();
151 } 180 }
152} 181}
153 182
154impl<'d> StateRunner<'d> { 183impl<'d> StateRunner<'d> {
184 /// Set link state.
155 pub fn set_link_state(&self, state: LinkState) { 185 pub fn set_link_state(&self, state: LinkState) {
156 self.shared.lock(|s| { 186 self.shared.lock(|s| {
157 let s = &mut *s.borrow_mut(); 187 let s = &mut *s.borrow_mut();
@@ -160,6 +190,7 @@ impl<'d> StateRunner<'d> {
160 }); 190 });
161 } 191 }
162 192
193 /// Set the hardware address.
163 pub fn set_hardware_address(&self, address: driver::HardwareAddress) { 194 pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
164 self.shared.lock(|s| { 195 self.shared.lock(|s| {
165 let s = &mut *s.borrow_mut(); 196 let s = &mut *s.borrow_mut();
@@ -170,16 +201,19 @@ impl<'d> StateRunner<'d> {
170} 201}
171 202
172impl<'d, const MTU: usize> RxRunner<'d, MTU> { 203impl<'d, const MTU: usize> RxRunner<'d, MTU> {
204 /// Wait until there is space for more inbound packets and return a slice they can be copied into.
173 pub async fn rx_buf(&mut self) -> &mut [u8] { 205 pub async fn rx_buf(&mut self) -> &mut [u8] {
174 let p = self.rx_chan.send().await; 206 let p = self.rx_chan.send().await;
175 &mut p.buf 207 &mut p.buf
176 } 208 }
177 209
210 /// Check if there is space for more inbound packets right now.
178 pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> { 211 pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
179 let p = self.rx_chan.try_send()?; 212 let p = self.rx_chan.try_send()?;
180 Some(&mut p.buf) 213 Some(&mut p.buf)
181 } 214 }
182 215
216 /// Polling the inbound channel if there is space for packets.
183 pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { 217 pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
184 match self.rx_chan.poll_send(cx) { 218 match self.rx_chan.poll_send(cx) {
185 Poll::Ready(p) => Poll::Ready(&mut p.buf), 219 Poll::Ready(p) => Poll::Ready(&mut p.buf),
@@ -187,6 +221,7 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
187 } 221 }
188 } 222 }
189 223
224 /// Mark packet of len bytes as pushed to the inbound channel.
190 pub fn rx_done(&mut self, len: usize) { 225 pub fn rx_done(&mut self, len: usize) {
191 let p = self.rx_chan.try_send().unwrap(); 226 let p = self.rx_chan.try_send().unwrap();
192 p.len = len; 227 p.len = len;
@@ -195,16 +230,19 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
195} 230}
196 231
197impl<'d, const MTU: usize> TxRunner<'d, MTU> { 232impl<'d, const MTU: usize> TxRunner<'d, MTU> {
233 /// Wait until there is space for more outbound packets and return a slice they can be copied into.
198 pub async fn tx_buf(&mut self) -> &mut [u8] { 234 pub async fn tx_buf(&mut self) -> &mut [u8] {
199 let p = self.tx_chan.receive().await; 235 let p = self.tx_chan.receive().await;
200 &mut p.buf[..p.len] 236 &mut p.buf[..p.len]
201 } 237 }
202 238
239 /// Check if there is space for more outbound packets right now.
203 pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> { 240 pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
204 let p = self.tx_chan.try_receive()?; 241 let p = self.tx_chan.try_receive()?;
205 Some(&mut p.buf[..p.len]) 242 Some(&mut p.buf[..p.len])
206 } 243 }
207 244
245 /// Polling the outbound channel if there is space for packets.
208 pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { 246 pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
209 match self.tx_chan.poll_receive(cx) { 247 match self.tx_chan.poll_receive(cx) {
210 Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]), 248 Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
@@ -212,11 +250,18 @@ impl<'d, const MTU: usize> TxRunner<'d, MTU> {
212 } 250 }
213 } 251 }
214 252
253 /// Mark outbound packet as copied.
215 pub fn tx_done(&mut self) { 254 pub fn tx_done(&mut self) {
216 self.tx_chan.receive_done(); 255 self.tx_chan.receive_done();
217 } 256 }
218} 257}
219 258
259/// Create a channel.
260///
261/// Returns a pair of handles for interfacing with the peripheral and the networking stack.
262///
263/// The runner is interfacing with the peripheral at the lower part of the stack.
264/// The device is interfacing with the networking stack on the layer above.
220pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>( 265pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
221 state: &'d mut State<MTU, N_RX, N_TX>, 266 state: &'d mut State<MTU, N_RX, N_TX>,
222 hardware_address: driver::HardwareAddress, 267 hardware_address: driver::HardwareAddress,
@@ -257,17 +302,22 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
257 ) 302 )
258} 303}
259 304
305/// Represents a packet of size MTU.
260pub struct PacketBuf<const MTU: usize> { 306pub struct PacketBuf<const MTU: usize> {
261 len: usize, 307 len: usize,
262 buf: [u8; MTU], 308 buf: [u8; MTU],
263} 309}
264 310
265impl<const MTU: usize> PacketBuf<MTU> { 311impl<const MTU: usize> PacketBuf<MTU> {
312 /// Create a new packet buffer.
266 pub const fn new() -> Self { 313 pub const fn new() -> Self {
267 Self { len: 0, buf: [0; MTU] } 314 Self { len: 0, buf: [0; MTU] }
268 } 315 }
269} 316}
270 317
318/// Channel device.
319///
320/// Holds the shared state and upper end of channels for inbound and outbound packets.
271pub struct Device<'d, const MTU: usize> { 321pub struct Device<'d, const MTU: usize> {
272 rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, 322 rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
273 tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, 323 tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
@@ -314,6 +364,9 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
314 } 364 }
315} 365}
316 366
367/// A rx token.
368///
369/// Holds inbound receive channel and interfaces with embassy-net-driver.
317pub struct RxToken<'a, const MTU: usize> { 370pub struct RxToken<'a, const MTU: usize> {
318 rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>, 371 rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
319} 372}
@@ -331,6 +384,9 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
331 } 384 }
332} 385}
333 386
387/// A tx token.
388///
389/// Holds outbound transmit channel and interfaces with embassy-net-driver.
334pub struct TxToken<'a, const MTU: usize> { 390pub struct TxToken<'a, const MTU: usize> {
335 tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>, 391 tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
336} 392}
diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml
index 70b1bbe2a..61984dd53 100644
--- a/embassy-net-esp-hosted/Cargo.toml
+++ b/embassy-net-esp-hosted/Cargo.toml
@@ -2,6 +2,10 @@
2name = "embassy-net-esp-hosted" 2name = "embassy-net-esp-hosted"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5description = "embassy-net driver for ESP-Hosted"
6keywords = ["embedded", "esp-hosted", "embassy-net", "embedded-hal-async", "wifi", "async"]
7categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
8license = "MIT OR Apache-2.0"
5 9
6[dependencies] 10[dependencies]
7defmt = { version = "0.3", optional = true } 11defmt = { version = "0.3", optional = true }
@@ -15,8 +19,7 @@ embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-
15embedded-hal = { version = "1.0.0-rc.3" } 19embedded-hal = { version = "1.0.0-rc.3" }
16embedded-hal-async = { version = "=1.0.0-rc.3" } 20embedded-hal-async = { version = "=1.0.0-rc.3" }
17 21
18noproto = { git="https://github.com/embassy-rs/noproto", rev = "f5e6d1f325b6ad4e344f60452b09576e24671f62", default-features = false, features = ["derive"] } 22noproto = "0.1.0"
19#noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] }
20heapless = "0.8" 23heapless = "0.8"
21 24
22[package.metadata.embassy_docs] 25[package.metadata.embassy_docs]
diff --git a/embassy-net-esp-hosted/README.md b/embassy-net-esp-hosted/README.md
new file mode 100644
index 000000000..3c9cc4c9e
--- /dev/null
+++ b/embassy-net-esp-hosted/README.md
@@ -0,0 +1,27 @@
1# ESP-Hosted `embassy-net` integration
2
3[`embassy-net`](https://crates.io/crates/embassy-net) integration for Espressif SoCs running the the ESP-Hosted stack.
4
5See [`examples`](https://github.com/embassy-rs/embassy/tree/main/examples/nrf52840) directory for usage examples with the nRF52840.
6
7## Supported chips
8
9- W5500
10- W5100S
11
12## Interoperability
13
14This crate can run on any executor.
15
16It supports any SPI driver implementing [`embedded-hal-async`](https://crates.io/crates/embedded-hal-async).
17
18
19## License
20
21This work is licensed under either of
22
23- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
24 http://www.apache.org/licenses/LICENSE-2.0)
25- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
26
27at your option.
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index c86891bc3..c8cea8503 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -5,38 +5,54 @@ use heapless::String;
5use crate::ioctl::Shared; 5use crate::ioctl::Shared;
6use crate::proto::{self, CtrlMsg}; 6use crate::proto::{self, CtrlMsg};
7 7
8/// Errors reported by control.
8#[derive(Copy, Clone, PartialEq, Eq, Debug)] 9#[derive(Copy, Clone, PartialEq, Eq, Debug)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))] 10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub enum Error { 11pub enum Error {
12 /// The operation failed with the given error code.
11 Failed(u32), 13 Failed(u32),
14 /// The operation timed out.
12 Timeout, 15 Timeout,
16 /// Internal error.
13 Internal, 17 Internal,
14} 18}
15 19
20/// Handle for managing the network and WiFI state.
16pub struct Control<'a> { 21pub struct Control<'a> {
17 state_ch: ch::StateRunner<'a>, 22 state_ch: ch::StateRunner<'a>,
18 shared: &'a Shared, 23 shared: &'a Shared,
19} 24}
20 25
26/// WiFi mode.
21#[allow(unused)] 27#[allow(unused)]
22#[derive(Copy, Clone, PartialEq, Eq, Debug)] 28#[derive(Copy, Clone, PartialEq, Eq, Debug)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))] 29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24enum WifiMode { 30enum WifiMode {
31 /// No mode.
25 None = 0, 32 None = 0,
33 /// Client station.
26 Sta = 1, 34 Sta = 1,
35 /// Access point mode.
27 Ap = 2, 36 Ap = 2,
37 /// Repeater mode.
28 ApSta = 3, 38 ApSta = 3,
29} 39}
30 40
31pub use proto::CtrlWifiSecProt as Security; 41pub use proto::CtrlWifiSecProt as Security;
32 42
43/// WiFi status.
33#[derive(Clone, Debug)] 44#[derive(Clone, Debug)]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))] 45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35pub struct Status { 46pub struct Status {
47 /// Service Set Identifier.
36 pub ssid: String<32>, 48 pub ssid: String<32>,
49 /// Basic Service Set Identifier.
37 pub bssid: [u8; 6], 50 pub bssid: [u8; 6],
51 /// Received Signal Strength Indicator.
38 pub rssi: i32, 52 pub rssi: i32,
53 /// WiFi channel.
39 pub channel: u32, 54 pub channel: u32,
55 /// Security mode.
40 pub security: Security, 56 pub security: Security,
41} 57}
42 58
@@ -65,6 +81,7 @@ impl<'a> Control<'a> {
65 Self { state_ch, shared } 81 Self { state_ch, shared }
66 } 82 }
67 83
84 /// Initialize device.
68 pub async fn init(&mut self) -> Result<(), Error> { 85 pub async fn init(&mut self) -> Result<(), Error> {
69 debug!("wait for init event..."); 86 debug!("wait for init event...");
70 self.shared.init_wait().await; 87 self.shared.init_wait().await;
@@ -82,6 +99,7 @@ impl<'a> Control<'a> {
82 Ok(()) 99 Ok(())
83 } 100 }
84 101
102 /// Get the current status.
85 pub async fn get_status(&mut self) -> Result<Status, Error> { 103 pub async fn get_status(&mut self) -> Result<Status, Error> {
86 let req = proto::CtrlMsgReqGetApConfig {}; 104 let req = proto::CtrlMsgReqGetApConfig {};
87 ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp); 105 ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp);
@@ -95,6 +113,7 @@ impl<'a> Control<'a> {
95 }) 113 })
96 } 114 }
97 115
116 /// Connect to the network identified by ssid using the provided password.
98 pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> { 117 pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
99 let req = proto::CtrlMsgReqConnectAp { 118 let req = proto::CtrlMsgReqConnectAp {
100 ssid: unwrap!(String::try_from(ssid)), 119 ssid: unwrap!(String::try_from(ssid)),
@@ -108,6 +127,7 @@ impl<'a> Control<'a> {
108 Ok(()) 127 Ok(())
109 } 128 }
110 129
130 /// Disconnect from any currently connected network.
111 pub async fn disconnect(&mut self) -> Result<(), Error> { 131 pub async fn disconnect(&mut self) -> Result<(), Error> {
112 let req = proto::CtrlMsgReqGetStatus {}; 132 let req = proto::CtrlMsgReqGetStatus {};
113 ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp); 133 ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp);
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs
index d61eaef3a..c78578bf1 100644
--- a/embassy-net-esp-hosted/src/lib.rs
+++ b/embassy-net-esp-hosted/src/lib.rs
@@ -1,4 +1,6 @@
1#![no_std] 1#![no_std]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
2 4
3use embassy_futures::select::{select4, Either4}; 5use embassy_futures::select::{select4, Either4};
4use embassy_net_driver_channel as ch; 6use embassy_net_driver_channel as ch;
@@ -97,12 +99,14 @@ enum InterfaceType {
97const MAX_SPI_BUFFER_SIZE: usize = 1600; 99const MAX_SPI_BUFFER_SIZE: usize = 1600;
98const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20); 100const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20);
99 101
102/// State for the esp-hosted driver.
100pub struct State { 103pub struct State {
101 shared: Shared, 104 shared: Shared,
102 ch: ch::State<MTU, 4, 4>, 105 ch: ch::State<MTU, 4, 4>,
103} 106}
104 107
105impl State { 108impl State {
109 /// Create a new state.
106 pub fn new() -> Self { 110 pub fn new() -> Self {
107 Self { 111 Self {
108 shared: Shared::new(), 112 shared: Shared::new(),
@@ -111,8 +115,13 @@ impl State {
111 } 115 }
112} 116}
113 117
118/// Type alias for network driver.
114pub type NetDriver<'a> = ch::Device<'a, MTU>; 119pub type NetDriver<'a> = ch::Device<'a, MTU>;
115 120
121/// Create a new esp-hosted driver using the provided state, SPI peripheral and pins.
122///
123/// 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.
116pub async fn new<'a, SPI, IN, OUT>( 125pub async fn new<'a, SPI, IN, OUT>(
117 state: &'a mut State, 126 state: &'a mut State,
118 spi: SPI, 127 spi: SPI,
@@ -144,6 +153,7 @@ where
144 (device, Control::new(state_ch, &state.shared), runner) 153 (device, Control::new(state_ch, &state.shared), runner)
145} 154}
146 155
156/// Runner for communicating with the WiFi device.
147pub struct Runner<'a, SPI, IN, OUT> { 157pub struct Runner<'a, SPI, IN, OUT> {
148 ch: ch::Runner<'a, MTU>, 158 ch: ch::Runner<'a, MTU>,
149 state_ch: ch::StateRunner<'a>, 159 state_ch: ch::StateRunner<'a>,
@@ -166,6 +176,7 @@ where
166{ 176{
167 async fn init(&mut self) {} 177 async fn init(&mut self) {}
168 178
179 /// Run the packet processing.
169 pub async fn run(mut self) -> ! { 180 pub async fn run(mut self) -> ! {
170 debug!("resetting..."); 181 debug!("resetting...");
171 self.reset.set_low().unwrap(); 182 self.reset.set_low().unwrap();
diff --git a/embassy-net-esp-hosted/src/proto.rs b/embassy-net-esp-hosted/src/proto.rs
index 8ceb1579d..034d5bf84 100644
--- a/embassy-net-esp-hosted/src/proto.rs
+++ b/embassy-net-esp-hosted/src/proto.rs
@@ -4,7 +4,7 @@ use heapless::{String, Vec};
4 4
5#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 5#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub struct ScanResult { 7pub(crate) struct ScanResult {
8 #[noproto(tag = "1")] 8 #[noproto(tag = "1")]
9 pub ssid: String<32>, 9 pub ssid: String<32>,
10 #[noproto(tag = "2")] 10 #[noproto(tag = "2")]
@@ -19,7 +19,7 @@ pub struct ScanResult {
19 19
20#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 20#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct ConnectedStaList { 22pub(crate) struct ConnectedStaList {
23 #[noproto(tag = "1")] 23 #[noproto(tag = "1")]
24 pub mac: String<32>, 24 pub mac: String<32>,
25 #[noproto(tag = "2")] 25 #[noproto(tag = "2")]
@@ -29,14 +29,14 @@ pub struct ConnectedStaList {
29 29
30#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 30#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))] 31#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub struct CtrlMsgReqGetMacAddress { 32pub(crate) struct CtrlMsgReqGetMacAddress {
33 #[noproto(tag = "1")] 33 #[noproto(tag = "1")]
34 pub mode: u32, 34 pub mode: u32,
35} 35}
36 36
37#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 37#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))] 38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39pub struct CtrlMsgRespGetMacAddress { 39pub(crate) struct CtrlMsgRespGetMacAddress {
40 #[noproto(tag = "1")] 40 #[noproto(tag = "1")]
41 pub mac: String<32>, 41 pub mac: String<32>,
42 #[noproto(tag = "2")] 42 #[noproto(tag = "2")]
@@ -45,11 +45,11 @@ pub struct CtrlMsgRespGetMacAddress {
45 45
46#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 46#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))] 47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub struct CtrlMsgReqGetMode {} 48pub(crate) struct CtrlMsgReqGetMode {}
49 49
50#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 50#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))] 51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub struct CtrlMsgRespGetMode { 52pub(crate) struct CtrlMsgRespGetMode {
53 #[noproto(tag = "1")] 53 #[noproto(tag = "1")]
54 pub mode: u32, 54 pub mode: u32,
55 #[noproto(tag = "2")] 55 #[noproto(tag = "2")]
@@ -58,32 +58,32 @@ pub struct CtrlMsgRespGetMode {
58 58
59#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 59#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))] 60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub struct CtrlMsgReqSetMode { 61pub(crate) struct CtrlMsgReqSetMode {
62 #[noproto(tag = "1")] 62 #[noproto(tag = "1")]
63 pub mode: u32, 63 pub mode: u32,
64} 64}
65 65
66#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 66#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
67#[cfg_attr(feature = "defmt", derive(defmt::Format))] 67#[cfg_attr(feature = "defmt", derive(defmt::Format))]
68pub struct CtrlMsgRespSetMode { 68pub(crate) struct CtrlMsgRespSetMode {
69 #[noproto(tag = "1")] 69 #[noproto(tag = "1")]
70 pub resp: u32, 70 pub resp: u32,
71} 71}
72 72
73#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 73#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75pub struct CtrlMsgReqGetStatus {} 75pub(crate) struct CtrlMsgReqGetStatus {}
76 76
77#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 77#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))] 78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79pub struct CtrlMsgRespGetStatus { 79pub(crate) struct CtrlMsgRespGetStatus {
80 #[noproto(tag = "1")] 80 #[noproto(tag = "1")]
81 pub resp: u32, 81 pub resp: u32,
82} 82}
83 83
84#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 84#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))] 85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub struct CtrlMsgReqSetMacAddress { 86pub(crate) struct CtrlMsgReqSetMacAddress {
87 #[noproto(tag = "1")] 87 #[noproto(tag = "1")]
88 pub mac: String<32>, 88 pub mac: String<32>,
89 #[noproto(tag = "2")] 89 #[noproto(tag = "2")]
@@ -92,18 +92,18 @@ pub struct CtrlMsgReqSetMacAddress {
92 92
93#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 93#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
94#[cfg_attr(feature = "defmt", derive(defmt::Format))] 94#[cfg_attr(feature = "defmt", derive(defmt::Format))]
95pub struct CtrlMsgRespSetMacAddress { 95pub(crate) struct CtrlMsgRespSetMacAddress {
96 #[noproto(tag = "1")] 96 #[noproto(tag = "1")]
97 pub resp: u32, 97 pub resp: u32,
98} 98}
99 99
100#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 100#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))] 101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102pub struct CtrlMsgReqGetApConfig {} 102pub(crate) struct CtrlMsgReqGetApConfig {}
103 103
104#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 104#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))] 105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub struct CtrlMsgRespGetApConfig { 106pub(crate) struct CtrlMsgRespGetApConfig {
107 #[noproto(tag = "1")] 107 #[noproto(tag = "1")]
108 pub ssid: String<32>, 108 pub ssid: String<32>,
109 #[noproto(tag = "2")] 109 #[noproto(tag = "2")]
@@ -120,7 +120,7 @@ pub struct CtrlMsgRespGetApConfig {
120 120
121#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 121#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
122#[cfg_attr(feature = "defmt", derive(defmt::Format))] 122#[cfg_attr(feature = "defmt", derive(defmt::Format))]
123pub struct CtrlMsgReqConnectAp { 123pub(crate) struct CtrlMsgReqConnectAp {
124 #[noproto(tag = "1")] 124 #[noproto(tag = "1")]
125 pub ssid: String<32>, 125 pub ssid: String<32>,
126 #[noproto(tag = "2")] 126 #[noproto(tag = "2")]
@@ -135,7 +135,7 @@ pub struct CtrlMsgReqConnectAp {
135 135
136#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 136#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
137#[cfg_attr(feature = "defmt", derive(defmt::Format))] 137#[cfg_attr(feature = "defmt", derive(defmt::Format))]
138pub struct CtrlMsgRespConnectAp { 138pub(crate) struct CtrlMsgRespConnectAp {
139 #[noproto(tag = "1")] 139 #[noproto(tag = "1")]
140 pub resp: u32, 140 pub resp: u32,
141 #[noproto(tag = "2")] 141 #[noproto(tag = "2")]
@@ -144,11 +144,11 @@ pub struct CtrlMsgRespConnectAp {
144 144
145#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 145#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
146#[cfg_attr(feature = "defmt", derive(defmt::Format))] 146#[cfg_attr(feature = "defmt", derive(defmt::Format))]
147pub struct CtrlMsgReqGetSoftApConfig {} 147pub(crate) struct CtrlMsgReqGetSoftApConfig {}
148 148
149#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 149#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
150#[cfg_attr(feature = "defmt", derive(defmt::Format))] 150#[cfg_attr(feature = "defmt", derive(defmt::Format))]
151pub struct CtrlMsgRespGetSoftApConfig { 151pub(crate) struct CtrlMsgRespGetSoftApConfig {
152 #[noproto(tag = "1")] 152 #[noproto(tag = "1")]
153 pub ssid: String<32>, 153 pub ssid: String<32>,
154 #[noproto(tag = "2")] 154 #[noproto(tag = "2")]
@@ -169,7 +169,7 @@ pub struct CtrlMsgRespGetSoftApConfig {
169 169
170#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 170#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
171#[cfg_attr(feature = "defmt", derive(defmt::Format))] 171#[cfg_attr(feature = "defmt", derive(defmt::Format))]
172pub struct CtrlMsgReqStartSoftAp { 172pub(crate) struct CtrlMsgReqStartSoftAp {
173 #[noproto(tag = "1")] 173 #[noproto(tag = "1")]
174 pub ssid: String<32>, 174 pub ssid: String<32>,
175 #[noproto(tag = "2")] 175 #[noproto(tag = "2")]
@@ -188,7 +188,7 @@ pub struct CtrlMsgReqStartSoftAp {
188 188
189#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 189#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
190#[cfg_attr(feature = "defmt", derive(defmt::Format))] 190#[cfg_attr(feature = "defmt", derive(defmt::Format))]
191pub struct CtrlMsgRespStartSoftAp { 191pub(crate) struct CtrlMsgRespStartSoftAp {
192 #[noproto(tag = "1")] 192 #[noproto(tag = "1")]
193 pub resp: u32, 193 pub resp: u32,
194 #[noproto(tag = "2")] 194 #[noproto(tag = "2")]
@@ -197,11 +197,11 @@ pub struct CtrlMsgRespStartSoftAp {
197 197
198#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 198#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
199#[cfg_attr(feature = "defmt", derive(defmt::Format))] 199#[cfg_attr(feature = "defmt", derive(defmt::Format))]
200pub struct CtrlMsgReqScanResult {} 200pub(crate) struct CtrlMsgReqScanResult {}
201 201
202#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 202#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
203#[cfg_attr(feature = "defmt", derive(defmt::Format))] 203#[cfg_attr(feature = "defmt", derive(defmt::Format))]
204pub struct CtrlMsgRespScanResult { 204pub(crate) struct CtrlMsgRespScanResult {
205 #[noproto(tag = "1")] 205 #[noproto(tag = "1")]
206 pub count: u32, 206 pub count: u32,
207 #[noproto(repeated, tag = "2")] 207 #[noproto(repeated, tag = "2")]
@@ -212,11 +212,11 @@ pub struct CtrlMsgRespScanResult {
212 212
213#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 213#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
214#[cfg_attr(feature = "defmt", derive(defmt::Format))] 214#[cfg_attr(feature = "defmt", derive(defmt::Format))]
215pub struct CtrlMsgReqSoftApConnectedSta {} 215pub(crate) struct CtrlMsgReqSoftApConnectedSta {}
216 216
217#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 217#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
218#[cfg_attr(feature = "defmt", derive(defmt::Format))] 218#[cfg_attr(feature = "defmt", derive(defmt::Format))]
219pub struct CtrlMsgRespSoftApConnectedSta { 219pub(crate) struct CtrlMsgRespSoftApConnectedSta {
220 #[noproto(tag = "1")] 220 #[noproto(tag = "1")]
221 pub num: u32, 221 pub num: u32,
222 #[noproto(repeated, tag = "2")] 222 #[noproto(repeated, tag = "2")]
@@ -227,43 +227,43 @@ pub struct CtrlMsgRespSoftApConnectedSta {
227 227
228#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 228#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
229#[cfg_attr(feature = "defmt", derive(defmt::Format))] 229#[cfg_attr(feature = "defmt", derive(defmt::Format))]
230pub struct CtrlMsgReqOtaBegin {} 230pub(crate) struct CtrlMsgReqOtaBegin {}
231 231
232#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 232#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
233#[cfg_attr(feature = "defmt", derive(defmt::Format))] 233#[cfg_attr(feature = "defmt", derive(defmt::Format))]
234pub struct CtrlMsgRespOtaBegin { 234pub(crate) struct CtrlMsgRespOtaBegin {
235 #[noproto(tag = "1")] 235 #[noproto(tag = "1")]
236 pub resp: u32, 236 pub resp: u32,
237} 237}
238 238
239#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 239#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
240#[cfg_attr(feature = "defmt", derive(defmt::Format))] 240#[cfg_attr(feature = "defmt", derive(defmt::Format))]
241pub struct CtrlMsgReqOtaWrite { 241pub(crate) struct CtrlMsgReqOtaWrite {
242 #[noproto(tag = "1")] 242 #[noproto(tag = "1")]
243 pub ota_data: Vec<u8, 1024>, 243 pub ota_data: Vec<u8, 1024>,
244} 244}
245 245
246#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 246#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
247#[cfg_attr(feature = "defmt", derive(defmt::Format))] 247#[cfg_attr(feature = "defmt", derive(defmt::Format))]
248pub struct CtrlMsgRespOtaWrite { 248pub(crate) struct CtrlMsgRespOtaWrite {
249 #[noproto(tag = "1")] 249 #[noproto(tag = "1")]
250 pub resp: u32, 250 pub resp: u32,
251} 251}
252 252
253#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 253#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
254#[cfg_attr(feature = "defmt", derive(defmt::Format))] 254#[cfg_attr(feature = "defmt", derive(defmt::Format))]
255pub struct CtrlMsgReqOtaEnd {} 255pub(crate) struct CtrlMsgReqOtaEnd {}
256 256
257#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 257#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
258#[cfg_attr(feature = "defmt", derive(defmt::Format))] 258#[cfg_attr(feature = "defmt", derive(defmt::Format))]
259pub struct CtrlMsgRespOtaEnd { 259pub(crate) struct CtrlMsgRespOtaEnd {
260 #[noproto(tag = "1")] 260 #[noproto(tag = "1")]
261 pub resp: u32, 261 pub resp: u32,
262} 262}
263 263
264#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 264#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
265#[cfg_attr(feature = "defmt", derive(defmt::Format))] 265#[cfg_attr(feature = "defmt", derive(defmt::Format))]
266pub struct CtrlMsgReqVendorIeData { 266pub(crate) struct CtrlMsgReqVendorIeData {
267 #[noproto(tag = "1")] 267 #[noproto(tag = "1")]
268 pub element_id: u32, 268 pub element_id: u32,
269 #[noproto(tag = "2")] 269 #[noproto(tag = "2")]
@@ -278,7 +278,7 @@ pub struct CtrlMsgReqVendorIeData {
278 278
279#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 279#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
280#[cfg_attr(feature = "defmt", derive(defmt::Format))] 280#[cfg_attr(feature = "defmt", derive(defmt::Format))]
281pub struct CtrlMsgReqSetSoftApVendorSpecificIe { 281pub(crate) struct CtrlMsgReqSetSoftApVendorSpecificIe {
282 #[noproto(tag = "1")] 282 #[noproto(tag = "1")]
283 pub enable: bool, 283 pub enable: bool,
284 #[noproto(tag = "2")] 284 #[noproto(tag = "2")]
@@ -291,32 +291,32 @@ pub struct CtrlMsgReqSetSoftApVendorSpecificIe {
291 291
292#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 292#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
293#[cfg_attr(feature = "defmt", derive(defmt::Format))] 293#[cfg_attr(feature = "defmt", derive(defmt::Format))]
294pub struct CtrlMsgRespSetSoftApVendorSpecificIe { 294pub(crate) struct CtrlMsgRespSetSoftApVendorSpecificIe {
295 #[noproto(tag = "1")] 295 #[noproto(tag = "1")]
296 pub resp: u32, 296 pub resp: u32,
297} 297}
298 298
299#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 299#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
300#[cfg_attr(feature = "defmt", derive(defmt::Format))] 300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301pub struct CtrlMsgReqSetWifiMaxTxPower { 301pub(crate) struct CtrlMsgReqSetWifiMaxTxPower {
302 #[noproto(tag = "1")] 302 #[noproto(tag = "1")]
303 pub wifi_max_tx_power: u32, 303 pub wifi_max_tx_power: u32,
304} 304}
305 305
306#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 306#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
307#[cfg_attr(feature = "defmt", derive(defmt::Format))] 307#[cfg_attr(feature = "defmt", derive(defmt::Format))]
308pub struct CtrlMsgRespSetWifiMaxTxPower { 308pub(crate) struct CtrlMsgRespSetWifiMaxTxPower {
309 #[noproto(tag = "1")] 309 #[noproto(tag = "1")]
310 pub resp: u32, 310 pub resp: u32,
311} 311}
312 312
313#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 313#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
314#[cfg_attr(feature = "defmt", derive(defmt::Format))] 314#[cfg_attr(feature = "defmt", derive(defmt::Format))]
315pub struct CtrlMsgReqGetWifiCurrTxPower {} 315pub(crate) struct CtrlMsgReqGetWifiCurrTxPower {}
316 316
317#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 317#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
318#[cfg_attr(feature = "defmt", derive(defmt::Format))] 318#[cfg_attr(feature = "defmt", derive(defmt::Format))]
319pub struct CtrlMsgRespGetWifiCurrTxPower { 319pub(crate) struct CtrlMsgRespGetWifiCurrTxPower {
320 #[noproto(tag = "1")] 320 #[noproto(tag = "1")]
321 pub wifi_curr_tx_power: u32, 321 pub wifi_curr_tx_power: u32,
322 #[noproto(tag = "2")] 322 #[noproto(tag = "2")]
@@ -325,7 +325,7 @@ pub struct CtrlMsgRespGetWifiCurrTxPower {
325 325
326#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 326#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
327#[cfg_attr(feature = "defmt", derive(defmt::Format))] 327#[cfg_attr(feature = "defmt", derive(defmt::Format))]
328pub struct CtrlMsgReqConfigHeartbeat { 328pub(crate) struct CtrlMsgReqConfigHeartbeat {
329 #[noproto(tag = "1")] 329 #[noproto(tag = "1")]
330 pub enable: bool, 330 pub enable: bool,
331 #[noproto(tag = "2")] 331 #[noproto(tag = "2")]
@@ -334,7 +334,7 @@ pub struct CtrlMsgReqConfigHeartbeat {
334 334
335#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 335#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
336#[cfg_attr(feature = "defmt", derive(defmt::Format))] 336#[cfg_attr(feature = "defmt", derive(defmt::Format))]
337pub struct CtrlMsgRespConfigHeartbeat { 337pub(crate) struct CtrlMsgRespConfigHeartbeat {
338 #[noproto(tag = "1")] 338 #[noproto(tag = "1")]
339 pub resp: u32, 339 pub resp: u32,
340} 340}
@@ -342,28 +342,28 @@ pub struct CtrlMsgRespConfigHeartbeat {
342 342
343#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 343#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
344#[cfg_attr(feature = "defmt", derive(defmt::Format))] 344#[cfg_attr(feature = "defmt", derive(defmt::Format))]
345pub struct CtrlMsgEventEspInit { 345pub(crate) struct CtrlMsgEventEspInit {
346 #[noproto(tag = "1")] 346 #[noproto(tag = "1")]
347 pub init_data: Vec<u8, 64>, 347 pub init_data: Vec<u8, 64>,
348} 348}
349 349
350#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 350#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
351#[cfg_attr(feature = "defmt", derive(defmt::Format))] 351#[cfg_attr(feature = "defmt", derive(defmt::Format))]
352pub struct CtrlMsgEventHeartbeat { 352pub(crate) struct CtrlMsgEventHeartbeat {
353 #[noproto(tag = "1")] 353 #[noproto(tag = "1")]
354 pub hb_num: u32, 354 pub hb_num: u32,
355} 355}
356 356
357#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 357#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
358#[cfg_attr(feature = "defmt", derive(defmt::Format))] 358#[cfg_attr(feature = "defmt", derive(defmt::Format))]
359pub struct CtrlMsgEventStationDisconnectFromAp { 359pub(crate) struct CtrlMsgEventStationDisconnectFromAp {
360 #[noproto(tag = "1")] 360 #[noproto(tag = "1")]
361 pub resp: u32, 361 pub resp: u32,
362} 362}
363 363
364#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 364#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
365#[cfg_attr(feature = "defmt", derive(defmt::Format))] 365#[cfg_attr(feature = "defmt", derive(defmt::Format))]
366pub struct CtrlMsgEventStationDisconnectFromEspSoftAp { 366pub(crate) struct CtrlMsgEventStationDisconnectFromEspSoftAp {
367 #[noproto(tag = "1")] 367 #[noproto(tag = "1")]
368 pub resp: u32, 368 pub resp: u32,
369 #[noproto(tag = "2")] 369 #[noproto(tag = "2")]
@@ -372,7 +372,7 @@ pub struct CtrlMsgEventStationDisconnectFromEspSoftAp {
372 372
373#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] 373#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
374#[cfg_attr(feature = "defmt", derive(defmt::Format))] 374#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375pub struct CtrlMsg { 375pub(crate) struct CtrlMsg {
376 /// msg_type could be req, resp or Event 376 /// msg_type could be req, resp or Event
377 #[noproto(tag = "1")] 377 #[noproto(tag = "1")]
378 pub msg_type: CtrlMsgType, 378 pub msg_type: CtrlMsgType,
@@ -390,7 +390,7 @@ pub struct CtrlMsg {
390/// union of all msg ids 390/// union of all msg ids
391#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)] 391#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)]
392#[cfg_attr(feature = "defmt", derive(defmt::Format))] 392#[cfg_attr(feature = "defmt", derive(defmt::Format))]
393pub enum CtrlMsgPayload { 393pub(crate) enum CtrlMsgPayload {
394 /// * Requests * 394 /// * Requests *
395 #[noproto(tag = "101")] 395 #[noproto(tag = "101")]
396 ReqGetMacAddress(CtrlMsgReqGetMacAddress), 396 ReqGetMacAddress(CtrlMsgReqGetMacAddress),
@@ -492,7 +492,7 @@ pub enum CtrlMsgPayload {
492#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 492#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
493#[repr(u32)] 493#[repr(u32)]
494#[cfg_attr(feature = "defmt", derive(defmt::Format))] 494#[cfg_attr(feature = "defmt", derive(defmt::Format))]
495pub enum CtrlVendorIeType { 495pub(crate) enum CtrlVendorIeType {
496 #[default] 496 #[default]
497 Beacon = 0, 497 Beacon = 0,
498 ProbeReq = 1, 498 ProbeReq = 1,
@@ -504,7 +504,7 @@ pub enum CtrlVendorIeType {
504#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 504#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
505#[repr(u32)] 505#[repr(u32)]
506#[cfg_attr(feature = "defmt", derive(defmt::Format))] 506#[cfg_attr(feature = "defmt", derive(defmt::Format))]
507pub enum CtrlVendorIeid { 507pub(crate) enum CtrlVendorIeid {
508 #[default] 508 #[default]
509 Id0 = 0, 509 Id0 = 0,
510 Id1 = 1, 510 Id1 = 1,
@@ -513,7 +513,7 @@ pub enum CtrlVendorIeid {
513#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 513#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
514#[repr(u32)] 514#[repr(u32)]
515#[cfg_attr(feature = "defmt", derive(defmt::Format))] 515#[cfg_attr(feature = "defmt", derive(defmt::Format))]
516pub enum CtrlWifiMode { 516pub(crate) enum CtrlWifiMode {
517 #[default] 517 #[default]
518 None = 0, 518 None = 0,
519 Sta = 1, 519 Sta = 1,
@@ -524,7 +524,7 @@ pub enum CtrlWifiMode {
524#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 524#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
525#[repr(u32)] 525#[repr(u32)]
526#[cfg_attr(feature = "defmt", derive(defmt::Format))] 526#[cfg_attr(feature = "defmt", derive(defmt::Format))]
527pub enum CtrlWifiBw { 527pub(crate) enum CtrlWifiBw {
528 #[default] 528 #[default]
529 BwInvalid = 0, 529 BwInvalid = 0,
530 Ht20 = 1, 530 Ht20 = 1,
@@ -534,13 +534,15 @@ pub enum CtrlWifiBw {
534#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 534#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
535#[repr(u32)] 535#[repr(u32)]
536#[cfg_attr(feature = "defmt", derive(defmt::Format))] 536#[cfg_attr(feature = "defmt", derive(defmt::Format))]
537pub enum CtrlWifiPowerSave { 537pub(crate) enum CtrlWifiPowerSave {
538 #[default] 538 #[default]
539 PsInvalid = 0, 539 PsInvalid = 0,
540 MinModem = 1, 540 MinModem = 1,
541 MaxModem = 2, 541 MaxModem = 2,
542} 542}
543 543
544/// Wifi Security Settings
545#[allow(missing_docs)]
544#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 546#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
545#[repr(u32)] 547#[repr(u32)]
546#[cfg_attr(feature = "defmt", derive(defmt::Format))] 548#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -560,7 +562,7 @@ pub enum CtrlWifiSecProt {
560#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 562#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
561#[repr(u32)] 563#[repr(u32)]
562#[cfg_attr(feature = "defmt", derive(defmt::Format))] 564#[cfg_attr(feature = "defmt", derive(defmt::Format))]
563pub enum CtrlStatus { 565pub(crate) enum CtrlStatus {
564 #[default] 566 #[default]
565 Connected = 0, 567 Connected = 0,
566 NotConnected = 1, 568 NotConnected = 1,
@@ -573,7 +575,7 @@ pub enum CtrlStatus {
573#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 575#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
574#[repr(u32)] 576#[repr(u32)]
575#[cfg_attr(feature = "defmt", derive(defmt::Format))] 577#[cfg_attr(feature = "defmt", derive(defmt::Format))]
576pub enum CtrlMsgType { 578pub(crate) enum CtrlMsgType {
577 #[default] 579 #[default]
578 MsgTypeInvalid = 0, 580 MsgTypeInvalid = 0,
579 Req = 1, 581 Req = 1,
@@ -585,7 +587,7 @@ pub enum CtrlMsgType {
585#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] 587#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
586#[repr(u32)] 588#[repr(u32)]
587#[cfg_attr(feature = "defmt", derive(defmt::Format))] 589#[cfg_attr(feature = "defmt", derive(defmt::Format))]
588pub enum CtrlMsgId { 590pub(crate) enum CtrlMsgId {
589 #[default] 591 #[default]
590 MsgIdInvalid = 0, 592 MsgIdInvalid = 0,
591 /// * Request Msgs * 593 /// * Request Msgs *
diff --git a/embassy-net-tuntap/Cargo.toml b/embassy-net-tuntap/Cargo.toml
index 4e374c365..7e2c7bfd5 100644
--- a/embassy-net-tuntap/Cargo.toml
+++ b/embassy-net-tuntap/Cargo.toml
@@ -6,6 +6,7 @@ keywords = ["embedded", "tuntap", "embassy-net", "embedded-hal-async", "ethernet
6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] 6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
7license = "MIT OR Apache-2.0" 7license = "MIT OR Apache-2.0"
8edition = "2021" 8edition = "2021"
9repository = "https://github.com/embassy-rs/embassy"
9 10
10[dependencies] 11[dependencies]
11embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } 12embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
@@ -16,4 +17,4 @@ libc = "0.2.101"
16[package.metadata.embassy_docs] 17[package.metadata.embassy_docs]
17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-tuntap-v$VERSION/embassy-net-tuntap/src/" 18src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-tuntap-v$VERSION/embassy-net-tuntap/src/"
18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-tuntap/src/" 19src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-tuntap/src/"
19target = "thumbv7em-none-eabi" \ No newline at end of file 20target = "thumbv7em-none-eabi"
diff --git a/embassy-net-tuntap/src/lib.rs b/embassy-net-tuntap/src/lib.rs
index 75c54c487..de30934eb 100644
--- a/embassy-net-tuntap/src/lib.rs
+++ b/embassy-net-tuntap/src/lib.rs
@@ -1,3 +1,5 @@
1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
1use std::io; 3use std::io;
2use std::io::{Read, Write}; 4use std::io::{Read, Write};
3use std::os::unix::io::{AsRawFd, RawFd}; 5use std::os::unix::io::{AsRawFd, RawFd};
@@ -7,12 +9,19 @@ use async_io::Async;
7use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; 9use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState};
8use log::*; 10use log::*;
9 11
12/// Get the MTU of the given interface.
10pub const SIOCGIFMTU: libc::c_ulong = 0x8921; 13pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
14/// Get the index of the given interface.
11pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933; 15pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933;
16/// Capture all packages.
12pub const _ETH_P_ALL: libc::c_short = 0x0003; 17pub const _ETH_P_ALL: libc::c_short = 0x0003;
18/// Set the interface flags.
13pub const TUNSETIFF: libc::c_ulong = 0x400454CA; 19pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
20/// TUN device.
14pub const _IFF_TUN: libc::c_int = 0x0001; 21pub const _IFF_TUN: libc::c_int = 0x0001;
22/// TAP device.
15pub const IFF_TAP: libc::c_int = 0x0002; 23pub const IFF_TAP: libc::c_int = 0x0002;
24/// No packet information.
16pub const IFF_NO_PI: libc::c_int = 0x1000; 25pub const IFF_NO_PI: libc::c_int = 0x1000;
17 26
18const ETHERNET_HEADER_LEN: usize = 14; 27const ETHERNET_HEADER_LEN: usize = 14;
@@ -47,6 +56,7 @@ fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, cmd: libc::c_ulong) -> io:
47 Ok(ifreq.ifr_data) 56 Ok(ifreq.ifr_data)
48} 57}
49 58
59/// A TUN/TAP device.
50#[derive(Debug)] 60#[derive(Debug)]
51pub struct TunTap { 61pub struct TunTap {
52 fd: libc::c_int, 62 fd: libc::c_int,
@@ -60,6 +70,7 @@ impl AsRawFd for TunTap {
60} 70}
61 71
62impl TunTap { 72impl TunTap {
73 /// Create a new TUN/TAP device.
63 pub fn new(name: &str) -> io::Result<TunTap> { 74 pub fn new(name: &str) -> io::Result<TunTap> {
64 unsafe { 75 unsafe {
65 let fd = libc::open( 76 let fd = libc::open(
@@ -126,11 +137,13 @@ impl io::Write for TunTap {
126 } 137 }
127} 138}
128 139
140/// A TUN/TAP device, wrapped in an async interface.
129pub struct TunTapDevice { 141pub struct TunTapDevice {
130 device: Async<TunTap>, 142 device: Async<TunTap>,
131} 143}
132 144
133impl TunTapDevice { 145impl TunTapDevice {
146 /// Create a new TUN/TAP device.
134 pub fn new(name: &str) -> io::Result<TunTapDevice> { 147 pub fn new(name: &str) -> io::Result<TunTapDevice> {
135 Ok(Self { 148 Ok(Self {
136 device: Async::new(TunTap::new(name)?)?, 149 device: Async::new(TunTap::new(name)?)?,
diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml
index a1f0b0c51..f628d8bd1 100644
--- a/embassy-net-wiznet/Cargo.toml
+++ b/embassy-net-wiznet/Cargo.toml
@@ -6,6 +6,7 @@ keywords = ["embedded", "wiznet", "embassy-net", "embedded-hal-async", "ethernet
6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] 6categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
7license = "MIT OR Apache-2.0" 7license = "MIT OR Apache-2.0"
8edition = "2021" 8edition = "2021"
9repository = "https://github.com/embassy-rs/embassy"
9 10
10[dependencies] 11[dependencies]
11embedded-hal = { version = "1.0.0-rc.3" } 12embedded-hal = { version = "1.0.0-rc.3" }
diff --git a/embassy-net-wiznet/src/chip/mod.rs b/embassy-net-wiznet/src/chip/mod.rs
index 562db515a..b987c2b36 100644
--- a/embassy-net-wiznet/src/chip/mod.rs
+++ b/embassy-net-wiznet/src/chip/mod.rs
@@ -1,3 +1,4 @@
1//! Wiznet W5100s and W5500 family driver.
1mod w5500; 2mod w5500;
2pub use w5500::W5500; 3pub use w5500::W5500;
3mod w5100s; 4mod w5100s;
@@ -45,4 +46,5 @@ pub(crate) mod sealed {
45 } 46 }
46} 47}
47 48
49/// Trait for Wiznet chips.
48pub trait Chip: sealed::Chip {} 50pub trait Chip: sealed::Chip {}
diff --git a/embassy-net-wiznet/src/chip/w5100s.rs b/embassy-net-wiznet/src/chip/w5100s.rs
index 07a840370..7d328bce5 100644
--- a/embassy-net-wiznet/src/chip/w5100s.rs
+++ b/embassy-net-wiznet/src/chip/w5100s.rs
@@ -4,6 +4,7 @@ const SOCKET_BASE: u16 = 0x400;
4const TX_BASE: u16 = 0x4000; 4const TX_BASE: u16 = 0x4000;
5const RX_BASE: u16 = 0x6000; 5const RX_BASE: u16 = 0x6000;
6 6
7/// Wizard W5100S chip.
7pub enum W5100S {} 8pub enum W5100S {}
8 9
9impl super::Chip for W5100S {} 10impl super::Chip for W5100S {}
diff --git a/embassy-net-wiznet/src/chip/w5500.rs b/embassy-net-wiznet/src/chip/w5500.rs
index 61e512946..16236126d 100644
--- a/embassy-net-wiznet/src/chip/w5500.rs
+++ b/embassy-net-wiznet/src/chip/w5500.rs
@@ -8,6 +8,7 @@ pub enum RegisterBlock {
8 RxBuf = 0x03, 8 RxBuf = 0x03,
9} 9}
10 10
11/// Wiznet W5500 chip.
11pub enum W5500 {} 12pub enum W5500 {}
12 13
13impl super::Chip for W5500 {} 14impl super::Chip for W5500 {}
diff --git a/embassy-net-wiznet/src/lib.rs b/embassy-net-wiznet/src/lib.rs
index f26f2bbb7..da70d22bd 100644
--- a/embassy-net-wiznet/src/lib.rs
+++ b/embassy-net-wiznet/src/lib.rs
@@ -1,6 +1,7 @@
1#![no_std] 1#![no_std]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")] 3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
4 5
5pub mod chip; 6pub mod chip;
6mod device; 7mod device;
@@ -47,6 +48,7 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
47 48
48/// You must call this in a background task for the driver to operate. 49/// You must call this in a background task for the driver to operate.
49impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> { 50impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
51 /// Run the driver.
50 pub async fn run(mut self) -> ! { 52 pub async fn run(mut self) -> ! {
51 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); 53 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
52 let mut tick = Ticker::every(Duration::from_millis(500)); 54 let mut tick = Ticker::every(Duration::from_millis(500));
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index bf1468642..d970d0332 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -411,10 +411,12 @@ impl<D: Driver> Stack<D> {
411 /// ```ignore 411 /// ```ignore
412 /// let config = embassy_net::Config::dhcpv4(Default::default()); 412 /// let config = embassy_net::Config::dhcpv4(Default::default());
413 ///// Init network stack 413 ///// Init network stack
414 /// let stack = &*make_static!(embassy_net::Stack::new( 414 /// static RESOURCES: StaticCell<embassy_net::StackResources<2> = StaticCell::new();
415 /// static STACK: StaticCell<embassy_net::Stack> = StaticCell::new();
416 /// let stack = &*STACK.init(embassy_net::Stack::new(
415 /// device, 417 /// device,
416 /// config, 418 /// config,
417 /// make_static!(embassy_net::StackResources::<2>::new()), 419 /// RESOURCES.init(embassy_net::StackResources::new()),
418 /// seed 420 /// seed
419 /// )); 421 /// ));
420 /// // Launch network task that runs `stack.run().await` 422 /// // Launch network task that runs `stack.run().await`
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 6d7440519..970f62b0c 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -64,6 +64,11 @@ nfc-pins-as-gpio = []
64# nrf52820, nrf52833, nrf52840: P0_18 64# nrf52820, nrf52833, nrf52840: P0_18
65reset-pin-as-gpio = [] 65reset-pin-as-gpio = []
66 66
67# Implements the MultiwriteNorFlash trait for QSPI. Should only be enabled if your external
68# flash supports the semantics described in
69# https://docs.rs/embedded-storage/0.3.1/embedded_storage/nor_flash/trait.MultiwriteNorFlash.html
70qspi-multiwrite-flash = []
71
67# Features starting with `_` are for internal use only. They're not intended 72# Features starting with `_` are for internal use only. They're not intended
68# to be enabled by other crates, and are not covered by semver guarantees. 73# to be enabled by other crates, and are not covered by semver guarantees.
69 74
diff --git a/embassy-nrf/README.md b/embassy-nrf/README.md
index 129ec0c01..39de3854b 100644
--- a/embassy-nrf/README.md
+++ b/embassy-nrf/README.md
@@ -6,6 +6,8 @@ The Embassy nRF HAL targets the Nordic Semiconductor nRF family of hardware. The
6for many peripherals. The benefit of using the async APIs is that the HAL takes care of waiting for peripherals to 6for many peripherals. The benefit of using the async APIs is that the HAL takes care of waiting for peripherals to
7complete operations in low power mod and handling interrupts, so that applications can focus on more important matters. 7complete operations in low power mod and handling interrupts, so that applications can focus on more important matters.
8 8
9NOTE: The Embassy HALs can be used both for non-async and async operations. For async, you can choose which runtime you want to use.
10
9## EasyDMA considerations 11## EasyDMA considerations
10 12
11On nRF chips, peripherals can use the so called EasyDMA feature to offload the task of interacting 13On nRF chips, peripherals can use the so called EasyDMA feature to offload the task of interacting
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index 85977a804..a47fb8350 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -50,19 +50,19 @@ impl<'d, T: Pin> Input<'d, T> {
50 Self { pin } 50 Self { pin }
51 } 51 }
52 52
53 /// Test if current pin level is high. 53 /// Get whether the pin input level is high.
54 #[inline] 54 #[inline]
55 pub fn is_high(&mut self) -> bool { 55 pub fn is_high(&mut self) -> bool {
56 self.pin.is_high() 56 self.pin.is_high()
57 } 57 }
58 58
59 /// Test if current pin level is low. 59 /// Get whether the pin input level is low.
60 #[inline] 60 #[inline]
61 pub fn is_low(&mut self) -> bool { 61 pub fn is_low(&mut self) -> bool {
62 self.pin.is_low() 62 self.pin.is_low()
63 } 63 }
64 64
65 /// Returns current pin level 65 /// Get the pin input level.
66 #[inline] 66 #[inline]
67 pub fn get_level(&mut self) -> Level { 67 pub fn get_level(&mut self) -> Level {
68 self.pin.get_level() 68 self.pin.get_level()
@@ -158,19 +158,19 @@ impl<'d, T: Pin> Output<'d, T> {
158 self.pin.set_level(level) 158 self.pin.set_level(level)
159 } 159 }
160 160
161 /// Is the output pin set as high? 161 /// Get whether the output level is set to high.
162 #[inline] 162 #[inline]
163 pub fn is_set_high(&mut self) -> bool { 163 pub fn is_set_high(&mut self) -> bool {
164 self.pin.is_set_high() 164 self.pin.is_set_high()
165 } 165 }
166 166
167 /// Is the output pin set as low? 167 /// Get whether the output level is set to low.
168 #[inline] 168 #[inline]
169 pub fn is_set_low(&mut self) -> bool { 169 pub fn is_set_low(&mut self) -> bool {
170 self.pin.is_set_low() 170 self.pin.is_set_low()
171 } 171 }
172 172
173 /// What level output is set to 173 /// Get the current output level.
174 #[inline] 174 #[inline]
175 pub fn get_output_level(&mut self) -> Level { 175 pub fn get_output_level(&mut self) -> Level {
176 self.pin.get_output_level() 176 self.pin.get_output_level()
@@ -275,13 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> {
275 self.pin.conf().reset(); 275 self.pin.conf().reset();
276 } 276 }
277 277
278 /// Test if current pin level is high. 278 /// Get whether the pin input level is high.
279 #[inline] 279 #[inline]
280 pub fn is_high(&mut self) -> bool { 280 pub fn is_high(&mut self) -> bool {
281 !self.is_low() 281 !self.is_low()
282 } 282 }
283 283
284 /// Test if current pin level is low. 284 /// Get whether the pin input level is low.
285 #[inline] 285 #[inline]
286 pub fn is_low(&mut self) -> bool { 286 pub fn is_low(&mut self) -> bool {
287 self.ref_is_low() 287 self.ref_is_low()
@@ -292,7 +292,7 @@ impl<'d, T: Pin> Flex<'d, T> {
292 self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 292 self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0
293 } 293 }
294 294
295 /// Returns current pin level 295 /// Get the pin input level.
296 #[inline] 296 #[inline]
297 pub fn get_level(&mut self) -> Level { 297 pub fn get_level(&mut self) -> Level {
298 self.is_high().into() 298 self.is_high().into()
@@ -319,25 +319,24 @@ impl<'d, T: Pin> Flex<'d, T> {
319 } 319 }
320 } 320 }
321 321
322 /// Is the output pin set as high? 322 /// Get whether the output level is set to high.
323 #[inline] 323 #[inline]
324 pub fn is_set_high(&mut self) -> bool { 324 pub fn is_set_high(&mut self) -> bool {
325 !self.is_set_low() 325 !self.is_set_low()
326 } 326 }
327 327
328 /// Is the output pin set as low? 328 /// Get whether the output level is set to low.
329 #[inline] 329 #[inline]
330 pub fn is_set_low(&mut self) -> bool { 330 pub fn is_set_low(&mut self) -> bool {
331 self.ref_is_set_low() 331 self.ref_is_set_low()
332 } 332 }
333 333
334 /// Is the output pin set as low?
335 #[inline] 334 #[inline]
336 pub(crate) fn ref_is_set_low(&self) -> bool { 335 pub(crate) fn ref_is_set_low(&self) -> bool {
337 self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0 336 self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0
338 } 337 }
339 338
340 /// What level output is set to 339 /// Get the current output level.
341 #[inline] 340 #[inline]
342 pub fn get_output_level(&mut self) -> Level { 341 pub fn get_output_level(&mut self) -> Level {
343 self.is_set_high().into() 342 self.is_set_high().into()
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 9093ad919..e3458e2de 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -354,7 +354,11 @@ unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteRe
354 WriteResult::Written 354 WriteResult::Written
355} 355}
356 356
357/// Initialize peripherals with the provided configuration. This should only be called once at startup. 357/// Initialize the `embassy-nrf` HAL with the provided configuration.
358///
359/// This returns the peripheral singletons that can be used for creating drivers.
360///
361/// This should only be called once at startup, otherwise it panics.
358pub fn init(config: config::Config) -> Peripherals { 362pub fn init(config: config::Config) -> Peripherals {
359 // Do this first, so that it panics if user is calling `init` a second time 363 // Do this first, so that it panics if user is calling `init` a second time
360 // before doing anything important. 364 // before doing anything important.
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index 5e1a4e842..f35b83628 100755
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -605,6 +605,9 @@ impl<'d, T: Instance> NorFlash for Qspi<'d, T> {
605 } 605 }
606} 606}
607 607
608#[cfg(feature = "qspi-multiwrite-flash")]
609impl<'d, T: Instance> embedded_storage::nor_flash::MultiwriteNorFlash for Qspi<'d, T> {}
610
608mod _eh1 { 611mod _eh1 {
609 use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash}; 612 use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
610 613
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index c557940b1..93dad68ce 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -87,5 +87,5 @@ pio = {version= "0.2.1" }
87rp2040-boot2 = "0.3" 87rp2040-boot2 = "0.3"
88 88
89[dev-dependencies] 89[dev-dependencies]
90embassy-executor = { version = "0.4.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] } 90embassy-executor = { version = "0.4.0", path = "../embassy-executor", features = ["arch-std", "executor-thread"] }
91static_cell = { version = "2" } 91static_cell = { version = "2" }
diff --git a/embassy-rp/README.md b/embassy-rp/README.md
new file mode 100644
index 000000000..cd79fe501
--- /dev/null
+++ b/embassy-rp/README.md
@@ -0,0 +1,23 @@
1# Embassy RP HAL
2
3HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed.
4
5The Embassy RP HAL targets the Raspberry Pi 2040 family of hardware. The HAL implements both blocking and async APIs
6for many peripherals. The benefit of using the async APIs is that the HAL takes care of waiting for peripherals to
7complete operations in low power mod and handling interrupts, so that applications can focus on more important matters.
8
9NOTE: The Embassy HALs can be used both for non-async and async operations. For async, you can choose which runtime you want to use.
10
11## Minimum supported Rust version (MSRV)
12
13Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
14
15## License
16
17This work is licensed under either of
18
19- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
20 <http://www.apache.org/licenses/LICENSE-2.0>)
21- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
22
23at your option.
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index 5b913f156..21360bf66 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -1,3 +1,4 @@
1//! ADC driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::mem; 4use core::mem;
@@ -16,6 +17,7 @@ use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt};
16 17
17static WAKER: AtomicWaker = AtomicWaker::new(); 18static WAKER: AtomicWaker = AtomicWaker::new();
18 19
20/// ADC config.
19#[non_exhaustive] 21#[non_exhaustive]
20pub struct Config {} 22pub struct Config {}
21 23
@@ -30,9 +32,11 @@ enum Source<'p> {
30 TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), 32 TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
31} 33}
32 34
35/// ADC channel.
33pub struct Channel<'p>(Source<'p>); 36pub struct Channel<'p>(Source<'p>);
34 37
35impl<'p> Channel<'p> { 38impl<'p> Channel<'p> {
39 /// Create a new ADC channel from pin with the provided [Pull] configuration.
36 pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { 40 pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
37 into_ref!(pin); 41 into_ref!(pin);
38 pin.pad_ctrl().modify(|w| { 42 pin.pad_ctrl().modify(|w| {
@@ -49,6 +53,7 @@ impl<'p> Channel<'p> {
49 Self(Source::Pin(pin.map_into())) 53 Self(Source::Pin(pin.map_into()))
50 } 54 }
51 55
56 /// Create a new ADC channel for the internal temperature sensor.
52 pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self { 57 pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
53 let r = pac::ADC; 58 let r = pac::ADC;
54 r.cs().write_set(|w| w.set_ts_en(true)); 59 r.cs().write_set(|w| w.set_ts_en(true));
@@ -83,35 +88,44 @@ impl<'p> Drop for Source<'p> {
83 } 88 }
84} 89}
85 90
91/// ADC sample.
86#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] 92#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))] 93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88#[repr(transparent)] 94#[repr(transparent)]
89pub struct Sample(u16); 95pub struct Sample(u16);
90 96
91impl Sample { 97impl Sample {
98 /// Sample is valid.
92 pub fn good(&self) -> bool { 99 pub fn good(&self) -> bool {
93 self.0 < 0x8000 100 self.0 < 0x8000
94 } 101 }
95 102
103 /// Sample value.
96 pub fn value(&self) -> u16 { 104 pub fn value(&self) -> u16 {
97 self.0 & !0x8000 105 self.0 & !0x8000
98 } 106 }
99} 107}
100 108
109/// ADC error.
101#[derive(Debug, Eq, PartialEq, Copy, Clone)] 110#[derive(Debug, Eq, PartialEq, Copy, Clone)]
102#[cfg_attr(feature = "defmt", derive(defmt::Format))] 111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103pub enum Error { 112pub enum Error {
113 /// Error converting value.
104 ConversionFailed, 114 ConversionFailed,
105} 115}
106 116
117/// ADC mode.
107pub trait Mode {} 118pub trait Mode {}
108 119
120/// ADC async mode.
109pub struct Async; 121pub struct Async;
110impl Mode for Async {} 122impl Mode for Async {}
111 123
124/// ADC blocking mode.
112pub struct Blocking; 125pub struct Blocking;
113impl Mode for Blocking {} 126impl Mode for Blocking {}
114 127
128/// ADC driver.
115pub struct Adc<'d, M: Mode> { 129pub struct Adc<'d, M: Mode> {
116 phantom: PhantomData<(&'d ADC, M)>, 130 phantom: PhantomData<(&'d ADC, M)>,
117} 131}
@@ -150,6 +164,7 @@ impl<'d, M: Mode> Adc<'d, M> {
150 while !r.cs().read().ready() {} 164 while !r.cs().read().ready() {}
151 } 165 }
152 166
167 /// Sample a value from a channel in blocking mode.
153 pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> { 168 pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> {
154 let r = Self::regs(); 169 let r = Self::regs();
155 r.cs().modify(|w| { 170 r.cs().modify(|w| {
@@ -166,6 +181,7 @@ impl<'d, M: Mode> Adc<'d, M> {
166} 181}
167 182
168impl<'d> Adc<'d, Async> { 183impl<'d> Adc<'d, Async> {
184 /// Create ADC driver in async mode.
169 pub fn new( 185 pub fn new(
170 _inner: impl Peripheral<P = ADC> + 'd, 186 _inner: impl Peripheral<P = ADC> + 'd,
171 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, 187 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
@@ -194,6 +210,7 @@ impl<'d> Adc<'d, Async> {
194 .await; 210 .await;
195 } 211 }
196 212
213 /// Sample a value from a channel until completed.
197 pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> { 214 pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> {
198 let r = Self::regs(); 215 let r = Self::regs();
199 r.cs().modify(|w| { 216 r.cs().modify(|w| {
@@ -272,6 +289,7 @@ impl<'d> Adc<'d, Async> {
272 } 289 }
273 } 290 }
274 291
292 /// Sample multiple values from a channel using DMA.
275 #[inline] 293 #[inline]
276 pub async fn read_many<S: AdcSample>( 294 pub async fn read_many<S: AdcSample>(
277 &mut self, 295 &mut self,
@@ -283,6 +301,7 @@ impl<'d> Adc<'d, Async> {
283 self.read_many_inner(ch, buf, false, div, dma).await 301 self.read_many_inner(ch, buf, false, div, dma).await
284 } 302 }
285 303
304 /// Sample multiple values from a channel using DMA with errors inlined in samples.
286 #[inline] 305 #[inline]
287 pub async fn read_many_raw( 306 pub async fn read_many_raw(
288 &mut self, 307 &mut self,
@@ -299,6 +318,7 @@ impl<'d> Adc<'d, Async> {
299} 318}
300 319
301impl<'d> Adc<'d, Blocking> { 320impl<'d> Adc<'d, Blocking> {
321 /// Create ADC driver in blocking mode.
302 pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self { 322 pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
303 Self::setup(); 323 Self::setup();
304 324
@@ -306,6 +326,7 @@ impl<'d> Adc<'d, Blocking> {
306 } 326 }
307} 327}
308 328
329/// Interrupt handler.
309pub struct InterruptHandler { 330pub struct InterruptHandler {
310 _empty: (), 331 _empty: (),
311} 332}
@@ -324,6 +345,7 @@ mod sealed {
324 pub trait AdcChannel {} 345 pub trait AdcChannel {}
325} 346}
326 347
348/// ADC sample.
327pub trait AdcSample: sealed::AdcSample {} 349pub trait AdcSample: sealed::AdcSample {}
328 350
329impl sealed::AdcSample for u16 {} 351impl sealed::AdcSample for u16 {}
@@ -332,7 +354,9 @@ impl AdcSample for u16 {}
332impl sealed::AdcSample for u8 {} 354impl sealed::AdcSample for u8 {}
333impl AdcSample for u8 {} 355impl AdcSample for u8 {}
334 356
357/// ADC channel.
335pub trait AdcChannel: sealed::AdcChannel {} 358pub trait AdcChannel: sealed::AdcChannel {}
359/// ADC pin.
336pub trait AdcPin: AdcChannel + gpio::Pin {} 360pub trait AdcPin: AdcChannel + gpio::Pin {}
337 361
338macro_rules! impl_pin { 362macro_rules! impl_pin {
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 220665462..19232b801 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -1,3 +1,4 @@
1//! Clock configuration for the RP2040
1use core::arch::asm; 2use core::arch::asm;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; 4use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
@@ -44,34 +45,50 @@ static CLOCKS: Clocks = Clocks {
44 rtc: AtomicU16::new(0), 45 rtc: AtomicU16::new(0),
45}; 46};
46 47
48/// Peripheral clock sources.
47#[repr(u8)] 49#[repr(u8)]
48#[non_exhaustive] 50#[non_exhaustive]
49#[derive(Clone, Copy, Debug, PartialEq, Eq)] 51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
50pub enum PeriClkSrc { 52pub enum PeriClkSrc {
53 /// SYS.
51 Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _, 54 Sys = ClkPeriCtrlAuxsrc::CLK_SYS as _,
55 /// PLL SYS.
52 PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _, 56 PllSys = ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS as _,
57 /// PLL USB.
53 PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _, 58 PllUsb = ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB as _,
59 /// ROSC.
54 Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _, 60 Rosc = ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH as _,
61 /// XOSC.
55 Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _, 62 Xosc = ClkPeriCtrlAuxsrc::XOSC_CLKSRC as _,
56 // Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ , 63 // Gpin0 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
57 // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ , 64 // Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
58} 65}
59 66
67/// CLock configuration.
60#[non_exhaustive] 68#[non_exhaustive]
61pub struct ClockConfig { 69pub struct ClockConfig {
70 /// Ring oscillator configuration.
62 pub rosc: Option<RoscConfig>, 71 pub rosc: Option<RoscConfig>,
72 /// External oscillator configuration.
63 pub xosc: Option<XoscConfig>, 73 pub xosc: Option<XoscConfig>,
74 /// Reference clock configuration.
64 pub ref_clk: RefClkConfig, 75 pub ref_clk: RefClkConfig,
76 /// System clock configuration.
65 pub sys_clk: SysClkConfig, 77 pub sys_clk: SysClkConfig,
78 /// Peripheral clock source configuration.
66 pub peri_clk_src: Option<PeriClkSrc>, 79 pub peri_clk_src: Option<PeriClkSrc>,
80 /// USB clock configuration.
67 pub usb_clk: Option<UsbClkConfig>, 81 pub usb_clk: Option<UsbClkConfig>,
82 /// ADC clock configuration.
68 pub adc_clk: Option<AdcClkConfig>, 83 pub adc_clk: Option<AdcClkConfig>,
84 /// RTC clock configuration.
69 pub rtc_clk: Option<RtcClkConfig>, 85 pub rtc_clk: Option<RtcClkConfig>,
70 // gpin0: Option<(u32, Gpin<'static, AnyPin>)>, 86 // gpin0: Option<(u32, Gpin<'static, AnyPin>)>,
71 // gpin1: Option<(u32, Gpin<'static, AnyPin>)>, 87 // gpin1: Option<(u32, Gpin<'static, AnyPin>)>,
72} 88}
73 89
74impl ClockConfig { 90impl ClockConfig {
91 /// Clock configuration derived from external crystal.
75 pub fn crystal(crystal_hz: u32) -> Self { 92 pub fn crystal(crystal_hz: u32) -> Self {
76 Self { 93 Self {
77 rosc: Some(RoscConfig { 94 rosc: Some(RoscConfig {
@@ -130,6 +147,7 @@ impl ClockConfig {
130 } 147 }
131 } 148 }
132 149
150 /// Clock configuration from internal oscillator.
133 pub fn rosc() -> Self { 151 pub fn rosc() -> Self {
134 Self { 152 Self {
135 rosc: Some(RoscConfig { 153 rosc: Some(RoscConfig {
@@ -179,130 +197,190 @@ impl ClockConfig {
179 // } 197 // }
180} 198}
181 199
200/// ROSC freq range.
182#[repr(u16)] 201#[repr(u16)]
183#[non_exhaustive] 202#[non_exhaustive]
184#[derive(Clone, Copy, Debug, PartialEq, Eq)] 203#[derive(Clone, Copy, Debug, PartialEq, Eq)]
185pub enum RoscRange { 204pub enum RoscRange {
205 /// Low range.
186 Low = pac::rosc::vals::FreqRange::LOW.0, 206 Low = pac::rosc::vals::FreqRange::LOW.0,
207 /// Medium range (1.33x low)
187 Medium = pac::rosc::vals::FreqRange::MEDIUM.0, 208 Medium = pac::rosc::vals::FreqRange::MEDIUM.0,
209 /// High range (2x low)
188 High = pac::rosc::vals::FreqRange::HIGH.0, 210 High = pac::rosc::vals::FreqRange::HIGH.0,
211 /// Too high. Should not be used.
189 TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0, 212 TooHigh = pac::rosc::vals::FreqRange::TOOHIGH.0,
190} 213}
191 214
215/// On-chip ring oscillator configuration.
192pub struct RoscConfig { 216pub struct RoscConfig {
193 /// Final frequency of the oscillator, after the divider has been applied. 217 /// Final frequency of the oscillator, after the divider has been applied.
194 /// The oscillator has a nominal frequency of 6.5MHz at medium range with 218 /// The oscillator has a nominal frequency of 6.5MHz at medium range with
195 /// divider 16 and all drive strengths set to 0, other values should be 219 /// divider 16 and all drive strengths set to 0, other values should be
196 /// measured in situ. 220 /// measured in situ.
197 pub hz: u32, 221 pub hz: u32,
222 /// Oscillator range.
198 pub range: RoscRange, 223 pub range: RoscRange,
224 /// Drive strength for oscillator.
199 pub drive_strength: [u8; 8], 225 pub drive_strength: [u8; 8],
226 /// Output divider.
200 pub div: u16, 227 pub div: u16,
201} 228}
202 229
230/// Crystal oscillator configuration.
203pub struct XoscConfig { 231pub struct XoscConfig {
232 /// Final frequency of the oscillator.
204 pub hz: u32, 233 pub hz: u32,
234 /// Configuring PLL for the system clock.
205 pub sys_pll: Option<PllConfig>, 235 pub sys_pll: Option<PllConfig>,
236 /// Configuring PLL for the USB clock.
206 pub usb_pll: Option<PllConfig>, 237 pub usb_pll: Option<PllConfig>,
238 /// Multiplier for the startup delay.
207 pub delay_multiplier: u32, 239 pub delay_multiplier: u32,
208} 240}
209 241
242/// PLL configuration.
210pub struct PllConfig { 243pub struct PllConfig {
244 /// Reference divisor.
211 pub refdiv: u8, 245 pub refdiv: u8,
246 /// Feedback divisor.
212 pub fbdiv: u16, 247 pub fbdiv: u16,
248 /// Output divisor 1.
213 pub post_div1: u8, 249 pub post_div1: u8,
250 /// Output divisor 2.
214 pub post_div2: u8, 251 pub post_div2: u8,
215} 252}
216 253
254/// Reference clock config.
217pub struct RefClkConfig { 255pub struct RefClkConfig {
256 /// Reference clock source.
218 pub src: RefClkSrc, 257 pub src: RefClkSrc,
258 /// Reference clock divider.
219 pub div: u8, 259 pub div: u8,
220} 260}
221 261
262/// Reference clock source.
222#[non_exhaustive] 263#[non_exhaustive]
223#[derive(Clone, Copy, Debug, PartialEq, Eq)] 264#[derive(Clone, Copy, Debug, PartialEq, Eq)]
224pub enum RefClkSrc { 265pub enum RefClkSrc {
225 // main sources 266 /// XOSC.
226 Xosc, 267 Xosc,
268 /// ROSC.
227 Rosc, 269 Rosc,
228 // aux sources 270 /// PLL USB.
229 PllUsb, 271 PllUsb,
230 // Gpin0, 272 // Gpin0,
231 // Gpin1, 273 // Gpin1,
232} 274}
233 275
276/// SYS clock source.
234#[non_exhaustive] 277#[non_exhaustive]
235#[derive(Clone, Copy, Debug, PartialEq, Eq)] 278#[derive(Clone, Copy, Debug, PartialEq, Eq)]
236pub enum SysClkSrc { 279pub enum SysClkSrc {
237 // main sources 280 /// REF.
238 Ref, 281 Ref,
239 // aux sources 282 /// PLL SYS.
240 PllSys, 283 PllSys,
284 /// PLL USB.
241 PllUsb, 285 PllUsb,
286 /// ROSC.
242 Rosc, 287 Rosc,
288 /// XOSC.
243 Xosc, 289 Xosc,
244 // Gpin0, 290 // Gpin0,
245 // Gpin1, 291 // Gpin1,
246} 292}
247 293
294/// SYS clock config.
248pub struct SysClkConfig { 295pub struct SysClkConfig {
296 /// SYS clock source.
249 pub src: SysClkSrc, 297 pub src: SysClkSrc,
298 /// SYS clock divider.
250 pub div_int: u32, 299 pub div_int: u32,
300 /// SYS clock fraction.
251 pub div_frac: u8, 301 pub div_frac: u8,
252} 302}
253 303
304/// USB clock source.
254#[repr(u8)] 305#[repr(u8)]
255#[non_exhaustive] 306#[non_exhaustive]
256#[derive(Clone, Copy, Debug, PartialEq, Eq)] 307#[derive(Clone, Copy, Debug, PartialEq, Eq)]
257pub enum UsbClkSrc { 308pub enum UsbClkSrc {
309 /// PLL USB.
258 PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _, 310 PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
311 /// PLL SYS.
259 PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _, 312 PllSys = ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS as _,
313 /// ROSC.
260 Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _, 314 Rosc = ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH as _,
315 /// XOSC.
261 Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _, 316 Xosc = ClkUsbCtrlAuxsrc::XOSC_CLKSRC as _,
262 // Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ , 317 // Gpin0 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
263 // Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ , 318 // Gpin1 = ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
264} 319}
265 320
321/// USB clock config.
266pub struct UsbClkConfig { 322pub struct UsbClkConfig {
323 /// USB clock source.
267 pub src: UsbClkSrc, 324 pub src: UsbClkSrc,
325 /// USB clock divider.
268 pub div: u8, 326 pub div: u8,
327 /// USB clock phase.
269 pub phase: u8, 328 pub phase: u8,
270} 329}
271 330
331/// ADC clock source.
272#[repr(u8)] 332#[repr(u8)]
273#[non_exhaustive] 333#[non_exhaustive]
274#[derive(Clone, Copy, Debug, PartialEq, Eq)] 334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
275pub enum AdcClkSrc { 335pub enum AdcClkSrc {
336 /// PLL USB.
276 PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _, 337 PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
338 /// PLL SYS.
277 PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _, 339 PllSys = ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
340 /// ROSC.
278 Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _, 341 Rosc = ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
342 /// XOSC.
279 Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _, 343 Xosc = ClkAdcCtrlAuxsrc::XOSC_CLKSRC as _,
280 // Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ , 344 // Gpin0 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
281 // Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ , 345 // Gpin1 = ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
282} 346}
283 347
348/// ADC clock config.
284pub struct AdcClkConfig { 349pub struct AdcClkConfig {
350 /// ADC clock source.
285 pub src: AdcClkSrc, 351 pub src: AdcClkSrc,
352 /// ADC clock divider.
286 pub div: u8, 353 pub div: u8,
354 /// ADC clock phase.
287 pub phase: u8, 355 pub phase: u8,
288} 356}
289 357
358/// RTC clock source.
290#[repr(u8)] 359#[repr(u8)]
291#[non_exhaustive] 360#[non_exhaustive]
292#[derive(Clone, Copy, Debug, PartialEq, Eq)] 361#[derive(Clone, Copy, Debug, PartialEq, Eq)]
293pub enum RtcClkSrc { 362pub enum RtcClkSrc {
363 /// PLL USB.
294 PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _, 364 PllUsb = ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB as _,
365 /// PLL SYS.
295 PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _, 366 PllSys = ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS as _,
367 /// ROSC.
296 Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _, 368 Rosc = ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH as _,
369 /// XOSC.
297 Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _, 370 Xosc = ClkRtcCtrlAuxsrc::XOSC_CLKSRC as _,
298 // Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ , 371 // Gpin0 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
299 // Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ , 372 // Gpin1 = ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
300} 373}
301 374
375/// RTC clock config.
302pub struct RtcClkConfig { 376pub struct RtcClkConfig {
377 /// RTC clock source.
303 pub src: RtcClkSrc, 378 pub src: RtcClkSrc,
379 /// RTC clock divider.
304 pub div_int: u32, 380 pub div_int: u32,
381 /// RTC clock divider fraction.
305 pub div_frac: u8, 382 pub div_frac: u8,
383 /// RTC clock phase.
306 pub phase: u8, 384 pub phase: u8,
307} 385}
308 386
@@ -579,10 +657,12 @@ fn configure_rosc(config: RoscConfig) -> u32 {
579 config.hz 657 config.hz
580} 658}
581 659
660/// ROSC clock frequency.
582pub fn rosc_freq() -> u32 { 661pub fn rosc_freq() -> u32 {
583 CLOCKS.rosc.load(Ordering::Relaxed) 662 CLOCKS.rosc.load(Ordering::Relaxed)
584} 663}
585 664
665/// XOSC clock frequency.
586pub fn xosc_freq() -> u32 { 666pub fn xosc_freq() -> u32 {
587 CLOCKS.xosc.load(Ordering::Relaxed) 667 CLOCKS.xosc.load(Ordering::Relaxed)
588} 668}
@@ -594,34 +674,42 @@ pub fn xosc_freq() -> u32 {
594// CLOCKS.gpin1.load(Ordering::Relaxed) 674// CLOCKS.gpin1.load(Ordering::Relaxed)
595// } 675// }
596 676
677/// PLL SYS clock frequency.
597pub fn pll_sys_freq() -> u32 { 678pub fn pll_sys_freq() -> u32 {
598 CLOCKS.pll_sys.load(Ordering::Relaxed) 679 CLOCKS.pll_sys.load(Ordering::Relaxed)
599} 680}
600 681
682/// PLL USB clock frequency.
601pub fn pll_usb_freq() -> u32 { 683pub fn pll_usb_freq() -> u32 {
602 CLOCKS.pll_usb.load(Ordering::Relaxed) 684 CLOCKS.pll_usb.load(Ordering::Relaxed)
603} 685}
604 686
687/// SYS clock frequency.
605pub fn clk_sys_freq() -> u32 { 688pub fn clk_sys_freq() -> u32 {
606 CLOCKS.sys.load(Ordering::Relaxed) 689 CLOCKS.sys.load(Ordering::Relaxed)
607} 690}
608 691
692/// REF clock frequency.
609pub fn clk_ref_freq() -> u32 { 693pub fn clk_ref_freq() -> u32 {
610 CLOCKS.reference.load(Ordering::Relaxed) 694 CLOCKS.reference.load(Ordering::Relaxed)
611} 695}
612 696
697/// Peripheral clock frequency.
613pub fn clk_peri_freq() -> u32 { 698pub fn clk_peri_freq() -> u32 {
614 CLOCKS.peri.load(Ordering::Relaxed) 699 CLOCKS.peri.load(Ordering::Relaxed)
615} 700}
616 701
702/// USB clock frequency.
617pub fn clk_usb_freq() -> u32 { 703pub fn clk_usb_freq() -> u32 {
618 CLOCKS.usb.load(Ordering::Relaxed) 704 CLOCKS.usb.load(Ordering::Relaxed)
619} 705}
620 706
707/// ADC clock frequency.
621pub fn clk_adc_freq() -> u32 { 708pub fn clk_adc_freq() -> u32 {
622 CLOCKS.adc.load(Ordering::Relaxed) 709 CLOCKS.adc.load(Ordering::Relaxed)
623} 710}
624 711
712/// RTC clock frequency.
625pub fn clk_rtc_freq() -> u16 { 713pub fn clk_rtc_freq() -> u16 {
626 CLOCKS.rtc.load(Ordering::Relaxed) 714 CLOCKS.rtc.load(Ordering::Relaxed)
627} 715}
@@ -682,7 +770,9 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 {
682 vco_freq / ((config.post_div1 * config.post_div2) as u32) 770 vco_freq / ((config.post_div1 * config.post_div2) as u32)
683} 771}
684 772
773/// General purpose input clock pin.
685pub trait GpinPin: crate::gpio::Pin { 774pub trait GpinPin: crate::gpio::Pin {
775 /// Pin number.
686 const NR: usize; 776 const NR: usize;
687} 777}
688 778
@@ -697,12 +787,14 @@ macro_rules! impl_gpinpin {
697impl_gpinpin!(PIN_20, 20, 0); 787impl_gpinpin!(PIN_20, 20, 0);
698impl_gpinpin!(PIN_22, 22, 1); 788impl_gpinpin!(PIN_22, 22, 1);
699 789
790/// General purpose clock input driver.
700pub struct Gpin<'d, T: Pin> { 791pub struct Gpin<'d, T: Pin> {
701 gpin: PeripheralRef<'d, AnyPin>, 792 gpin: PeripheralRef<'d, AnyPin>,
702 _phantom: PhantomData<T>, 793 _phantom: PhantomData<T>,
703} 794}
704 795
705impl<'d, T: Pin> Gpin<'d, T> { 796impl<'d, T: Pin> Gpin<'d, T> {
797 /// Create new gpin driver.
706 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> { 798 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
707 into_ref!(gpin); 799 into_ref!(gpin);
708 800
@@ -728,7 +820,9 @@ impl<'d, T: Pin> Drop for Gpin<'d, T> {
728 } 820 }
729} 821}
730 822
823/// General purpose clock output pin.
731pub trait GpoutPin: crate::gpio::Pin { 824pub trait GpoutPin: crate::gpio::Pin {
825 /// Pin number.
732 fn number(&self) -> usize; 826 fn number(&self) -> usize;
733} 827}
734 828
@@ -747,26 +841,38 @@ impl_gpoutpin!(PIN_23, 1);
747impl_gpoutpin!(PIN_24, 2); 841impl_gpoutpin!(PIN_24, 2);
748impl_gpoutpin!(PIN_25, 3); 842impl_gpoutpin!(PIN_25, 3);
749 843
844/// Gpout clock source.
750#[repr(u8)] 845#[repr(u8)]
751pub enum GpoutSrc { 846pub enum GpoutSrc {
847 /// Sys PLL.
752 PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _, 848 PllSys = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS as _,
753 // Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ , 849 // Gpin0 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN0 as _ ,
754 // Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ , 850 // Gpin1 = ClkGpoutCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
851 /// USB PLL.
755 PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _, 852 PllUsb = ClkGpoutCtrlAuxsrc::CLKSRC_PLL_USB as _,
853 /// ROSC.
756 Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _, 854 Rosc = ClkGpoutCtrlAuxsrc::ROSC_CLKSRC as _,
855 /// XOSC.
757 Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _, 856 Xosc = ClkGpoutCtrlAuxsrc::XOSC_CLKSRC as _,
857 /// SYS.
758 Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _, 858 Sys = ClkGpoutCtrlAuxsrc::CLK_SYS as _,
859 /// USB.
759 Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _, 860 Usb = ClkGpoutCtrlAuxsrc::CLK_USB as _,
861 /// ADC.
760 Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _, 862 Adc = ClkGpoutCtrlAuxsrc::CLK_ADC as _,
863 /// RTC.
761 Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _, 864 Rtc = ClkGpoutCtrlAuxsrc::CLK_RTC as _,
865 /// REF.
762 Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _, 866 Ref = ClkGpoutCtrlAuxsrc::CLK_REF as _,
763} 867}
764 868
869/// General purpose clock output driver.
765pub struct Gpout<'d, T: GpoutPin> { 870pub struct Gpout<'d, T: GpoutPin> {
766 gpout: PeripheralRef<'d, T>, 871 gpout: PeripheralRef<'d, T>,
767} 872}
768 873
769impl<'d, T: GpoutPin> Gpout<'d, T> { 874impl<'d, T: GpoutPin> Gpout<'d, T> {
875 /// Create new general purpose cloud output.
770 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self { 876 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
771 into_ref!(gpout); 877 into_ref!(gpout);
772 878
@@ -775,6 +881,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
775 Self { gpout } 881 Self { gpout }
776 } 882 }
777 883
884 /// Set clock divider.
778 pub fn set_div(&self, int: u32, frac: u8) { 885 pub fn set_div(&self, int: u32, frac: u8) {
779 let c = pac::CLOCKS; 886 let c = pac::CLOCKS;
780 c.clk_gpout_div(self.gpout.number()).write(|w| { 887 c.clk_gpout_div(self.gpout.number()).write(|w| {
@@ -783,6 +890,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
783 }); 890 });
784 } 891 }
785 892
893 /// Set clock source.
786 pub fn set_src(&self, src: GpoutSrc) { 894 pub fn set_src(&self, src: GpoutSrc) {
787 let c = pac::CLOCKS; 895 let c = pac::CLOCKS;
788 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 896 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -790,6 +898,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
790 }); 898 });
791 } 899 }
792 900
901 /// Enable clock.
793 pub fn enable(&self) { 902 pub fn enable(&self) {
794 let c = pac::CLOCKS; 903 let c = pac::CLOCKS;
795 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 904 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -797,6 +906,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
797 }); 906 });
798 } 907 }
799 908
909 /// Disable clock.
800 pub fn disable(&self) { 910 pub fn disable(&self) {
801 let c = pac::CLOCKS; 911 let c = pac::CLOCKS;
802 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 912 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
@@ -804,6 +914,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
804 }); 914 });
805 } 915 }
806 916
917 /// Clock frequency.
807 pub fn get_freq(&self) -> u32 { 918 pub fn get_freq(&self) -> u32 {
808 let c = pac::CLOCKS; 919 let c = pac::CLOCKS;
809 let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc(); 920 let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 45ca21a75..088a842a1 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -38,6 +38,9 @@ pub(crate) unsafe fn init() {
38 interrupt::DMA_IRQ_0.enable(); 38 interrupt::DMA_IRQ_0.enable();
39} 39}
40 40
41/// DMA read.
42///
43/// SAFETY: Slice must point to a valid location reachable by DMA.
41pub unsafe fn read<'a, C: Channel, W: Word>( 44pub unsafe fn read<'a, C: Channel, W: Word>(
42 ch: impl Peripheral<P = C> + 'a, 45 ch: impl Peripheral<P = C> + 'a,
43 from: *const W, 46 from: *const W,
@@ -57,6 +60,9 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
57 ) 60 )
58} 61}
59 62
63/// DMA write.
64///
65/// SAFETY: Slice must point to a valid location reachable by DMA.
60pub unsafe fn write<'a, C: Channel, W: Word>( 66pub unsafe fn write<'a, C: Channel, W: Word>(
61 ch: impl Peripheral<P = C> + 'a, 67 ch: impl Peripheral<P = C> + 'a,
62 from: *const [W], 68 from: *const [W],
@@ -79,6 +85,9 @@ pub unsafe fn write<'a, C: Channel, W: Word>(
79// static mut so that this is allocated in RAM. 85// static mut so that this is allocated in RAM.
80static mut DUMMY: u32 = 0; 86static mut DUMMY: u32 = 0;
81 87
88/// DMA repeated write.
89///
90/// SAFETY: Slice must point to a valid location reachable by DMA.
82pub unsafe fn write_repeated<'a, C: Channel, W: Word>( 91pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
83 ch: impl Peripheral<P = C> + 'a, 92 ch: impl Peripheral<P = C> + 'a,
84 to: *mut W, 93 to: *mut W,
@@ -97,6 +106,9 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
97 ) 106 )
98} 107}
99 108
109/// DMA copy between slices.
110///
111/// SAFETY: Slices must point to locations reachable by DMA.
100pub unsafe fn copy<'a, C: Channel, W: Word>( 112pub unsafe fn copy<'a, C: Channel, W: Word>(
101 ch: impl Peripheral<P = C> + 'a, 113 ch: impl Peripheral<P = C> + 'a,
102 from: &[W], 114 from: &[W],
@@ -152,6 +164,7 @@ fn copy_inner<'a, C: Channel>(
152 Transfer::new(ch) 164 Transfer::new(ch)
153} 165}
154 166
167/// DMA transfer driver.
155#[must_use = "futures do nothing unless you `.await` or poll them"] 168#[must_use = "futures do nothing unless you `.await` or poll them"]
156pub struct Transfer<'a, C: Channel> { 169pub struct Transfer<'a, C: Channel> {
157 channel: PeripheralRef<'a, C>, 170 channel: PeripheralRef<'a, C>,
@@ -201,19 +214,25 @@ mod sealed {
201 pub trait Word {} 214 pub trait Word {}
202} 215}
203 216
217/// DMA channel interface.
204pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static { 218pub trait Channel: Peripheral<P = Self> + sealed::Channel + Into<AnyChannel> + Sized + 'static {
219 /// Channel number.
205 fn number(&self) -> u8; 220 fn number(&self) -> u8;
206 221
222 /// Channel registry block.
207 fn regs(&self) -> pac::dma::Channel { 223 fn regs(&self) -> pac::dma::Channel {
208 pac::DMA.ch(self.number() as _) 224 pac::DMA.ch(self.number() as _)
209 } 225 }
210 226
227 /// Convert into type-erased [AnyChannel].
211 fn degrade(self) -> AnyChannel { 228 fn degrade(self) -> AnyChannel {
212 AnyChannel { number: self.number() } 229 AnyChannel { number: self.number() }
213 } 230 }
214} 231}
215 232
233/// DMA word.
216pub trait Word: sealed::Word { 234pub trait Word: sealed::Word {
235 /// Word size.
217 fn size() -> vals::DataSize; 236 fn size() -> vals::DataSize;
218} 237}
219 238
@@ -238,6 +257,7 @@ impl Word for u32 {
238 } 257 }
239} 258}
240 259
260/// Type erased DMA channel.
241pub struct AnyChannel { 261pub struct AnyChannel {
242 number: u8, 262 number: u8,
243} 263}
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 1b20561da..2d673cf6c 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -1,3 +1,4 @@
1//! Flash driver.
1use core::future::Future; 2use core::future::Future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::pin::Pin; 4use core::pin::Pin;
@@ -13,9 +14,10 @@ use crate::dma::{AnyChannel, Channel, Transfer};
13use crate::pac; 14use crate::pac;
14use crate::peripherals::FLASH; 15use crate::peripherals::FLASH;
15 16
17/// Flash base address.
16pub const FLASH_BASE: *const u32 = 0x10000000 as _; 18pub const FLASH_BASE: *const u32 = 0x10000000 as _;
17 19
18// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. 20/// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead.
19// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. 21// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance.
20pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); 22pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
21 23
@@ -24,10 +26,15 @@ pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram");
24// These limitations are currently enforced because of using the 26// These limitations are currently enforced because of using the
25// RP2040 boot-rom flash functions, that are optimized for flash compatibility 27// RP2040 boot-rom flash functions, that are optimized for flash compatibility
26// rather than performance. 28// rather than performance.
29/// Flash page size.
27pub const PAGE_SIZE: usize = 256; 30pub const PAGE_SIZE: usize = 256;
31/// Flash write size.
28pub const WRITE_SIZE: usize = 1; 32pub const WRITE_SIZE: usize = 1;
33/// Flash read size.
29pub const READ_SIZE: usize = 1; 34pub const READ_SIZE: usize = 1;
35/// Flash erase size.
30pub const ERASE_SIZE: usize = 4096; 36pub const ERASE_SIZE: usize = 4096;
37/// Flash DMA read size.
31pub const ASYNC_READ_SIZE: usize = 4; 38pub const ASYNC_READ_SIZE: usize = 4;
32 39
33/// Error type for NVMC operations. 40/// Error type for NVMC operations.
@@ -38,7 +45,9 @@ pub enum Error {
38 OutOfBounds, 45 OutOfBounds,
39 /// Unaligned operation or using unaligned buffers. 46 /// Unaligned operation or using unaligned buffers.
40 Unaligned, 47 Unaligned,
48 /// Accessed from the wrong core.
41 InvalidCore, 49 InvalidCore,
50 /// Other error
42 Other, 51 Other,
43} 52}
44 53
@@ -96,12 +105,18 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, '
96 } 105 }
97} 106}
98 107
108/// Flash driver.
99pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> { 109pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
100 dma: Option<PeripheralRef<'d, AnyChannel>>, 110 dma: Option<PeripheralRef<'d, AnyChannel>>,
101 phantom: PhantomData<(&'d mut T, M)>, 111 phantom: PhantomData<(&'d mut T, M)>,
102} 112}
103 113
104impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> { 114impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> {
115 /// Blocking read.
116 ///
117 /// The offset and buffer must be aligned.
118 ///
119 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
105 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 120 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
106 trace!( 121 trace!(
107 "Reading from 0x{:x} to 0x{:x}", 122 "Reading from 0x{:x} to 0x{:x}",
@@ -116,10 +131,14 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
116 Ok(()) 131 Ok(())
117 } 132 }
118 133
134 /// Flash capacity.
119 pub fn capacity(&self) -> usize { 135 pub fn capacity(&self) -> usize {
120 FLASH_SIZE 136 FLASH_SIZE
121 } 137 }
122 138
139 /// Blocking erase.
140 ///
141 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
123 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 142 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
124 check_erase(self, from, to)?; 143 check_erase(self, from, to)?;
125 144
@@ -136,6 +155,11 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
136 Ok(()) 155 Ok(())
137 } 156 }
138 157
158 /// Blocking write.
159 ///
160 /// The offset and buffer must be aligned.
161 ///
162 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
139 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 163 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
140 check_write(self, offset, bytes.len())?; 164 check_write(self, offset, bytes.len())?;
141 165
@@ -219,6 +243,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
219} 243}
220 244
221impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> { 245impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
246 /// Create a new flash driver in blocking mode.
222 pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self { 247 pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
223 Self { 248 Self {
224 dma: None, 249 dma: None,
@@ -228,6 +253,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE
228} 253}
229 254
230impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { 255impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
256 /// Create a new flash driver in async mode.
231 pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self { 257 pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
232 into_ref!(dma); 258 into_ref!(dma);
233 Self { 259 Self {
@@ -236,6 +262,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
236 } 262 }
237 } 263 }
238 264
265 /// Start a background read operation.
266 ///
267 /// The offset and buffer must be aligned.
268 ///
269 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
239 pub fn background_read<'a>( 270 pub fn background_read<'a>(
240 &'a mut self, 271 &'a mut self,
241 offset: u32, 272 offset: u32,
@@ -279,6 +310,11 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
279 }) 310 })
280 } 311 }
281 312
313 /// Async read.
314 ///
315 /// The offset and buffer must be aligned.
316 ///
317 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
282 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 318 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
283 use core::mem::MaybeUninit; 319 use core::mem::MaybeUninit;
284 320
@@ -874,7 +910,9 @@ mod sealed {
874 pub trait Mode {} 910 pub trait Mode {}
875} 911}
876 912
913/// Flash instance.
877pub trait Instance: sealed::Instance {} 914pub trait Instance: sealed::Instance {}
915/// Flash mode.
878pub trait Mode: sealed::Mode {} 916pub trait Mode: sealed::Mode {}
879 917
880impl sealed::Instance for FLASH {} 918impl sealed::Instance for FLASH {}
@@ -887,7 +925,9 @@ macro_rules! impl_mode {
887 }; 925 };
888} 926}
889 927
928/// Flash blocking mode.
890pub struct Blocking; 929pub struct Blocking;
930/// Flash async mode.
891pub struct Async; 931pub struct Async;
892 932
893impl_mode!(Blocking); 933impl_mode!(Blocking);
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 23273e627..2e6692abe 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -1,3 +1,4 @@
1//! GPIO driver.
1#![macro_use] 2#![macro_use]
2use core::convert::Infallible; 3use core::convert::Infallible;
3use core::future::Future; 4use core::future::Future;
@@ -23,7 +24,9 @@ static QSPI_WAKERS: [AtomicWaker; QSPI_PIN_COUNT] = [NEW_AW; QSPI_PIN_COUNT];
23/// Represents a digital input or output level. 24/// Represents a digital input or output level.
24#[derive(Debug, Eq, PartialEq, Clone, Copy)] 25#[derive(Debug, Eq, PartialEq, Clone, Copy)]
25pub enum Level { 26pub enum Level {
27 /// Logical low.
26 Low, 28 Low,
29 /// Logical high.
27 High, 30 High,
28} 31}
29 32
@@ -48,48 +51,66 @@ impl From<Level> for bool {
48/// Represents a pull setting for an input. 51/// Represents a pull setting for an input.
49#[derive(Debug, Clone, Copy, Eq, PartialEq)] 52#[derive(Debug, Clone, Copy, Eq, PartialEq)]
50pub enum Pull { 53pub enum Pull {
54 /// No pull.
51 None, 55 None,
56 /// Internal pull-up resistor.
52 Up, 57 Up,
58 /// Internal pull-down resistor.
53 Down, 59 Down,
54} 60}
55 61
56/// Drive strength of an output 62/// Drive strength of an output
57#[derive(Debug, Eq, PartialEq)] 63#[derive(Debug, Eq, PartialEq)]
58pub enum Drive { 64pub enum Drive {
65 /// 2 mA drive.
59 _2mA, 66 _2mA,
67 /// 4 mA drive.
60 _4mA, 68 _4mA,
69 /// 8 mA drive.
61 _8mA, 70 _8mA,
71 /// 1 2mA drive.
62 _12mA, 72 _12mA,
63} 73}
64/// Slew rate of an output 74/// Slew rate of an output
65#[derive(Debug, Eq, PartialEq)] 75#[derive(Debug, Eq, PartialEq)]
66pub enum SlewRate { 76pub enum SlewRate {
77 /// Fast slew rate.
67 Fast, 78 Fast,
79 /// Slow slew rate.
68 Slow, 80 Slow,
69} 81}
70 82
71/// A GPIO bank with up to 32 pins. 83/// A GPIO bank with up to 32 pins.
72#[derive(Debug, Eq, PartialEq)] 84#[derive(Debug, Eq, PartialEq)]
73pub enum Bank { 85pub enum Bank {
86 /// Bank 0.
74 Bank0 = 0, 87 Bank0 = 0,
88 /// QSPI.
75 #[cfg(feature = "qspi-as-gpio")] 89 #[cfg(feature = "qspi-as-gpio")]
76 Qspi = 1, 90 Qspi = 1,
77} 91}
78 92
93/// Dormant mode config.
79#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)] 94#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))] 95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub struct DormantWakeConfig { 96pub struct DormantWakeConfig {
97 /// Wake on edge high.
82 pub edge_high: bool, 98 pub edge_high: bool,
99 /// Wake on edge low.
83 pub edge_low: bool, 100 pub edge_low: bool,
101 /// Wake on level high.
84 pub level_high: bool, 102 pub level_high: bool,
103 /// Wake on level low.
85 pub level_low: bool, 104 pub level_low: bool,
86} 105}
87 106
107/// GPIO input driver.
88pub struct Input<'d, T: Pin> { 108pub struct Input<'d, T: Pin> {
89 pin: Flex<'d, T>, 109 pin: Flex<'d, T>,
90} 110}
91 111
92impl<'d, T: Pin> Input<'d, T> { 112impl<'d, T: Pin> Input<'d, T> {
113 /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
93 #[inline] 114 #[inline]
94 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { 115 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
95 let mut pin = Flex::new(pin); 116 let mut pin = Flex::new(pin);
@@ -104,11 +125,13 @@ impl<'d, T: Pin> Input<'d, T> {
104 self.pin.set_schmitt(enable) 125 self.pin.set_schmitt(enable)
105 } 126 }
106 127
128 /// Get whether the pin input level is high.
107 #[inline] 129 #[inline]
108 pub fn is_high(&mut self) -> bool { 130 pub fn is_high(&mut self) -> bool {
109 self.pin.is_high() 131 self.pin.is_high()
110 } 132 }
111 133
134 /// Get whether the pin input level is low.
112 #[inline] 135 #[inline]
113 pub fn is_low(&mut self) -> bool { 136 pub fn is_low(&mut self) -> bool {
114 self.pin.is_low() 137 self.pin.is_low()
@@ -120,31 +143,37 @@ impl<'d, T: Pin> Input<'d, T> {
120 self.pin.get_level() 143 self.pin.get_level()
121 } 144 }
122 145
146 /// Wait until the pin is high. If it is already high, return immediately.
123 #[inline] 147 #[inline]
124 pub async fn wait_for_high(&mut self) { 148 pub async fn wait_for_high(&mut self) {
125 self.pin.wait_for_high().await; 149 self.pin.wait_for_high().await;
126 } 150 }
127 151
152 /// Wait until the pin is low. If it is already low, return immediately.
128 #[inline] 153 #[inline]
129 pub async fn wait_for_low(&mut self) { 154 pub async fn wait_for_low(&mut self) {
130 self.pin.wait_for_low().await; 155 self.pin.wait_for_low().await;
131 } 156 }
132 157
158 /// Wait for the pin to undergo a transition from low to high.
133 #[inline] 159 #[inline]
134 pub async fn wait_for_rising_edge(&mut self) { 160 pub async fn wait_for_rising_edge(&mut self) {
135 self.pin.wait_for_rising_edge().await; 161 self.pin.wait_for_rising_edge().await;
136 } 162 }
137 163
164 /// Wait for the pin to undergo a transition from high to low.
138 #[inline] 165 #[inline]
139 pub async fn wait_for_falling_edge(&mut self) { 166 pub async fn wait_for_falling_edge(&mut self) {
140 self.pin.wait_for_falling_edge().await; 167 self.pin.wait_for_falling_edge().await;
141 } 168 }
142 169
170 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
143 #[inline] 171 #[inline]
144 pub async fn wait_for_any_edge(&mut self) { 172 pub async fn wait_for_any_edge(&mut self) {
145 self.pin.wait_for_any_edge().await; 173 self.pin.wait_for_any_edge().await;
146 } 174 }
147 175
176 /// Configure dormant wake.
148 #[inline] 177 #[inline]
149 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { 178 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
150 self.pin.dormant_wake(cfg) 179 self.pin.dormant_wake(cfg)
@@ -155,10 +184,15 @@ impl<'d, T: Pin> Input<'d, T> {
155#[derive(Debug, Eq, PartialEq, Copy, Clone)] 184#[derive(Debug, Eq, PartialEq, Copy, Clone)]
156#[cfg_attr(feature = "defmt", derive(defmt::Format))] 185#[cfg_attr(feature = "defmt", derive(defmt::Format))]
157pub enum InterruptTrigger { 186pub enum InterruptTrigger {
187 /// Trigger on pin low.
158 LevelLow, 188 LevelLow,
189 /// Trigger on pin high.
159 LevelHigh, 190 LevelHigh,
191 /// Trigger on high to low transition.
160 EdgeLow, 192 EdgeLow,
193 /// Trigger on low to high transition.
161 EdgeHigh, 194 EdgeHigh,
195 /// Trigger on any transition.
162 AnyEdge, 196 AnyEdge,
163} 197}
164 198
@@ -226,6 +260,7 @@ struct InputFuture<'a, T: Pin> {
226} 260}
227 261
228impl<'d, T: Pin> InputFuture<'d, T> { 262impl<'d, T: Pin> InputFuture<'d, T> {
263 /// Create a new future wiating for input trigger.
229 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self { 264 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
230 into_ref!(pin); 265 into_ref!(pin);
231 let pin_group = (pin.pin() % 8) as usize; 266 let pin_group = (pin.pin() % 8) as usize;
@@ -308,11 +343,13 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
308 } 343 }
309} 344}
310 345
346/// GPIO output driver.
311pub struct Output<'d, T: Pin> { 347pub struct Output<'d, T: Pin> {
312 pin: Flex<'d, T>, 348 pin: Flex<'d, T>,
313} 349}
314 350
315impl<'d, T: Pin> Output<'d, T> { 351impl<'d, T: Pin> Output<'d, T> {
352 /// Create GPIO output driver for a [Pin] with the provided [Level].
316 #[inline] 353 #[inline]
317 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { 354 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
318 let mut pin = Flex::new(pin); 355 let mut pin = Flex::new(pin);
@@ -331,7 +368,7 @@ impl<'d, T: Pin> Output<'d, T> {
331 self.pin.set_drive_strength(strength) 368 self.pin.set_drive_strength(strength)
332 } 369 }
333 370
334 // Set the pin's slew rate. 371 /// Set the pin's slew rate.
335 #[inline] 372 #[inline]
336 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 373 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
337 self.pin.set_slew_rate(slew_rate) 374 self.pin.set_slew_rate(slew_rate)
@@ -386,6 +423,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
386} 423}
387 424
388impl<'d, T: Pin> OutputOpenDrain<'d, T> { 425impl<'d, T: Pin> OutputOpenDrain<'d, T> {
426 /// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
389 #[inline] 427 #[inline]
390 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self { 428 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level) -> Self {
391 let mut pin = Flex::new(pin); 429 let mut pin = Flex::new(pin);
@@ -403,7 +441,7 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
403 self.pin.set_drive_strength(strength) 441 self.pin.set_drive_strength(strength)
404 } 442 }
405 443
406 // Set the pin's slew rate. 444 /// Set the pin's slew rate.
407 #[inline] 445 #[inline]
408 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 446 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
409 self.pin.set_slew_rate(slew_rate) 447 self.pin.set_slew_rate(slew_rate)
@@ -456,11 +494,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
456 self.pin.toggle_set_as_output() 494 self.pin.toggle_set_as_output()
457 } 495 }
458 496
497 /// Get whether the pin input level is high.
459 #[inline] 498 #[inline]
460 pub fn is_high(&mut self) -> bool { 499 pub fn is_high(&mut self) -> bool {
461 self.pin.is_high() 500 self.pin.is_high()
462 } 501 }
463 502
503 /// Get whether the pin input level is low.
464 #[inline] 504 #[inline]
465 pub fn is_low(&mut self) -> bool { 505 pub fn is_low(&mut self) -> bool {
466 self.pin.is_low() 506 self.pin.is_low()
@@ -472,26 +512,31 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
472 self.is_high().into() 512 self.is_high().into()
473 } 513 }
474 514
515 /// Wait until the pin is high. If it is already high, return immediately.
475 #[inline] 516 #[inline]
476 pub async fn wait_for_high(&mut self) { 517 pub async fn wait_for_high(&mut self) {
477 self.pin.wait_for_high().await; 518 self.pin.wait_for_high().await;
478 } 519 }
479 520
521 /// Wait until the pin is low. If it is already low, return immediately.
480 #[inline] 522 #[inline]
481 pub async fn wait_for_low(&mut self) { 523 pub async fn wait_for_low(&mut self) {
482 self.pin.wait_for_low().await; 524 self.pin.wait_for_low().await;
483 } 525 }
484 526
527 /// Wait for the pin to undergo a transition from low to high.
485 #[inline] 528 #[inline]
486 pub async fn wait_for_rising_edge(&mut self) { 529 pub async fn wait_for_rising_edge(&mut self) {
487 self.pin.wait_for_rising_edge().await; 530 self.pin.wait_for_rising_edge().await;
488 } 531 }
489 532
533 /// Wait for the pin to undergo a transition from high to low.
490 #[inline] 534 #[inline]
491 pub async fn wait_for_falling_edge(&mut self) { 535 pub async fn wait_for_falling_edge(&mut self) {
492 self.pin.wait_for_falling_edge().await; 536 self.pin.wait_for_falling_edge().await;
493 } 537 }
494 538
539 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
495 #[inline] 540 #[inline]
496 pub async fn wait_for_any_edge(&mut self) { 541 pub async fn wait_for_any_edge(&mut self) {
497 self.pin.wait_for_any_edge().await; 542 self.pin.wait_for_any_edge().await;
@@ -508,6 +553,10 @@ pub struct Flex<'d, T: Pin> {
508} 553}
509 554
510impl<'d, T: Pin> Flex<'d, T> { 555impl<'d, T: Pin> Flex<'d, T> {
556 /// Wrap the pin in a `Flex`.
557 ///
558 /// The pin remains disconnected. The initial output level is unspecified, but can be changed
559 /// before the pin is put into output mode.
511 #[inline] 560 #[inline]
512 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self { 561 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
513 into_ref!(pin); 562 into_ref!(pin);
@@ -556,7 +605,7 @@ impl<'d, T: Pin> Flex<'d, T> {
556 }); 605 });
557 } 606 }
558 607
559 // Set the pin's slew rate. 608 /// Set the pin's slew rate.
560 #[inline] 609 #[inline]
561 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 610 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
562 self.pin.pad_ctrl().modify(|w| { 611 self.pin.pad_ctrl().modify(|w| {
@@ -589,6 +638,7 @@ impl<'d, T: Pin> Flex<'d, T> {
589 self.pin.sio_oe().value_set().write_value(self.bit()) 638 self.pin.sio_oe().value_set().write_value(self.bit())
590 } 639 }
591 640
641 /// Set as output pin.
592 #[inline] 642 #[inline]
593 pub fn is_set_as_output(&mut self) -> bool { 643 pub fn is_set_as_output(&mut self) -> bool {
594 self.ref_is_set_as_output() 644 self.ref_is_set_as_output()
@@ -599,15 +649,18 @@ impl<'d, T: Pin> Flex<'d, T> {
599 (self.pin.sio_oe().value().read() & self.bit()) != 0 649 (self.pin.sio_oe().value().read() & self.bit()) != 0
600 } 650 }
601 651
652 /// Toggle output pin.
602 #[inline] 653 #[inline]
603 pub fn toggle_set_as_output(&mut self) { 654 pub fn toggle_set_as_output(&mut self) {
604 self.pin.sio_oe().value_xor().write_value(self.bit()) 655 self.pin.sio_oe().value_xor().write_value(self.bit())
605 } 656 }
606 657
658 /// Get whether the pin input level is high.
607 #[inline] 659 #[inline]
608 pub fn is_high(&mut self) -> bool { 660 pub fn is_high(&mut self) -> bool {
609 !self.is_low() 661 !self.is_low()
610 } 662 }
663 /// Get whether the pin input level is low.
611 664
612 #[inline] 665 #[inline]
613 pub fn is_low(&mut self) -> bool { 666 pub fn is_low(&mut self) -> bool {
@@ -675,31 +728,37 @@ impl<'d, T: Pin> Flex<'d, T> {
675 self.pin.sio_out().value_xor().write_value(self.bit()) 728 self.pin.sio_out().value_xor().write_value(self.bit())
676 } 729 }
677 730
731 /// Wait until the pin is high. If it is already high, return immediately.
678 #[inline] 732 #[inline]
679 pub async fn wait_for_high(&mut self) { 733 pub async fn wait_for_high(&mut self) {
680 InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await; 734 InputFuture::new(&mut self.pin, InterruptTrigger::LevelHigh).await;
681 } 735 }
682 736
737 /// Wait until the pin is low. If it is already low, return immediately.
683 #[inline] 738 #[inline]
684 pub async fn wait_for_low(&mut self) { 739 pub async fn wait_for_low(&mut self) {
685 InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await; 740 InputFuture::new(&mut self.pin, InterruptTrigger::LevelLow).await;
686 } 741 }
687 742
743 /// Wait for the pin to undergo a transition from low to high.
688 #[inline] 744 #[inline]
689 pub async fn wait_for_rising_edge(&mut self) { 745 pub async fn wait_for_rising_edge(&mut self) {
690 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await; 746 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
691 } 747 }
692 748
749 /// Wait for the pin to undergo a transition from high to low.
693 #[inline] 750 #[inline]
694 pub async fn wait_for_falling_edge(&mut self) { 751 pub async fn wait_for_falling_edge(&mut self) {
695 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await; 752 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
696 } 753 }
697 754
755 /// Wait for the pin to undergo any transition, i.e low to high OR high to low.
698 #[inline] 756 #[inline]
699 pub async fn wait_for_any_edge(&mut self) { 757 pub async fn wait_for_any_edge(&mut self) {
700 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; 758 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
701 } 759 }
702 760
761 /// Configure dormant wake.
703 #[inline] 762 #[inline]
704 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { 763 pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> {
705 let idx = self.pin._pin() as usize; 764 let idx = self.pin._pin() as usize;
@@ -737,6 +796,7 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
737 } 796 }
738} 797}
739 798
799/// Dormant wake driver.
740pub struct DormantWake<'w, T: Pin> { 800pub struct DormantWake<'w, T: Pin> {
741 pin: PeripheralRef<'w, T>, 801 pin: PeripheralRef<'w, T>,
742 cfg: DormantWakeConfig, 802 cfg: DormantWakeConfig,
@@ -818,6 +878,7 @@ pub(crate) mod sealed {
818 } 878 }
819} 879}
820 880
881/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
821pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 882pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
822 /// Degrade to a generic pin struct 883 /// Degrade to a generic pin struct
823 fn degrade(self) -> AnyPin { 884 fn degrade(self) -> AnyPin {
@@ -839,6 +900,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
839 } 900 }
840} 901}
841 902
903/// Type-erased GPIO pin
842pub struct AnyPin { 904pub struct AnyPin {
843 pin_bank: u8, 905 pin_bank: u8,
844} 906}
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index 15095236a..74d015792 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -1,3 +1,4 @@
1//! I2C driver.
1use core::future; 2use core::future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -22,6 +23,7 @@ pub enum AbortReason {
22 ArbitrationLoss, 23 ArbitrationLoss,
23 /// Transmit ended with data still in fifo 24 /// Transmit ended with data still in fifo
24 TxNotEmpty(u16), 25 TxNotEmpty(u16),
26 /// Other reason.
25 Other(u32), 27 Other(u32),
26} 28}
27 29
@@ -41,9 +43,11 @@ pub enum Error {
41 AddressReserved(u16), 43 AddressReserved(u16),
42} 44}
43 45
46/// I2C config.
44#[non_exhaustive] 47#[non_exhaustive]
45#[derive(Copy, Clone)] 48#[derive(Copy, Clone)]
46pub struct Config { 49pub struct Config {
50 /// Frequency.
47 pub frequency: u32, 51 pub frequency: u32,
48} 52}
49 53
@@ -53,13 +57,16 @@ impl Default for Config {
53 } 57 }
54} 58}
55 59
60/// Size of I2C FIFO.
56pub const FIFO_SIZE: u8 = 16; 61pub const FIFO_SIZE: u8 = 16;
57 62
63/// I2C driver.
58pub struct I2c<'d, T: Instance, M: Mode> { 64pub struct I2c<'d, T: Instance, M: Mode> {
59 phantom: PhantomData<(&'d mut T, M)>, 65 phantom: PhantomData<(&'d mut T, M)>,
60} 66}
61 67
62impl<'d, T: Instance> I2c<'d, T, Blocking> { 68impl<'d, T: Instance> I2c<'d, T, Blocking> {
69 /// Create a new driver instance in blocking mode.
63 pub fn new_blocking( 70 pub fn new_blocking(
64 peri: impl Peripheral<P = T> + 'd, 71 peri: impl Peripheral<P = T> + 'd,
65 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 72 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@@ -72,6 +79,7 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
72} 79}
73 80
74impl<'d, T: Instance> I2c<'d, T, Async> { 81impl<'d, T: Instance> I2c<'d, T, Async> {
82 /// Create a new driver instance in async mode.
75 pub fn new_async( 83 pub fn new_async(
76 peri: impl Peripheral<P = T> + 'd, 84 peri: impl Peripheral<P = T> + 'd,
77 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 85 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
@@ -292,16 +300,19 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
292 } 300 }
293 } 301 }
294 302
303 /// Read from address into buffer using DMA.
295 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { 304 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
296 Self::setup(addr)?; 305 Self::setup(addr)?;
297 self.read_async_internal(buffer, true, true).await 306 self.read_async_internal(buffer, true, true).await
298 } 307 }
299 308
309 /// Write to address from buffer using DMA.
300 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> { 310 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
301 Self::setup(addr)?; 311 Self::setup(addr)?;
302 self.write_async_internal(bytes, true).await 312 self.write_async_internal(bytes, true).await
303 } 313 }
304 314
315 /// Write to address from bytes and read from address into buffer using DMA.
305 pub async fn write_read_async( 316 pub async fn write_read_async(
306 &mut self, 317 &mut self,
307 addr: u16, 318 addr: u16,
@@ -314,6 +325,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
314 } 325 }
315} 326}
316 327
328/// Interrupt handler.
317pub struct InterruptHandler<T: Instance> { 329pub struct InterruptHandler<T: Instance> {
318 _uart: PhantomData<T>, 330 _uart: PhantomData<T>,
319} 331}
@@ -569,17 +581,20 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
569 // Blocking public API 581 // Blocking public API
570 // ========================= 582 // =========================
571 583
584 /// Read from address into buffer blocking caller until done.
572 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 585 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
573 Self::setup(address.into())?; 586 Self::setup(address.into())?;
574 self.read_blocking_internal(read, true, true) 587 self.read_blocking_internal(read, true, true)
575 // Automatic Stop 588 // Automatic Stop
576 } 589 }
577 590
591 /// Write to address from buffer blocking caller until done.
578 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 592 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
579 Self::setup(address.into())?; 593 Self::setup(address.into())?;
580 self.write_blocking_internal(write, true) 594 self.write_blocking_internal(write, true)
581 } 595 }
582 596
597 /// Write to address from bytes and read from address into buffer blocking caller until done.
583 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 598 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
584 Self::setup(address.into())?; 599 Self::setup(address.into())?;
585 self.write_blocking_internal(write, false)?; 600 self.write_blocking_internal(write, false)?;
@@ -742,6 +757,7 @@ where
742 } 757 }
743} 758}
744 759
760/// Check if address is reserved.
745pub fn i2c_reserved_addr(addr: u16) -> bool { 761pub fn i2c_reserved_addr(addr: u16) -> bool {
746 ((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0 762 ((addr & 0x78) == 0 || (addr & 0x78) == 0x78) && addr != 0
747} 763}
@@ -768,6 +784,7 @@ mod sealed {
768 pub trait SclPin<T: Instance> {} 784 pub trait SclPin<T: Instance> {}
769} 785}
770 786
787/// Driver mode.
771pub trait Mode: sealed::Mode {} 788pub trait Mode: sealed::Mode {}
772 789
773macro_rules! impl_mode { 790macro_rules! impl_mode {
@@ -777,12 +794,15 @@ macro_rules! impl_mode {
777 }; 794 };
778} 795}
779 796
797/// Blocking mode.
780pub struct Blocking; 798pub struct Blocking;
799/// Async mode.
781pub struct Async; 800pub struct Async;
782 801
783impl_mode!(Blocking); 802impl_mode!(Blocking);
784impl_mode!(Async); 803impl_mode!(Async);
785 804
805/// I2C instance.
786pub trait Instance: sealed::Instance {} 806pub trait Instance: sealed::Instance {}
787 807
788macro_rules! impl_instance { 808macro_rules! impl_instance {
@@ -819,7 +839,9 @@ macro_rules! impl_instance {
819impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33); 839impl_instance!(I2C0, I2C0_IRQ, set_i2c0, 32, 33);
820impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35); 840impl_instance!(I2C1, I2C1_IRQ, set_i2c1, 34, 35);
821 841
842/// SDA pin.
822pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} 843pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
844/// SCL pin.
823pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} 845pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
824 846
825macro_rules! impl_pin { 847macro_rules! impl_pin {
diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs
index 9271ede3a..721b7a1f6 100644
--- a/embassy-rp/src/i2c_slave.rs
+++ b/embassy-rp/src/i2c_slave.rs
@@ -1,3 +1,4 @@
1//! I2C slave driver.
1use core::future; 2use core::future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -63,11 +64,13 @@ impl Default for Config {
63 } 64 }
64} 65}
65 66
67/// I2CSlave driver.
66pub struct I2cSlave<'d, T: Instance> { 68pub struct I2cSlave<'d, T: Instance> {
67 phantom: PhantomData<&'d mut T>, 69 phantom: PhantomData<&'d mut T>,
68} 70}
69 71
70impl<'d, T: Instance> I2cSlave<'d, T> { 72impl<'d, T: Instance> I2cSlave<'d, T> {
73 /// Create a new instance.
71 pub fn new( 74 pub fn new(
72 _peri: impl Peripheral<P = T> + 'd, 75 _peri: impl Peripheral<P = T> + 'd,
73 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 76 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index 5151323a9..fdacf4965 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -1,5 +1,7 @@
1#![no_std] 1#![no_std]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
3 5
4// This mod MUST go first, so that the others see its macros. 6// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt; 7pub(crate) mod fmt;
@@ -31,9 +33,7 @@ pub mod usb;
31pub mod watchdog; 33pub mod watchdog;
32 34
33// PIO 35// PIO
34// TODO: move `pio_instr_util` and `relocate` to inside `pio`
35pub mod pio; 36pub mod pio;
36pub mod pio_instr_util;
37pub(crate) mod relocate; 37pub(crate) mod relocate;
38 38
39// Reexports 39// Reexports
@@ -247,7 +247,6 @@ select_bootloader! {
247/// # Usage 247/// # Usage
248/// 248///
249/// ```no_run 249/// ```no_run
250/// #![feature(type_alias_impl_trait)]
251/// use embassy_rp::install_core0_stack_guard; 250/// use embassy_rp::install_core0_stack_guard;
252/// use embassy_executor::{Executor, Spawner}; 251/// use embassy_executor::{Executor, Spawner};
253/// 252///
@@ -302,11 +301,14 @@ fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
302 Ok(()) 301 Ok(())
303} 302}
304 303
304/// HAL configuration for RP.
305pub mod config { 305pub mod config {
306 use crate::clocks::ClockConfig; 306 use crate::clocks::ClockConfig;
307 307
308 /// HAL configuration passed when initializing.
308 #[non_exhaustive] 309 #[non_exhaustive]
309 pub struct Config { 310 pub struct Config {
311 /// Clock configuration.
310 pub clocks: ClockConfig, 312 pub clocks: ClockConfig,
311 } 313 }
312 314
@@ -319,12 +321,18 @@ pub mod config {
319 } 321 }
320 322
321 impl Config { 323 impl Config {
324 /// Create a new configuration with the provided clock config.
322 pub fn new(clocks: ClockConfig) -> Self { 325 pub fn new(clocks: ClockConfig) -> Self {
323 Self { clocks } 326 Self { clocks }
324 } 327 }
325 } 328 }
326} 329}
327 330
331/// Initialize the `embassy-rp` HAL with the provided configuration.
332///
333/// This returns the peripheral singletons that can be used for creating drivers.
334///
335/// This should only be called once at startup, otherwise it panics.
328pub fn init(config: config::Config) -> Peripherals { 336pub fn init(config: config::Config) -> Peripherals {
329 // Do this first, so that it panics if user is calling `init` a second time 337 // Do this first, so that it panics if user is calling `init` a second time
330 // before doing anything important. 338 // before doing anything important.
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index 915761801..252f30dc1 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -11,7 +11,6 @@
11//! # Usage 11//! # Usage
12//! 12//!
13//! ```no_run 13//! ```no_run
14//! # #![feature(type_alias_impl_trait)]
15//! use embassy_rp::multicore::Stack; 14//! use embassy_rp::multicore::Stack;
16//! use static_cell::StaticCell; 15//! use static_cell::StaticCell;
17//! use embassy_executor::Executor; 16//! use embassy_executor::Executor;
diff --git a/embassy-rp/src/pio_instr_util.rs b/embassy-rp/src/pio/instr.rs
index 25393b476..9a44088c6 100644
--- a/embassy-rp/src/pio_instr_util.rs
+++ b/embassy-rp/src/pio/instr.rs
@@ -1,7 +1,9 @@
1//! Instructions controlling the PIO.
1use pio::{InSource, InstructionOperands, JmpCondition, OutDestination, SetDestination}; 2use pio::{InSource, InstructionOperands, JmpCondition, OutDestination, SetDestination};
2 3
3use crate::pio::{Instance, StateMachine}; 4use crate::pio::{Instance, StateMachine};
4 5
6/// Set value of scratch register X.
5pub unsafe fn set_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, value: u32) { 7pub unsafe fn set_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, value: u32) {
6 const OUT: u16 = InstructionOperands::OUT { 8 const OUT: u16 = InstructionOperands::OUT {
7 destination: OutDestination::X, 9 destination: OutDestination::X,
@@ -12,6 +14,7 @@ pub unsafe fn set_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, S
12 sm.exec_instr(OUT); 14 sm.exec_instr(OUT);
13} 15}
14 16
17/// Get value of scratch register X.
15pub unsafe fn get_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>) -> u32 { 18pub unsafe fn get_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>) -> u32 {
16 const IN: u16 = InstructionOperands::IN { 19 const IN: u16 = InstructionOperands::IN {
17 source: InSource::X, 20 source: InSource::X,
@@ -22,6 +25,7 @@ pub unsafe fn get_x<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, S
22 sm.rx().pull() 25 sm.rx().pull()
23} 26}
24 27
28/// Set value of scratch register Y.
25pub unsafe fn set_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, value: u32) { 29pub unsafe fn set_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, value: u32) {
26 const OUT: u16 = InstructionOperands::OUT { 30 const OUT: u16 = InstructionOperands::OUT {
27 destination: OutDestination::Y, 31 destination: OutDestination::Y,
@@ -32,6 +36,7 @@ pub unsafe fn set_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, S
32 sm.exec_instr(OUT); 36 sm.exec_instr(OUT);
33} 37}
34 38
39/// Get value of scratch register Y.
35pub unsafe fn get_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>) -> u32 { 40pub unsafe fn get_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>) -> u32 {
36 const IN: u16 = InstructionOperands::IN { 41 const IN: u16 = InstructionOperands::IN {
37 source: InSource::Y, 42 source: InSource::Y,
@@ -43,6 +48,7 @@ pub unsafe fn get_y<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, S
43 sm.rx().pull() 48 sm.rx().pull()
44} 49}
45 50
51/// Set instruction for pindir destination.
46pub unsafe fn set_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u8) { 52pub unsafe fn set_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u8) {
47 let set: u16 = InstructionOperands::SET { 53 let set: u16 = InstructionOperands::SET {
48 destination: SetDestination::PINDIRS, 54 destination: SetDestination::PINDIRS,
@@ -52,6 +58,7 @@ pub unsafe fn set_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachine<P
52 sm.exec_instr(set); 58 sm.exec_instr(set);
53} 59}
54 60
61/// Set instruction for pin destination.
55pub unsafe fn set_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u8) { 62pub unsafe fn set_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u8) {
56 let set: u16 = InstructionOperands::SET { 63 let set: u16 = InstructionOperands::SET {
57 destination: SetDestination::PINS, 64 destination: SetDestination::PINS,
@@ -61,6 +68,7 @@ pub unsafe fn set_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO,
61 sm.exec_instr(set); 68 sm.exec_instr(set);
62} 69}
63 70
71/// Out instruction for pin destination.
64pub unsafe fn set_out_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u32) { 72pub unsafe fn set_out_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u32) {
65 const OUT: u16 = InstructionOperands::OUT { 73 const OUT: u16 = InstructionOperands::OUT {
66 destination: OutDestination::PINS, 74 destination: OutDestination::PINS,
@@ -70,6 +78,8 @@ pub unsafe fn set_out_pin<PIO: Instance, const SM: usize>(sm: &mut StateMachine<
70 sm.tx().push(data); 78 sm.tx().push(data);
71 sm.exec_instr(OUT); 79 sm.exec_instr(OUT);
72} 80}
81
82/// Out instruction for pindir destination.
73pub unsafe fn set_out_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u32) { 83pub unsafe fn set_out_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, data: u32) {
74 const OUT: u16 = InstructionOperands::OUT { 84 const OUT: u16 = InstructionOperands::OUT {
75 destination: OutDestination::PINDIRS, 85 destination: OutDestination::PINDIRS,
@@ -80,6 +90,7 @@ pub unsafe fn set_out_pindir<PIO: Instance, const SM: usize>(sm: &mut StateMachi
80 sm.exec_instr(OUT); 90 sm.exec_instr(OUT);
81} 91}
82 92
93/// Jump instruction to address.
83pub unsafe fn exec_jmp<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, to_addr: u8) { 94pub unsafe fn exec_jmp<PIO: Instance, const SM: usize>(sm: &mut StateMachine<PIO, SM>, to_addr: u8) {
84 let jmp: u16 = InstructionOperands::JMP { 95 let jmp: u16 = InstructionOperands::JMP {
85 address: to_addr, 96 address: to_addr,
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio/mod.rs
index 97dfce2e6..ca9795024 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -1,3 +1,4 @@
1//! PIO driver.
1use core::future::Future; 2use core::future::Future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::pin::Pin as FuturePin; 4use core::pin::Pin as FuturePin;
@@ -19,8 +20,11 @@ use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate};
19use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; 20use crate::interrupt::typelevel::{Binding, Handler, Interrupt};
20use crate::pac::dma::vals::TreqSel; 21use crate::pac::dma::vals::TreqSel;
21use crate::relocate::RelocatedProgram; 22use crate::relocate::RelocatedProgram;
22use crate::{pac, peripherals, pio_instr_util, RegExt}; 23use crate::{pac, peripherals, RegExt};
23 24
25pub mod instr;
26
27/// Wakers for interrupts and FIFOs.
24pub struct Wakers([AtomicWaker; 12]); 28pub struct Wakers([AtomicWaker; 12]);
25 29
26impl Wakers { 30impl Wakers {
@@ -38,6 +42,7 @@ impl Wakers {
38 } 42 }
39} 43}
40 44
45/// FIFO config.
41#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] 46#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))] 47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43#[repr(u8)] 48#[repr(u8)]
@@ -51,6 +56,8 @@ pub enum FifoJoin {
51 TxOnly, 56 TxOnly,
52} 57}
53 58
59/// Shift direction.
60#[allow(missing_docs)]
54#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] 61#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))] 62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56#[repr(u8)] 63#[repr(u8)]
@@ -60,6 +67,8 @@ pub enum ShiftDirection {
60 Left = 0, 67 Left = 0,
61} 68}
62 69
70/// Pin direction.
71#[allow(missing_docs)]
63#[derive(Clone, Copy, PartialEq, Eq, Debug)] 72#[derive(Clone, Copy, PartialEq, Eq, Debug)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))] 73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65#[repr(u8)] 74#[repr(u8)]
@@ -68,12 +77,15 @@ pub enum Direction {
68 Out = 1, 77 Out = 1,
69} 78}
70 79
80/// Which fifo level to use in status check.
71#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] 81#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
72#[cfg_attr(feature = "defmt", derive(defmt::Format))] 82#[cfg_attr(feature = "defmt", derive(defmt::Format))]
73#[repr(u8)] 83#[repr(u8)]
74pub enum StatusSource { 84pub enum StatusSource {
75 #[default] 85 #[default]
86 /// All-ones if TX FIFO level < N, otherwise all-zeroes.
76 TxFifoLevel = 0, 87 TxFifoLevel = 0,
88 /// All-ones if RX FIFO level < N, otherwise all-zeroes.
77 RxFifoLevel = 1, 89 RxFifoLevel = 1,
78} 90}
79 91
@@ -81,6 +93,7 @@ const RXNEMPTY_MASK: u32 = 1 << 0;
81const TXNFULL_MASK: u32 = 1 << 4; 93const TXNFULL_MASK: u32 = 1 << 4;
82const SMIRQ_MASK: u32 = 1 << 8; 94const SMIRQ_MASK: u32 = 1 << 8;
83 95
96/// Interrupt handler for PIO.
84pub struct InterruptHandler<PIO: Instance> { 97pub struct InterruptHandler<PIO: Instance> {
85 _pio: PhantomData<PIO>, 98 _pio: PhantomData<PIO>,
86} 99}
@@ -105,6 +118,7 @@ pub struct FifoOutFuture<'a, 'd, PIO: Instance, const SM: usize> {
105} 118}
106 119
107impl<'a, 'd, PIO: Instance, const SM: usize> FifoOutFuture<'a, 'd, PIO, SM> { 120impl<'a, 'd, PIO: Instance, const SM: usize> FifoOutFuture<'a, 'd, PIO, SM> {
121 /// Create a new future waiting for TX-FIFO to become writable.
108 pub fn new(sm: &'a mut StateMachineTx<'d, PIO, SM>, value: u32) -> Self { 122 pub fn new(sm: &'a mut StateMachineTx<'d, PIO, SM>, value: u32) -> Self {
109 FifoOutFuture { sm_tx: sm, value } 123 FifoOutFuture { sm_tx: sm, value }
110 } 124 }
@@ -136,13 +150,14 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoOutFuture<'a, 'd, PIO,
136 } 150 }
137} 151}
138 152
139/// Future that waits for RX-FIFO to become readable 153/// Future that waits for RX-FIFO to become readable.
140#[must_use = "futures do nothing unless you `.await` or poll them"] 154#[must_use = "futures do nothing unless you `.await` or poll them"]
141pub struct FifoInFuture<'a, 'd, PIO: Instance, const SM: usize> { 155pub struct FifoInFuture<'a, 'd, PIO: Instance, const SM: usize> {
142 sm_rx: &'a mut StateMachineRx<'d, PIO, SM>, 156 sm_rx: &'a mut StateMachineRx<'d, PIO, SM>,
143} 157}
144 158
145impl<'a, 'd, PIO: Instance, const SM: usize> FifoInFuture<'a, 'd, PIO, SM> { 159impl<'a, 'd, PIO: Instance, const SM: usize> FifoInFuture<'a, 'd, PIO, SM> {
160 /// Create future that waits for RX-FIFO to become readable.
146 pub fn new(sm: &'a mut StateMachineRx<'d, PIO, SM>) -> Self { 161 pub fn new(sm: &'a mut StateMachineRx<'d, PIO, SM>) -> Self {
147 FifoInFuture { sm_rx: sm } 162 FifoInFuture { sm_rx: sm }
148 } 163 }
@@ -207,6 +222,7 @@ impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> {
207 } 222 }
208} 223}
209 224
225/// Type representing a PIO pin.
210pub struct Pin<'l, PIO: Instance> { 226pub struct Pin<'l, PIO: Instance> {
211 pin: PeripheralRef<'l, AnyPin>, 227 pin: PeripheralRef<'l, AnyPin>,
212 pio: PhantomData<PIO>, 228 pio: PhantomData<PIO>,
@@ -226,7 +242,7 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
226 }); 242 });
227 } 243 }
228 244
229 // Set the pin's slew rate. 245 /// Set the pin's slew rate.
230 #[inline] 246 #[inline]
231 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 247 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
232 self.pin.pad_ctrl().modify(|w| { 248 self.pin.pad_ctrl().modify(|w| {
@@ -251,6 +267,7 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
251 }); 267 });
252 } 268 }
253 269
270 /// Set the pin's input sync bypass.
254 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { 271 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) {
255 let mask = 1 << self.pin(); 272 let mask = 1 << self.pin();
256 if bypass { 273 if bypass {
@@ -260,28 +277,34 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
260 } 277 }
261 } 278 }
262 279
280 /// Get the underlying pin number.
263 pub fn pin(&self) -> u8 { 281 pub fn pin(&self) -> u8 {
264 self.pin._pin() 282 self.pin._pin()
265 } 283 }
266} 284}
267 285
286/// Type representing a state machine RX FIFO.
268pub struct StateMachineRx<'d, PIO: Instance, const SM: usize> { 287pub struct StateMachineRx<'d, PIO: Instance, const SM: usize> {
269 pio: PhantomData<&'d mut PIO>, 288 pio: PhantomData<&'d mut PIO>,
270} 289}
271 290
272impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { 291impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
292 /// Check if RX FIFO is empty.
273 pub fn empty(&self) -> bool { 293 pub fn empty(&self) -> bool {
274 PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 294 PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0
275 } 295 }
276 296
297 /// Check if RX FIFO is full.
277 pub fn full(&self) -> bool { 298 pub fn full(&self) -> bool {
278 PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 299 PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0
279 } 300 }
280 301
302 /// Check RX FIFO level.
281 pub fn level(&self) -> u8 { 303 pub fn level(&self) -> u8 {
282 (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f 304 (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f
283 } 305 }
284 306
307 /// Check if state machine has stalled on full RX FIFO.
285 pub fn stalled(&self) -> bool { 308 pub fn stalled(&self) -> bool {
286 let fdebug = PIO::PIO.fdebug(); 309 let fdebug = PIO::PIO.fdebug();
287 let ret = fdebug.read().rxstall() & (1 << SM) != 0; 310 let ret = fdebug.read().rxstall() & (1 << SM) != 0;
@@ -291,6 +314,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
291 ret 314 ret
292 } 315 }
293 316
317 /// Check if RX FIFO underflow (i.e. read-on-empty by the system) has occurred.
294 pub fn underflowed(&self) -> bool { 318 pub fn underflowed(&self) -> bool {
295 let fdebug = PIO::PIO.fdebug(); 319 let fdebug = PIO::PIO.fdebug();
296 let ret = fdebug.read().rxunder() & (1 << SM) != 0; 320 let ret = fdebug.read().rxunder() & (1 << SM) != 0;
@@ -300,10 +324,12 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
300 ret 324 ret
301 } 325 }
302 326
327 /// Pull data from RX FIFO.
303 pub fn pull(&mut self) -> u32 { 328 pub fn pull(&mut self) -> u32 {
304 PIO::PIO.rxf(SM).read() 329 PIO::PIO.rxf(SM).read()
305 } 330 }
306 331
332 /// Attempt pulling data from RX FIFO.
307 pub fn try_pull(&mut self) -> Option<u32> { 333 pub fn try_pull(&mut self) -> Option<u32> {
308 if self.empty() { 334 if self.empty() {
309 return None; 335 return None;
@@ -311,10 +337,12 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
311 Some(self.pull()) 337 Some(self.pull())
312 } 338 }
313 339
340 /// Wait for RX FIFO readable.
314 pub fn wait_pull<'a>(&'a mut self) -> FifoInFuture<'a, 'd, PIO, SM> { 341 pub fn wait_pull<'a>(&'a mut self) -> FifoInFuture<'a, 'd, PIO, SM> {
315 FifoInFuture::new(self) 342 FifoInFuture::new(self)
316 } 343 }
317 344
345 /// Prepare DMA transfer from RX FIFO.
318 pub fn dma_pull<'a, C: Channel, W: Word>( 346 pub fn dma_pull<'a, C: Channel, W: Word>(
319 &'a mut self, 347 &'a mut self,
320 ch: PeripheralRef<'a, C>, 348 ch: PeripheralRef<'a, C>,
@@ -340,22 +368,28 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
340 } 368 }
341} 369}
342 370
371/// Type representing a state machine TX FIFO.
343pub struct StateMachineTx<'d, PIO: Instance, const SM: usize> { 372pub struct StateMachineTx<'d, PIO: Instance, const SM: usize> {
344 pio: PhantomData<&'d mut PIO>, 373 pio: PhantomData<&'d mut PIO>,
345} 374}
346 375
347impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { 376impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
377 /// Check if TX FIFO is empty.
348 pub fn empty(&self) -> bool { 378 pub fn empty(&self) -> bool {
349 PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 379 PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0
350 } 380 }
381
382 /// Check if TX FIFO is full.
351 pub fn full(&self) -> bool { 383 pub fn full(&self) -> bool {
352 PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 384 PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0
353 } 385 }
354 386
387 /// Check TX FIFO level.
355 pub fn level(&self) -> u8 { 388 pub fn level(&self) -> u8 {
356 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f 389 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f
357 } 390 }
358 391
392 /// Check state machine has stalled on empty TX FIFO.
359 pub fn stalled(&self) -> bool { 393 pub fn stalled(&self) -> bool {
360 let fdebug = PIO::PIO.fdebug(); 394 let fdebug = PIO::PIO.fdebug();
361 let ret = fdebug.read().txstall() & (1 << SM) != 0; 395 let ret = fdebug.read().txstall() & (1 << SM) != 0;
@@ -365,6 +399,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
365 ret 399 ret
366 } 400 }
367 401
402 /// Check if FIFO overflowed.
368 pub fn overflowed(&self) -> bool { 403 pub fn overflowed(&self) -> bool {
369 let fdebug = PIO::PIO.fdebug(); 404 let fdebug = PIO::PIO.fdebug();
370 let ret = fdebug.read().txover() & (1 << SM) != 0; 405 let ret = fdebug.read().txover() & (1 << SM) != 0;
@@ -374,10 +409,12 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
374 ret 409 ret
375 } 410 }
376 411
412 /// Force push data to TX FIFO.
377 pub fn push(&mut self, v: u32) { 413 pub fn push(&mut self, v: u32) {
378 PIO::PIO.txf(SM).write_value(v); 414 PIO::PIO.txf(SM).write_value(v);
379 } 415 }
380 416
417 /// Attempt to push data to TX FIFO.
381 pub fn try_push(&mut self, v: u32) -> bool { 418 pub fn try_push(&mut self, v: u32) -> bool {
382 if self.full() { 419 if self.full() {
383 return false; 420 return false;
@@ -386,10 +423,12 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
386 true 423 true
387 } 424 }
388 425
426 /// Wait until FIFO is ready for writing.
389 pub fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, 'd, PIO, SM> { 427 pub fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, 'd, PIO, SM> {
390 FifoOutFuture::new(self, value) 428 FifoOutFuture::new(self, value)
391 } 429 }
392 430
431 /// Prepare a DMA transfer to TX FIFO.
393 pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> { 432 pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> {
394 let pio_no = PIO::PIO_NO; 433 let pio_no = PIO::PIO_NO;
395 let p = ch.regs(); 434 let p = ch.regs();
@@ -411,6 +450,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
411 } 450 }
412} 451}
413 452
453/// A type representing a single PIO state machine.
414pub struct StateMachine<'d, PIO: Instance, const SM: usize> { 454pub struct StateMachine<'d, PIO: Instance, const SM: usize> {
415 rx: StateMachineRx<'d, PIO, SM>, 455 rx: StateMachineRx<'d, PIO, SM>,
416 tx: StateMachineTx<'d, PIO, SM>, 456 tx: StateMachineTx<'d, PIO, SM>,
@@ -430,52 +470,78 @@ fn assert_consecutive<'d, PIO: Instance>(pins: &[&Pin<'d, PIO>]) {
430 } 470 }
431} 471}
432 472
473/// PIO Execution config.
433#[derive(Clone, Copy, Default, Debug)] 474#[derive(Clone, Copy, Default, Debug)]
434#[cfg_attr(feature = "defmt", derive(defmt::Format))] 475#[cfg_attr(feature = "defmt", derive(defmt::Format))]
435#[non_exhaustive] 476#[non_exhaustive]
436pub struct ExecConfig { 477pub struct ExecConfig {
478 /// If true, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit.
437 pub side_en: bool, 479 pub side_en: bool,
480 /// If true, side-set data is asserted to pin directions, instead of pin values.
438 pub side_pindir: bool, 481 pub side_pindir: bool,
482 /// Pin to trigger jump.
439 pub jmp_pin: u8, 483 pub jmp_pin: u8,
484 /// After reaching this address, execution is wrapped to wrap_bottom.
440 pub wrap_top: u8, 485 pub wrap_top: u8,
486 /// After reaching wrap_top, execution is wrapped to this address.
441 pub wrap_bottom: u8, 487 pub wrap_bottom: u8,
442} 488}
443 489
490/// PIO shift register config for input or output.
444#[derive(Clone, Copy, Default, Debug)] 491#[derive(Clone, Copy, Default, Debug)]
445#[cfg_attr(feature = "defmt", derive(defmt::Format))] 492#[cfg_attr(feature = "defmt", derive(defmt::Format))]
446pub struct ShiftConfig { 493pub struct ShiftConfig {
494 /// Number of bits shifted out of OSR before autopull.
447 pub threshold: u8, 495 pub threshold: u8,
496 /// Shift direction.
448 pub direction: ShiftDirection, 497 pub direction: ShiftDirection,
498 /// For output: Pull automatically output shift register is emptied.
499 /// For input: Push automatically when the input shift register is filled.
449 pub auto_fill: bool, 500 pub auto_fill: bool,
450} 501}
451 502
503/// PIO pin config.
452#[derive(Clone, Copy, Default, Debug)] 504#[derive(Clone, Copy, Default, Debug)]
453#[cfg_attr(feature = "defmt", derive(defmt::Format))] 505#[cfg_attr(feature = "defmt", derive(defmt::Format))]
454pub struct PinConfig { 506pub struct PinConfig {
507 /// The number of MSBs of the Delay/Side-set instruction field which are used for side-set.
455 pub sideset_count: u8, 508 pub sideset_count: u8,
509 /// The number of pins asserted by a SET. In the range 0 to 5 inclusive.
456 pub set_count: u8, 510 pub set_count: u8,
511 /// The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive.
457 pub out_count: u8, 512 pub out_count: u8,
513 /// The pin which is mapped to the least-significant bit of a state machine's IN data bus.
458 pub in_base: u8, 514 pub in_base: u8,
515 /// The lowest-numbered pin that will be affected by a side-set operation.
459 pub sideset_base: u8, 516 pub sideset_base: u8,
517 /// The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction.
460 pub set_base: u8, 518 pub set_base: u8,
519 /// The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction.
461 pub out_base: u8, 520 pub out_base: u8,
462} 521}
463 522
523/// PIO config.
464#[derive(Clone, Copy, Debug)] 524#[derive(Clone, Copy, Debug)]
465pub struct Config<'d, PIO: Instance> { 525pub struct Config<'d, PIO: Instance> {
466 // CLKDIV 526 /// Clock divisor register for state machines.
467 pub clock_divider: FixedU32<U8>, 527 pub clock_divider: FixedU32<U8>,
468 // EXECCTRL 528 /// Which data bit to use for inline OUT enable.
469 pub out_en_sel: u8, 529 pub out_en_sel: u8,
530 /// Use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY.
470 pub inline_out_en: bool, 531 pub inline_out_en: bool,
532 /// Continuously assert the most recent OUT/SET to the pins.
471 pub out_sticky: bool, 533 pub out_sticky: bool,
534 /// Which source to use for checking status.
472 pub status_sel: StatusSource, 535 pub status_sel: StatusSource,
536 /// Status comparison level.
473 pub status_n: u8, 537 pub status_n: u8,
474 exec: ExecConfig, 538 exec: ExecConfig,
475 origin: Option<u8>, 539 origin: Option<u8>,
476 // SHIFTCTRL 540 /// Configure FIFO allocation.
477 pub fifo_join: FifoJoin, 541 pub fifo_join: FifoJoin,
542 /// Input shifting config.
478 pub shift_in: ShiftConfig, 543 pub shift_in: ShiftConfig,
544 /// Output shifting config.
479 pub shift_out: ShiftConfig, 545 pub shift_out: ShiftConfig,
480 // PINCTRL 546 // PINCTRL
481 pins: PinConfig, 547 pins: PinConfig,
@@ -505,16 +571,22 @@ impl<'d, PIO: Instance> Default for Config<'d, PIO> {
505} 571}
506 572
507impl<'d, PIO: Instance> Config<'d, PIO> { 573impl<'d, PIO: Instance> Config<'d, PIO> {
574 /// Get execution configuration.
508 pub fn get_exec(&self) -> ExecConfig { 575 pub fn get_exec(&self) -> ExecConfig {
509 self.exec 576 self.exec
510 } 577 }
578
579 /// Update execution configuration.
511 pub unsafe fn set_exec(&mut self, e: ExecConfig) { 580 pub unsafe fn set_exec(&mut self, e: ExecConfig) {
512 self.exec = e; 581 self.exec = e;
513 } 582 }
514 583
584 /// Get pin configuration.
515 pub fn get_pins(&self) -> PinConfig { 585 pub fn get_pins(&self) -> PinConfig {
516 self.pins 586 self.pins
517 } 587 }
588
589 /// Update pin configuration.
518 pub unsafe fn set_pins(&mut self, p: PinConfig) { 590 pub unsafe fn set_pins(&mut self, p: PinConfig) {
519 self.pins = p; 591 self.pins = p;
520 } 592 }
@@ -537,6 +609,7 @@ impl<'d, PIO: Instance> Config<'d, PIO> {
537 self.origin = Some(prog.origin); 609 self.origin = Some(prog.origin);
538 } 610 }
539 611
612 /// Set pin used to signal jump.
540 pub fn set_jmp_pin(&mut self, pin: &Pin<'d, PIO>) { 613 pub fn set_jmp_pin(&mut self, pin: &Pin<'d, PIO>) {
541 self.exec.jmp_pin = pin.pin(); 614 self.exec.jmp_pin = pin.pin();
542 } 615 }
@@ -571,6 +644,7 @@ impl<'d, PIO: Instance> Config<'d, PIO> {
571} 644}
572 645
573impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { 646impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
647 /// Set the config for a given PIO state machine.
574 pub fn set_config(&mut self, config: &Config<'d, PIO>) { 648 pub fn set_config(&mut self, config: &Config<'d, PIO>) {
575 // sm expects 0 for 65536, truncation makes that happen 649 // sm expects 0 for 65536, truncation makes that happen
576 assert!(config.clock_divider <= 65536, "clkdiv must be <= 65536"); 650 assert!(config.clock_divider <= 65536, "clkdiv must be <= 65536");
@@ -617,7 +691,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
617 w.set_out_base(config.pins.out_base); 691 w.set_out_base(config.pins.out_base);
618 }); 692 });
619 if let Some(origin) = config.origin { 693 if let Some(origin) = config.origin {
620 unsafe { pio_instr_util::exec_jmp(self, origin) } 694 unsafe { instr::exec_jmp(self, origin) }
621 } 695 }
622 } 696 }
623 697
@@ -626,10 +700,13 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
626 PIO::PIO.sm(SM) 700 PIO::PIO.sm(SM)
627 } 701 }
628 702
703 /// Restart this state machine.
629 pub fn restart(&mut self) { 704 pub fn restart(&mut self) {
630 let mask = 1u8 << SM; 705 let mask = 1u8 << SM;
631 PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask)); 706 PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask));
632 } 707 }
708
709 /// Enable state machine.
633 pub fn set_enable(&mut self, enable: bool) { 710 pub fn set_enable(&mut self, enable: bool) {
634 let mask = 1u8 << SM; 711 let mask = 1u8 << SM;
635 if enable { 712 if enable {
@@ -639,10 +716,12 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
639 } 716 }
640 } 717 }
641 718
719 /// Check if state machine is enabled.
642 pub fn is_enabled(&self) -> bool { 720 pub fn is_enabled(&self) -> bool {
643 PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 721 PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0
644 } 722 }
645 723
724 /// Restart a state machine's clock divider from an initial phase of 0.
646 pub fn clkdiv_restart(&mut self) { 725 pub fn clkdiv_restart(&mut self) {
647 let mask = 1u8 << SM; 726 let mask = 1u8 << SM;
648 PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask)); 727 PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask));
@@ -690,6 +769,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
690 }); 769 });
691 } 770 }
692 771
772 /// Flush FIFOs for state machine.
693 pub fn clear_fifos(&mut self) { 773 pub fn clear_fifos(&mut self) {
694 // Toggle FJOIN_RX to flush FIFOs 774 // Toggle FJOIN_RX to flush FIFOs
695 let shiftctrl = Self::this_sm().shiftctrl(); 775 let shiftctrl = Self::this_sm().shiftctrl();
@@ -701,21 +781,31 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
701 }); 781 });
702 } 782 }
703 783
784 /// Instruct state machine to execute a given instructions
785 ///
786 /// SAFETY: The state machine must be in a state where executing
787 /// an arbitrary instruction does not crash it.
704 pub unsafe fn exec_instr(&mut self, instr: u16) { 788 pub unsafe fn exec_instr(&mut self, instr: u16) {
705 Self::this_sm().instr().write(|w| w.set_instr(instr)); 789 Self::this_sm().instr().write(|w| w.set_instr(instr));
706 } 790 }
707 791
792 /// Return a read handle for reading state machine outputs.
708 pub fn rx(&mut self) -> &mut StateMachineRx<'d, PIO, SM> { 793 pub fn rx(&mut self) -> &mut StateMachineRx<'d, PIO, SM> {
709 &mut self.rx 794 &mut self.rx
710 } 795 }
796
797 /// Return a handle for writing to inputs.
711 pub fn tx(&mut self) -> &mut StateMachineTx<'d, PIO, SM> { 798 pub fn tx(&mut self) -> &mut StateMachineTx<'d, PIO, SM> {
712 &mut self.tx 799 &mut self.tx
713 } 800 }
801
802 /// Return both read and write handles for the state machine.
714 pub fn rx_tx(&mut self) -> (&mut StateMachineRx<'d, PIO, SM>, &mut StateMachineTx<'d, PIO, SM>) { 803 pub fn rx_tx(&mut self) -> (&mut StateMachineRx<'d, PIO, SM>, &mut StateMachineTx<'d, PIO, SM>) {
715 (&mut self.rx, &mut self.tx) 804 (&mut self.rx, &mut self.tx)
716 } 805 }
717} 806}
718 807
808/// PIO handle.
719pub struct Common<'d, PIO: Instance> { 809pub struct Common<'d, PIO: Instance> {
720 instructions_used: u32, 810 instructions_used: u32,
721 pio: PhantomData<&'d mut PIO>, 811 pio: PhantomData<&'d mut PIO>,
@@ -727,18 +817,25 @@ impl<'d, PIO: Instance> Drop for Common<'d, PIO> {
727 } 817 }
728} 818}
729 819
820/// Memory of PIO instance.
730pub struct InstanceMemory<'d, PIO: Instance> { 821pub struct InstanceMemory<'d, PIO: Instance> {
731 used_mask: u32, 822 used_mask: u32,
732 pio: PhantomData<&'d mut PIO>, 823 pio: PhantomData<&'d mut PIO>,
733} 824}
734 825
826/// A loaded PIO program.
735pub struct LoadedProgram<'d, PIO: Instance> { 827pub struct LoadedProgram<'d, PIO: Instance> {
828 /// Memory used by program.
736 pub used_memory: InstanceMemory<'d, PIO>, 829 pub used_memory: InstanceMemory<'d, PIO>,
830 /// Program origin for loading.
737 pub origin: u8, 831 pub origin: u8,
832 /// Wrap controls what to do once program is done executing.
738 pub wrap: Wrap, 833 pub wrap: Wrap,
834 /// Data for 'side' set instruction parameters.
739 pub side_set: SideSet, 835 pub side_set: SideSet,
740} 836}
741 837
838/// Errors loading a PIO program.
742#[derive(Clone, Copy, PartialEq, Eq, Debug)] 839#[derive(Clone, Copy, PartialEq, Eq, Debug)]
743#[cfg_attr(feature = "defmt", derive(defmt::Format))] 840#[cfg_attr(feature = "defmt", derive(defmt::Format))]
744pub enum LoadError { 841pub enum LoadError {
@@ -834,6 +931,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
834 self.instructions_used &= !instrs.used_mask; 931 self.instructions_used &= !instrs.used_mask;
835 } 932 }
836 933
934 /// Bypass flipflop synchronizer on GPIO inputs.
837 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { 935 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
838 // this can interfere with per-pin bypass functions. splitting the 936 // this can interfere with per-pin bypass functions. splitting the
839 // modification is going to be fine since nothing that relies on 937 // modification is going to be fine since nothing that relies on
@@ -842,6 +940,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
842 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass); 940 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass);
843 } 941 }
844 942
943 /// Get bypass configuration.
845 pub fn get_input_sync_bypass(&self) -> u32 { 944 pub fn get_input_sync_bypass(&self) -> u32 {
846 PIO::PIO.input_sync_bypass().read() 945 PIO::PIO.input_sync_bypass().read()
847 } 946 }
@@ -861,6 +960,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
861 } 960 }
862 } 961 }
863 962
963 /// Apply changes to all state machines in a batch.
864 pub fn apply_sm_batch(&mut self, f: impl FnOnce(&mut PioBatch<'d, PIO>)) { 964 pub fn apply_sm_batch(&mut self, f: impl FnOnce(&mut PioBatch<'d, PIO>)) {
865 let mut batch = PioBatch { 965 let mut batch = PioBatch {
866 clkdiv_restart: 0, 966 clkdiv_restart: 0,
@@ -878,6 +978,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
878 } 978 }
879} 979}
880 980
981/// Represents multiple state machines in a single type.
881pub struct PioBatch<'a, PIO: Instance> { 982pub struct PioBatch<'a, PIO: Instance> {
882 clkdiv_restart: u8, 983 clkdiv_restart: u8,
883 sm_restart: u8, 984 sm_restart: u8,
@@ -887,25 +988,25 @@ pub struct PioBatch<'a, PIO: Instance> {
887} 988}
888 989
889impl<'a, PIO: Instance> PioBatch<'a, PIO> { 990impl<'a, PIO: Instance> PioBatch<'a, PIO> {
890 pub fn restart_clockdiv<const SM: usize>(&mut self, _sm: &mut StateMachine<'a, PIO, SM>) { 991 /// Restart a state machine's clock divider from an initial phase of 0.
891 self.clkdiv_restart |= 1 << SM;
892 }
893
894 pub fn restart<const SM: usize>(&mut self, _sm: &mut StateMachine<'a, PIO, SM>) { 992 pub fn restart<const SM: usize>(&mut self, _sm: &mut StateMachine<'a, PIO, SM>) {
895 self.clkdiv_restart |= 1 << SM; 993 self.clkdiv_restart |= 1 << SM;
896 } 994 }
897 995
996 /// Enable a specific state machine.
898 pub fn set_enable<const SM: usize>(&mut self, _sm: &mut StateMachine<'a, PIO, SM>, enable: bool) { 997 pub fn set_enable<const SM: usize>(&mut self, _sm: &mut StateMachine<'a, PIO, SM>, enable: bool) {
899 self.sm_enable_mask |= 1 << SM; 998 self.sm_enable_mask |= 1 << SM;
900 self.sm_enable |= (enable as u8) << SM; 999 self.sm_enable |= (enable as u8) << SM;
901 } 1000 }
902} 1001}
903 1002
1003/// Type representing a PIO interrupt.
904pub struct Irq<'d, PIO: Instance, const N: usize> { 1004pub struct Irq<'d, PIO: Instance, const N: usize> {
905 pio: PhantomData<&'d mut PIO>, 1005 pio: PhantomData<&'d mut PIO>,
906} 1006}
907 1007
908impl<'d, PIO: Instance, const N: usize> Irq<'d, PIO, N> { 1008impl<'d, PIO: Instance, const N: usize> Irq<'d, PIO, N> {
1009 /// Wait for an IRQ to fire.
909 pub fn wait<'a>(&'a mut self) -> IrqFuture<'a, 'd, PIO> { 1010 pub fn wait<'a>(&'a mut self) -> IrqFuture<'a, 'd, PIO> {
910 IrqFuture { 1011 IrqFuture {
911 pio: PhantomData, 1012 pio: PhantomData,
@@ -914,59 +1015,79 @@ impl<'d, PIO: Instance, const N: usize> Irq<'d, PIO, N> {
914 } 1015 }
915} 1016}
916 1017
1018/// Interrupt flags for a PIO instance.
917#[derive(Clone)] 1019#[derive(Clone)]
918pub struct IrqFlags<'d, PIO: Instance> { 1020pub struct IrqFlags<'d, PIO: Instance> {
919 pio: PhantomData<&'d mut PIO>, 1021 pio: PhantomData<&'d mut PIO>,
920} 1022}
921 1023
922impl<'d, PIO: Instance> IrqFlags<'d, PIO> { 1024impl<'d, PIO: Instance> IrqFlags<'d, PIO> {
1025 /// Check if interrupt fired.
923 pub fn check(&self, irq_no: u8) -> bool { 1026 pub fn check(&self, irq_no: u8) -> bool {
924 assert!(irq_no < 8); 1027 assert!(irq_no < 8);
925 self.check_any(1 << irq_no) 1028 self.check_any(1 << irq_no)
926 } 1029 }
927 1030
1031 /// Check if any of the interrupts in the bitmap fired.
928 pub fn check_any(&self, irqs: u8) -> bool { 1032 pub fn check_any(&self, irqs: u8) -> bool {
929 PIO::PIO.irq().read().irq() & irqs != 0 1033 PIO::PIO.irq().read().irq() & irqs != 0
930 } 1034 }
931 1035
1036 /// Check if all interrupts have fired.
932 pub fn check_all(&self, irqs: u8) -> bool { 1037 pub fn check_all(&self, irqs: u8) -> bool {
933 PIO::PIO.irq().read().irq() & irqs == irqs 1038 PIO::PIO.irq().read().irq() & irqs == irqs
934 } 1039 }
935 1040
1041 /// Clear interrupt for interrupt number.
936 pub fn clear(&self, irq_no: usize) { 1042 pub fn clear(&self, irq_no: usize) {
937 assert!(irq_no < 8); 1043 assert!(irq_no < 8);
938 self.clear_all(1 << irq_no); 1044 self.clear_all(1 << irq_no);
939 } 1045 }
940 1046
1047 /// Clear all interrupts set in the bitmap.
941 pub fn clear_all(&self, irqs: u8) { 1048 pub fn clear_all(&self, irqs: u8) {
942 PIO::PIO.irq().write(|w| w.set_irq(irqs)) 1049 PIO::PIO.irq().write(|w| w.set_irq(irqs))
943 } 1050 }
944 1051
1052 /// Fire a given interrupt.
945 pub fn set(&self, irq_no: usize) { 1053 pub fn set(&self, irq_no: usize) {
946 assert!(irq_no < 8); 1054 assert!(irq_no < 8);
947 self.set_all(1 << irq_no); 1055 self.set_all(1 << irq_no);
948 } 1056 }
949 1057
1058 /// Fire all interrupts.
950 pub fn set_all(&self, irqs: u8) { 1059 pub fn set_all(&self, irqs: u8) {
951 PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) 1060 PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs))
952 } 1061 }
953} 1062}
954 1063
1064/// An instance of the PIO driver.
955pub struct Pio<'d, PIO: Instance> { 1065pub struct Pio<'d, PIO: Instance> {
1066 /// PIO handle.
956 pub common: Common<'d, PIO>, 1067 pub common: Common<'d, PIO>,
1068 /// PIO IRQ flags.
957 pub irq_flags: IrqFlags<'d, PIO>, 1069 pub irq_flags: IrqFlags<'d, PIO>,
1070 /// IRQ0 configuration.
958 pub irq0: Irq<'d, PIO, 0>, 1071 pub irq0: Irq<'d, PIO, 0>,
1072 /// IRQ1 configuration.
959 pub irq1: Irq<'d, PIO, 1>, 1073 pub irq1: Irq<'d, PIO, 1>,
1074 /// IRQ2 configuration.
960 pub irq2: Irq<'d, PIO, 2>, 1075 pub irq2: Irq<'d, PIO, 2>,
1076 /// IRQ3 configuration.
961 pub irq3: Irq<'d, PIO, 3>, 1077 pub irq3: Irq<'d, PIO, 3>,
1078 /// State machine 0 handle.
962 pub sm0: StateMachine<'d, PIO, 0>, 1079 pub sm0: StateMachine<'d, PIO, 0>,
1080 /// State machine 1 handle.
963 pub sm1: StateMachine<'d, PIO, 1>, 1081 pub sm1: StateMachine<'d, PIO, 1>,
1082 /// State machine 2 handle.
964 pub sm2: StateMachine<'d, PIO, 2>, 1083 pub sm2: StateMachine<'d, PIO, 2>,
1084 /// State machine 3 handle.
965 pub sm3: StateMachine<'d, PIO, 3>, 1085 pub sm3: StateMachine<'d, PIO, 3>,
966 _pio: PhantomData<&'d mut PIO>, 1086 _pio: PhantomData<&'d mut PIO>,
967} 1087}
968 1088
969impl<'d, PIO: Instance> Pio<'d, PIO> { 1089impl<'d, PIO: Instance> Pio<'d, PIO> {
1090 /// Create a new instance of a PIO peripheral.
970 pub fn new(_pio: impl Peripheral<P = PIO> + 'd, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { 1091 pub fn new(_pio: impl Peripheral<P = PIO> + 'd, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self {
971 PIO::state().users.store(5, Ordering::Release); 1092 PIO::state().users.store(5, Ordering::Release);
972 PIO::state().used_pins.store(0, Ordering::Release); 1093 PIO::state().used_pins.store(0, Ordering::Release);
@@ -1003,9 +1124,10 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1003 } 1124 }
1004} 1125}
1005 1126
1006// we need to keep a record of which pins are assigned to each PIO. make_pio_pin 1127/// Representation of the PIO state keeping a record of which pins are assigned to
1007// notionally takes ownership of the pin it is given, but the wrapped pin cannot 1128/// each PIO.
1008// be treated as an owned resource since dropping it would have to deconfigure 1129// make_pio_pin notionally takes ownership of the pin it is given, but the wrapped pin
1130// cannot be treated as an owned resource since dropping it would have to deconfigure
1009// the pin, breaking running state machines in the process. pins are also shared 1131// the pin, breaking running state machines in the process. pins are also shared
1010// between all state machines, which makes ownership even messier to track any 1132// between all state machines, which makes ownership even messier to track any
1011// other way. 1133// other way.
@@ -1059,6 +1181,7 @@ mod sealed {
1059 } 1181 }
1060} 1182}
1061 1183
1184/// PIO instance.
1062pub trait Instance: sealed::Instance + Sized + Unpin {} 1185pub trait Instance: sealed::Instance + Sized + Unpin {}
1063 1186
1064macro_rules! impl_pio { 1187macro_rules! impl_pio {
@@ -1076,6 +1199,7 @@ macro_rules! impl_pio {
1076impl_pio!(PIO0, 0, PIO0, PIO0_0, PIO0_IRQ_0); 1199impl_pio!(PIO0, 0, PIO0, PIO0_0, PIO0_IRQ_0);
1077impl_pio!(PIO1, 1, PIO1, PIO1_0, PIO1_IRQ_0); 1200impl_pio!(PIO1, 1, PIO1, PIO1_0, PIO1_IRQ_0);
1078 1201
1202/// PIO pin.
1079pub trait PioPin: sealed::PioPin + gpio::Pin {} 1203pub trait PioPin: sealed::PioPin + gpio::Pin {}
1080 1204
1081macro_rules! impl_pio_pin { 1205macro_rules! impl_pio_pin {
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 516b8254b..784a05f92 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -61,9 +61,13 @@ impl Default for Config {
61 } 61 }
62} 62}
63 63
64/// PWM input mode.
64pub enum InputMode { 65pub enum InputMode {
66 /// Level mode.
65 Level, 67 Level,
68 /// Rising edge mode.
66 RisingEdge, 69 RisingEdge,
70 /// Falling edge mode.
67 FallingEdge, 71 FallingEdge,
68} 72}
69 73
@@ -77,6 +81,7 @@ impl From<InputMode> for Divmode {
77 } 81 }
78} 82}
79 83
84/// PWM driver.
80pub struct Pwm<'d, T: Channel> { 85pub struct Pwm<'d, T: Channel> {
81 inner: PeripheralRef<'d, T>, 86 inner: PeripheralRef<'d, T>,
82 pin_a: Option<PeripheralRef<'d, AnyPin>>, 87 pin_a: Option<PeripheralRef<'d, AnyPin>>,
@@ -114,11 +119,13 @@ impl<'d, T: Channel> Pwm<'d, T> {
114 } 119 }
115 } 120 }
116 121
122 /// Create PWM driver without any configured pins.
117 #[inline] 123 #[inline]
118 pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self { 124 pub fn new_free(inner: impl Peripheral<P = T> + 'd, config: Config) -> Self {
119 Self::new_inner(inner, None, None, config, Divmode::DIV) 125 Self::new_inner(inner, None, None, config, Divmode::DIV)
120 } 126 }
121 127
128 /// Create PWM driver with a single 'a' as output.
122 #[inline] 129 #[inline]
123 pub fn new_output_a( 130 pub fn new_output_a(
124 inner: impl Peripheral<P = T> + 'd, 131 inner: impl Peripheral<P = T> + 'd,
@@ -129,6 +136,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
129 Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV) 136 Self::new_inner(inner, Some(a.map_into()), None, config, Divmode::DIV)
130 } 137 }
131 138
139 /// Create PWM driver with a single 'b' pin as output.
132 #[inline] 140 #[inline]
133 pub fn new_output_b( 141 pub fn new_output_b(
134 inner: impl Peripheral<P = T> + 'd, 142 inner: impl Peripheral<P = T> + 'd,
@@ -139,6 +147,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
139 Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV) 147 Self::new_inner(inner, None, Some(b.map_into()), config, Divmode::DIV)
140 } 148 }
141 149
150 /// Create PWM driver with a 'a' and 'b' pins as output.
142 #[inline] 151 #[inline]
143 pub fn new_output_ab( 152 pub fn new_output_ab(
144 inner: impl Peripheral<P = T> + 'd, 153 inner: impl Peripheral<P = T> + 'd,
@@ -150,6 +159,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
150 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV) 159 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, Divmode::DIV)
151 } 160 }
152 161
162 /// Create PWM driver with a single 'b' as input pin.
153 #[inline] 163 #[inline]
154 pub fn new_input( 164 pub fn new_input(
155 inner: impl Peripheral<P = T> + 'd, 165 inner: impl Peripheral<P = T> + 'd,
@@ -161,6 +171,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
161 Self::new_inner(inner, None, Some(b.map_into()), config, mode.into()) 171 Self::new_inner(inner, None, Some(b.map_into()), config, mode.into())
162 } 172 }
163 173
174 /// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
164 #[inline] 175 #[inline]
165 pub fn new_output_input( 176 pub fn new_output_input(
166 inner: impl Peripheral<P = T> + 'd, 177 inner: impl Peripheral<P = T> + 'd,
@@ -173,6 +184,7 @@ impl<'d, T: Channel> Pwm<'d, T> {
173 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into()) 184 Self::new_inner(inner, Some(a.map_into()), Some(b.map_into()), config, mode.into())
174 } 185 }
175 186
187 /// Set the PWM config.
176 pub fn set_config(&mut self, config: &Config) { 188 pub fn set_config(&mut self, config: &Config) {
177 Self::configure(self.inner.regs(), config); 189 Self::configure(self.inner.regs(), config);
178 } 190 }
@@ -216,28 +228,33 @@ impl<'d, T: Channel> Pwm<'d, T> {
216 while p.csr().read().ph_ret() {} 228 while p.csr().read().ph_ret() {}
217 } 229 }
218 230
231 /// Read PWM counter.
219 #[inline] 232 #[inline]
220 pub fn counter(&self) -> u16 { 233 pub fn counter(&self) -> u16 {
221 self.inner.regs().ctr().read().ctr() 234 self.inner.regs().ctr().read().ctr()
222 } 235 }
223 236
237 /// Write PWM counter.
224 #[inline] 238 #[inline]
225 pub fn set_counter(&self, ctr: u16) { 239 pub fn set_counter(&self, ctr: u16) {
226 self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) 240 self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
227 } 241 }
228 242
243 /// Wait for channel interrupt.
229 #[inline] 244 #[inline]
230 pub fn wait_for_wrap(&mut self) { 245 pub fn wait_for_wrap(&mut self) {
231 while !self.wrapped() {} 246 while !self.wrapped() {}
232 self.clear_wrapped(); 247 self.clear_wrapped();
233 } 248 }
234 249
250 /// Check if interrupt for channel is set.
235 #[inline] 251 #[inline]
236 pub fn wrapped(&mut self) -> bool { 252 pub fn wrapped(&mut self) -> bool {
237 pac::PWM.intr().read().0 & self.bit() != 0 253 pac::PWM.intr().read().0 & self.bit() != 0
238 } 254 }
239 255
240 #[inline] 256 #[inline]
257 /// Clear interrupt flag.
241 pub fn clear_wrapped(&mut self) { 258 pub fn clear_wrapped(&mut self) {
242 pac::PWM.intr().write_value(Intr(self.bit() as _)); 259 pac::PWM.intr().write_value(Intr(self.bit() as _));
243 } 260 }
@@ -248,15 +265,18 @@ impl<'d, T: Channel> Pwm<'d, T> {
248 } 265 }
249} 266}
250 267
268/// Batch representation of PWM channels.
251pub struct PwmBatch(u32); 269pub struct PwmBatch(u32);
252 270
253impl PwmBatch { 271impl PwmBatch {
254 #[inline] 272 #[inline]
273 /// Enable a PWM channel in this batch.
255 pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) { 274 pub fn enable(&mut self, pwm: &Pwm<'_, impl Channel>) {
256 self.0 |= pwm.bit(); 275 self.0 |= pwm.bit();
257 } 276 }
258 277
259 #[inline] 278 #[inline]
279 /// Enable channels in this batch in a PWM.
260 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { 280 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
261 let mut en = PwmBatch(0); 281 let mut en = PwmBatch(0);
262 batch(&mut en); 282 batch(&mut en);
@@ -284,9 +304,12 @@ mod sealed {
284 pub trait Channel {} 304 pub trait Channel {}
285} 305}
286 306
307/// PWM Channel.
287pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static { 308pub trait Channel: Peripheral<P = Self> + sealed::Channel + Sized + 'static {
309 /// Channel number.
288 fn number(&self) -> u8; 310 fn number(&self) -> u8;
289 311
312 /// Channel register block.
290 fn regs(&self) -> pac::pwm::Channel { 313 fn regs(&self) -> pac::pwm::Channel {
291 pac::PWM.ch(self.number() as _) 314 pac::PWM.ch(self.number() as _)
292 } 315 }
@@ -312,7 +335,9 @@ channel!(PWM_CH5, 5);
312channel!(PWM_CH6, 6); 335channel!(PWM_CH6, 6);
313channel!(PWM_CH7, 7); 336channel!(PWM_CH7, 7);
314 337
338/// PWM Pin A.
315pub trait PwmPinA<T: Channel>: GpioPin {} 339pub trait PwmPinA<T: Channel>: GpioPin {}
340/// PWM Pin B.
316pub trait PwmPinB<T: Channel>: GpioPin {} 341pub trait PwmPinB<T: Channel>: GpioPin {}
317 342
318macro_rules! impl_pin { 343macro_rules! impl_pin {
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs
index 60ca8627b..b696989f5 100644
--- a/embassy-rp/src/rtc/mod.rs
+++ b/embassy-rp/src/rtc/mod.rs
@@ -1,3 +1,4 @@
1//! RTC driver.
1mod filter; 2mod filter;
2 3
3use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 4use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
@@ -194,6 +195,7 @@ mod sealed {
194 } 195 }
195} 196}
196 197
198/// RTC peripheral instance.
197pub trait Instance: sealed::Instance {} 199pub trait Instance: sealed::Instance {}
198 200
199impl sealed::Instance for crate::peripherals::RTC { 201impl sealed::Instance for crate::peripherals::RTC {
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 6ba985a65..a2a22ffe5 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -11,6 +11,7 @@ use crate::gpio::sealed::Pin as _;
11use crate::gpio::{AnyPin, Pin as GpioPin}; 11use crate::gpio::{AnyPin, Pin as GpioPin};
12use crate::{pac, peripherals, Peripheral}; 12use crate::{pac, peripherals, Peripheral};
13 13
14/// SPI errors.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))] 16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16#[non_exhaustive] 17#[non_exhaustive]
@@ -18,11 +19,15 @@ pub enum Error {
18 // No errors for now 19 // No errors for now
19} 20}
20 21
22/// SPI configuration.
21#[non_exhaustive] 23#[non_exhaustive]
22#[derive(Clone)] 24#[derive(Clone)]
23pub struct Config { 25pub struct Config {
26 /// Frequency.
24 pub frequency: u32, 27 pub frequency: u32,
28 /// Phase.
25 pub phase: Phase, 29 pub phase: Phase,
30 /// Polarity.
26 pub polarity: Polarity, 31 pub polarity: Polarity,
27} 32}
28 33
@@ -36,6 +41,7 @@ impl Default for Config {
36 } 41 }
37} 42}
38 43
44/// SPI driver.
39pub struct Spi<'d, T: Instance, M: Mode> { 45pub struct Spi<'d, T: Instance, M: Mode> {
40 inner: PeripheralRef<'d, T>, 46 inner: PeripheralRef<'d, T>,
41 tx_dma: Option<PeripheralRef<'d, AnyChannel>>, 47 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
@@ -119,6 +125,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
119 } 125 }
120 } 126 }
121 127
128 /// Write data to SPI blocking execution until done.
122 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { 129 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
123 let p = self.inner.regs(); 130 let p = self.inner.regs();
124 for &b in data { 131 for &b in data {
@@ -131,6 +138,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
131 Ok(()) 138 Ok(())
132 } 139 }
133 140
141 /// Transfer data in place to SPI blocking execution until done.
134 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { 142 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
135 let p = self.inner.regs(); 143 let p = self.inner.regs();
136 for b in data { 144 for b in data {
@@ -143,6 +151,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
143 Ok(()) 151 Ok(())
144 } 152 }
145 153
154 /// Read data from SPI blocking execution until done.
146 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { 155 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
147 let p = self.inner.regs(); 156 let p = self.inner.regs();
148 for b in data { 157 for b in data {
@@ -155,6 +164,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
155 Ok(()) 164 Ok(())
156 } 165 }
157 166
167 /// Transfer data to SPI blocking execution until done.
158 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { 168 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
159 let p = self.inner.regs(); 169 let p = self.inner.regs();
160 let len = read.len().max(write.len()); 170 let len = read.len().max(write.len());
@@ -172,12 +182,14 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
172 Ok(()) 182 Ok(())
173 } 183 }
174 184
185 /// Block execution until SPI is done.
175 pub fn flush(&mut self) -> Result<(), Error> { 186 pub fn flush(&mut self) -> Result<(), Error> {
176 let p = self.inner.regs(); 187 let p = self.inner.regs();
177 while p.sr().read().bsy() {} 188 while p.sr().read().bsy() {}
178 Ok(()) 189 Ok(())
179 } 190 }
180 191
192 /// Set SPI frequency.
181 pub fn set_frequency(&mut self, freq: u32) { 193 pub fn set_frequency(&mut self, freq: u32) {
182 let (presc, postdiv) = calc_prescs(freq); 194 let (presc, postdiv) = calc_prescs(freq);
183 let p = self.inner.regs(); 195 let p = self.inner.regs();
@@ -196,6 +208,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
196} 208}
197 209
198impl<'d, T: Instance> Spi<'d, T, Blocking> { 210impl<'d, T: Instance> Spi<'d, T, Blocking> {
211 /// Create an SPI driver in blocking mode.
199 pub fn new_blocking( 212 pub fn new_blocking(
200 inner: impl Peripheral<P = T> + 'd, 213 inner: impl Peripheral<P = T> + 'd,
201 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 214 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -216,6 +229,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
216 ) 229 )
217 } 230 }
218 231
232 /// Create an SPI driver in blocking mode supporting writes only.
219 pub fn new_blocking_txonly( 233 pub fn new_blocking_txonly(
220 inner: impl Peripheral<P = T> + 'd, 234 inner: impl Peripheral<P = T> + 'd,
221 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 235 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -235,6 +249,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
235 ) 249 )
236 } 250 }
237 251
252 /// Create an SPI driver in blocking mode supporting reads only.
238 pub fn new_blocking_rxonly( 253 pub fn new_blocking_rxonly(
239 inner: impl Peripheral<P = T> + 'd, 254 inner: impl Peripheral<P = T> + 'd,
240 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 255 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -256,6 +271,7 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
256} 271}
257 272
258impl<'d, T: Instance> Spi<'d, T, Async> { 273impl<'d, T: Instance> Spi<'d, T, Async> {
274 /// Create an SPI driver in async mode supporting DMA operations.
259 pub fn new( 275 pub fn new(
260 inner: impl Peripheral<P = T> + 'd, 276 inner: impl Peripheral<P = T> + 'd,
261 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 277 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -278,6 +294,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
278 ) 294 )
279 } 295 }
280 296
297 /// Create an SPI driver in async mode supporting DMA write operations only.
281 pub fn new_txonly( 298 pub fn new_txonly(
282 inner: impl Peripheral<P = T> + 'd, 299 inner: impl Peripheral<P = T> + 'd,
283 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 300 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -298,6 +315,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
298 ) 315 )
299 } 316 }
300 317
318 /// Create an SPI driver in async mode supporting DMA read operations only.
301 pub fn new_rxonly( 319 pub fn new_rxonly(
302 inner: impl Peripheral<P = T> + 'd, 320 inner: impl Peripheral<P = T> + 'd,
303 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 321 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
@@ -318,6 +336,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
318 ) 336 )
319 } 337 }
320 338
339 /// Write data to SPI using DMA.
321 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 340 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
322 let tx_ch = self.tx_dma.as_mut().unwrap(); 341 let tx_ch = self.tx_dma.as_mut().unwrap();
323 let tx_transfer = unsafe { 342 let tx_transfer = unsafe {
@@ -340,6 +359,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
340 Ok(()) 359 Ok(())
341 } 360 }
342 361
362 /// Read data from SPI using DMA.
343 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 363 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
344 // Start RX first. Transfer starts when TX starts, if RX 364 // Start RX first. Transfer starts when TX starts, if RX
345 // is not started yet we might lose bytes. 365 // is not started yet we might lose bytes.
@@ -365,10 +385,12 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
365 Ok(()) 385 Ok(())
366 } 386 }
367 387
388 /// Transfer data to SPI using DMA.
368 pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { 389 pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> {
369 self.transfer_inner(rx_buffer, tx_buffer).await 390 self.transfer_inner(rx_buffer, tx_buffer).await
370 } 391 }
371 392
393 /// Transfer data in place to SPI using DMA.
372 pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { 394 pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
373 self.transfer_inner(words, words).await 395 self.transfer_inner(words, words).await
374 } 396 }
@@ -434,7 +456,10 @@ mod sealed {
434 } 456 }
435} 457}
436 458
459/// Mode.
437pub trait Mode: sealed::Mode {} 460pub trait Mode: sealed::Mode {}
461
462/// SPI instance trait.
438pub trait Instance: sealed::Instance {} 463pub trait Instance: sealed::Instance {}
439 464
440macro_rules! impl_instance { 465macro_rules! impl_instance {
@@ -454,9 +479,13 @@ macro_rules! impl_instance {
454impl_instance!(SPI0, Spi0, 16, 17); 479impl_instance!(SPI0, Spi0, 16, 17);
455impl_instance!(SPI1, Spi1, 18, 19); 480impl_instance!(SPI1, Spi1, 18, 19);
456 481
482/// CLK pin.
457pub trait ClkPin<T: Instance>: GpioPin {} 483pub trait ClkPin<T: Instance>: GpioPin {}
484/// CS pin.
458pub trait CsPin<T: Instance>: GpioPin {} 485pub trait CsPin<T: Instance>: GpioPin {}
486/// MOSI pin.
459pub trait MosiPin<T: Instance>: GpioPin {} 487pub trait MosiPin<T: Instance>: GpioPin {}
488/// MISO pin.
460pub trait MisoPin<T: Instance>: GpioPin {} 489pub trait MisoPin<T: Instance>: GpioPin {}
461 490
462macro_rules! impl_pin { 491macro_rules! impl_pin {
@@ -503,7 +532,9 @@ macro_rules! impl_mode {
503 }; 532 };
504} 533}
505 534
535/// Blocking mode.
506pub struct Blocking; 536pub struct Blocking;
537/// Async mode.
507pub struct Async; 538pub struct Async;
508 539
509impl_mode!(Blocking); 540impl_mode!(Blocking);
diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs
index faa8df037..69c0c85b1 100644
--- a/embassy-rp/src/timer.rs
+++ b/embassy-rp/src/timer.rs
@@ -1,3 +1,4 @@
1//! Timer driver.
1use core::cell::Cell; 2use core::cell::Cell;
2 3
3use atomic_polyfill::{AtomicU8, Ordering}; 4use atomic_polyfill::{AtomicU8, Ordering};
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index ca030f560..99c958129 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -1,3 +1,4 @@
1//! Buffered UART driver.
1use core::future::{poll_fn, Future}; 2use core::future::{poll_fn, Future};
2use core::slice; 3use core::slice;
3use core::task::Poll; 4use core::task::Poll;
@@ -38,15 +39,18 @@ impl State {
38 } 39 }
39} 40}
40 41
42/// Buffered UART driver.
41pub struct BufferedUart<'d, T: Instance> { 43pub struct BufferedUart<'d, T: Instance> {
42 pub(crate) rx: BufferedUartRx<'d, T>, 44 pub(crate) rx: BufferedUartRx<'d, T>,
43 pub(crate) tx: BufferedUartTx<'d, T>, 45 pub(crate) tx: BufferedUartTx<'d, T>,
44} 46}
45 47
48/// Buffered UART RX handle.
46pub struct BufferedUartRx<'d, T: Instance> { 49pub struct BufferedUartRx<'d, T: Instance> {
47 pub(crate) phantom: PhantomData<&'d mut T>, 50 pub(crate) phantom: PhantomData<&'d mut T>,
48} 51}
49 52
53/// Buffered UART TX handle.
50pub struct BufferedUartTx<'d, T: Instance> { 54pub struct BufferedUartTx<'d, T: Instance> {
51 pub(crate) phantom: PhantomData<&'d mut T>, 55 pub(crate) phantom: PhantomData<&'d mut T>,
52} 56}
@@ -84,6 +88,7 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
84} 88}
85 89
86impl<'d, T: Instance> BufferedUart<'d, T> { 90impl<'d, T: Instance> BufferedUart<'d, T> {
91 /// Create a buffered UART instance.
87 pub fn new( 92 pub fn new(
88 _uart: impl Peripheral<P = T> + 'd, 93 _uart: impl Peripheral<P = T> + 'd,
89 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 94 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -104,6 +109,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
104 } 109 }
105 } 110 }
106 111
112 /// Create a buffered UART instance with flow control.
107 pub fn new_with_rtscts( 113 pub fn new_with_rtscts(
108 _uart: impl Peripheral<P = T> + 'd, 114 _uart: impl Peripheral<P = T> + 'd,
109 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 115 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -132,32 +138,39 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
132 } 138 }
133 } 139 }
134 140
141 /// Write to UART TX buffer blocking execution until done.
135 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> { 142 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> {
136 self.tx.blocking_write(buffer) 143 self.tx.blocking_write(buffer)
137 } 144 }
138 145
146 /// Flush UART TX blocking execution until done.
139 pub fn blocking_flush(&mut self) -> Result<(), Error> { 147 pub fn blocking_flush(&mut self) -> Result<(), Error> {
140 self.tx.blocking_flush() 148 self.tx.blocking_flush()
141 } 149 }
142 150
151 /// Read from UART RX buffer blocking execution until done.
143 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 152 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
144 self.rx.blocking_read(buffer) 153 self.rx.blocking_read(buffer)
145 } 154 }
146 155
156 /// Check if UART is busy transmitting.
147 pub fn busy(&self) -> bool { 157 pub fn busy(&self) -> bool {
148 self.tx.busy() 158 self.tx.busy()
149 } 159 }
150 160
161 /// Wait until TX is empty and send break condition.
151 pub async fn send_break(&mut self, bits: u32) { 162 pub async fn send_break(&mut self, bits: u32) {
152 self.tx.send_break(bits).await 163 self.tx.send_break(bits).await
153 } 164 }
154 165
166 /// Split into separate RX and TX handles.
155 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) { 167 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
156 (self.rx, self.tx) 168 (self.rx, self.tx)
157 } 169 }
158} 170}
159 171
160impl<'d, T: Instance> BufferedUartRx<'d, T> { 172impl<'d, T: Instance> BufferedUartRx<'d, T> {
173 /// Create a new buffered UART RX.
161 pub fn new( 174 pub fn new(
162 _uart: impl Peripheral<P = T> + 'd, 175 _uart: impl Peripheral<P = T> + 'd,
163 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 176 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -173,6 +186,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
173 Self { phantom: PhantomData } 186 Self { phantom: PhantomData }
174 } 187 }
175 188
189 /// Create a new buffered UART RX with flow control.
176 pub fn new_with_rts( 190 pub fn new_with_rts(
177 _uart: impl Peripheral<P = T> + 'd, 191 _uart: impl Peripheral<P = T> + 'd,
178 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 192 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -253,6 +267,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
253 Poll::Ready(result) 267 Poll::Ready(result)
254 } 268 }
255 269
270 /// Read from UART RX buffer blocking execution until done.
256 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 271 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
257 loop { 272 loop {
258 match Self::try_read(buf) { 273 match Self::try_read(buf) {
@@ -303,6 +318,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
303} 318}
304 319
305impl<'d, T: Instance> BufferedUartTx<'d, T> { 320impl<'d, T: Instance> BufferedUartTx<'d, T> {
321 /// Create a new buffered UART TX.
306 pub fn new( 322 pub fn new(
307 _uart: impl Peripheral<P = T> + 'd, 323 _uart: impl Peripheral<P = T> + 'd,
308 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 324 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -318,6 +334,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
318 Self { phantom: PhantomData } 334 Self { phantom: PhantomData }
319 } 335 }
320 336
337 /// Create a new buffered UART TX with flow control.
321 pub fn new_with_cts( 338 pub fn new_with_cts(
322 _uart: impl Peripheral<P = T> + 'd, 339 _uart: impl Peripheral<P = T> + 'd,
323 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 340 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -373,6 +390,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
373 }) 390 })
374 } 391 }
375 392
393 /// Write to UART TX buffer blocking execution until done.
376 pub fn blocking_write(&mut self, buf: &[u8]) -> Result<usize, Error> { 394 pub fn blocking_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
377 if buf.is_empty() { 395 if buf.is_empty() {
378 return Ok(0); 396 return Ok(0);
@@ -398,6 +416,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
398 } 416 }
399 } 417 }
400 418
419 /// Flush UART TX blocking execution until done.
401 pub fn blocking_flush(&mut self) -> Result<(), Error> { 420 pub fn blocking_flush(&mut self) -> Result<(), Error> {
402 loop { 421 loop {
403 let state = T::buffered_state(); 422 let state = T::buffered_state();
@@ -407,6 +426,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
407 } 426 }
408 } 427 }
409 428
429 /// Check if UART is busy.
410 pub fn busy(&self) -> bool { 430 pub fn busy(&self) -> bool {
411 T::regs().uartfr().read().busy() 431 T::regs().uartfr().read().busy()
412 } 432 }
@@ -466,6 +486,7 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
466 } 486 }
467} 487}
468 488
489/// Interrupt handler.
469pub struct BufferedInterruptHandler<T: Instance> { 490pub struct BufferedInterruptHandler<T: Instance> {
470 _uart: PhantomData<T>, 491 _uart: PhantomData<T>,
471} 492}
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 18705b141..99fce0fc9 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -1,3 +1,4 @@
1//! UART driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -20,11 +21,16 @@ use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
20mod buffered; 21mod buffered;
21pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx}; 22pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx};
22 23
24/// Word length.
23#[derive(Clone, Copy, PartialEq, Eq, Debug)] 25#[derive(Clone, Copy, PartialEq, Eq, Debug)]
24pub enum DataBits { 26pub enum DataBits {
27 /// 5 bits.
25 DataBits5, 28 DataBits5,
29 /// 6 bits.
26 DataBits6, 30 DataBits6,
31 /// 7 bits.
27 DataBits7, 32 DataBits7,
33 /// 8 bits.
28 DataBits8, 34 DataBits8,
29} 35}
30 36
@@ -39,13 +45,18 @@ impl DataBits {
39 } 45 }
40} 46}
41 47
48/// Parity bit.
42#[derive(Clone, Copy, PartialEq, Eq, Debug)] 49#[derive(Clone, Copy, PartialEq, Eq, Debug)]
43pub enum Parity { 50pub enum Parity {
51 /// No parity.
44 ParityNone, 52 ParityNone,
53 /// Even parity.
45 ParityEven, 54 ParityEven,
55 /// Odd parity.
46 ParityOdd, 56 ParityOdd,
47} 57}
48 58
59/// Stop bits.
49#[derive(Clone, Copy, PartialEq, Eq, Debug)] 60#[derive(Clone, Copy, PartialEq, Eq, Debug)]
50pub enum StopBits { 61pub enum StopBits {
51 #[doc = "1 stop bit"] 62 #[doc = "1 stop bit"]
@@ -54,20 +65,25 @@ pub enum StopBits {
54 STOP2, 65 STOP2,
55} 66}
56 67
68/// UART config.
57#[non_exhaustive] 69#[non_exhaustive]
58#[derive(Clone, Copy, PartialEq, Eq, Debug)] 70#[derive(Clone, Copy, PartialEq, Eq, Debug)]
59pub struct Config { 71pub struct Config {
72 /// Baud rate.
60 pub baudrate: u32, 73 pub baudrate: u32,
74 /// Word length.
61 pub data_bits: DataBits, 75 pub data_bits: DataBits,
76 /// Stop bits.
62 pub stop_bits: StopBits, 77 pub stop_bits: StopBits,
78 /// Parity bit.
63 pub parity: Parity, 79 pub parity: Parity,
64 /// Invert the tx pin output 80 /// Invert the tx pin output
65 pub invert_tx: bool, 81 pub invert_tx: bool,
66 /// Invert the rx pin input 82 /// Invert the rx pin input
67 pub invert_rx: bool, 83 pub invert_rx: bool,
68 // Invert the rts pin 84 /// Invert the rts pin
69 pub invert_rts: bool, 85 pub invert_rts: bool,
70 // Invert the cts pin 86 /// Invert the cts pin
71 pub invert_cts: bool, 87 pub invert_cts: bool,
72} 88}
73 89
@@ -102,21 +118,25 @@ pub enum Error {
102 Framing, 118 Framing,
103} 119}
104 120
121/// Internal DMA state of UART RX.
105pub struct DmaState { 122pub struct DmaState {
106 rx_err_waker: AtomicWaker, 123 rx_err_waker: AtomicWaker,
107 rx_errs: AtomicU16, 124 rx_errs: AtomicU16,
108} 125}
109 126
127/// UART driver.
110pub struct Uart<'d, T: Instance, M: Mode> { 128pub struct Uart<'d, T: Instance, M: Mode> {
111 tx: UartTx<'d, T, M>, 129 tx: UartTx<'d, T, M>,
112 rx: UartRx<'d, T, M>, 130 rx: UartRx<'d, T, M>,
113} 131}
114 132
133/// UART TX driver.
115pub struct UartTx<'d, T: Instance, M: Mode> { 134pub struct UartTx<'d, T: Instance, M: Mode> {
116 tx_dma: Option<PeripheralRef<'d, AnyChannel>>, 135 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
117 phantom: PhantomData<(&'d mut T, M)>, 136 phantom: PhantomData<(&'d mut T, M)>,
118} 137}
119 138
139/// UART RX driver.
120pub struct UartRx<'d, T: Instance, M: Mode> { 140pub struct UartRx<'d, T: Instance, M: Mode> {
121 rx_dma: Option<PeripheralRef<'d, AnyChannel>>, 141 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
122 phantom: PhantomData<(&'d mut T, M)>, 142 phantom: PhantomData<(&'d mut T, M)>,
@@ -142,6 +162,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
142 } 162 }
143 } 163 }
144 164
165 /// Transmit the provided buffer blocking execution until done.
145 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 166 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
146 let r = T::regs(); 167 let r = T::regs();
147 for &b in buffer { 168 for &b in buffer {
@@ -151,12 +172,14 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
151 Ok(()) 172 Ok(())
152 } 173 }
153 174
175 /// Flush UART TX blocking execution until done.
154 pub fn blocking_flush(&mut self) -> Result<(), Error> { 176 pub fn blocking_flush(&mut self) -> Result<(), Error> {
155 let r = T::regs(); 177 let r = T::regs();
156 while !r.uartfr().read().txfe() {} 178 while !r.uartfr().read().txfe() {}
157 Ok(()) 179 Ok(())
158 } 180 }
159 181
182 /// Check if UART is busy transmitting.
160 pub fn busy(&self) -> bool { 183 pub fn busy(&self) -> bool {
161 T::regs().uartfr().read().busy() 184 T::regs().uartfr().read().busy()
162 } 185 }
@@ -191,6 +214,8 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
191} 214}
192 215
193impl<'d, T: Instance> UartTx<'d, T, Blocking> { 216impl<'d, T: Instance> UartTx<'d, T, Blocking> {
217 /// Convert this uart TX instance into a buffered uart using the provided
218 /// irq and transmit buffer.
194 pub fn into_buffered( 219 pub fn into_buffered(
195 self, 220 self,
196 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 221 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -203,6 +228,7 @@ impl<'d, T: Instance> UartTx<'d, T, Blocking> {
203} 228}
204 229
205impl<'d, T: Instance> UartTx<'d, T, Async> { 230impl<'d, T: Instance> UartTx<'d, T, Async> {
231 /// Write to UART TX from the provided buffer using DMA.
206 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 232 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
207 let ch = self.tx_dma.as_mut().unwrap(); 233 let ch = self.tx_dma.as_mut().unwrap();
208 let transfer = unsafe { 234 let transfer = unsafe {
@@ -246,6 +272,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
246 } 272 }
247 } 273 }
248 274
275 /// Read from UART RX blocking execution until done.
249 pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> { 276 pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> {
250 while buffer.len() > 0 { 277 while buffer.len() > 0 {
251 let received = self.drain_fifo(buffer)?; 278 let received = self.drain_fifo(buffer)?;
@@ -294,6 +321,7 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
294} 321}
295 322
296impl<'d, T: Instance> UartRx<'d, T, Blocking> { 323impl<'d, T: Instance> UartRx<'d, T, Blocking> {
324 /// Create a new UART RX instance for blocking mode operations.
297 pub fn new_blocking( 325 pub fn new_blocking(
298 _uart: impl Peripheral<P = T> + 'd, 326 _uart: impl Peripheral<P = T> + 'd,
299 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 327 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -304,6 +332,8 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
304 Self::new_inner(false, None) 332 Self::new_inner(false, None)
305 } 333 }
306 334
335 /// Convert this uart RX instance into a buffered uart using the provided
336 /// irq and receive buffer.
307 pub fn into_buffered( 337 pub fn into_buffered(
308 self, 338 self,
309 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 339 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -315,6 +345,7 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
315 } 345 }
316} 346}
317 347
348/// Interrupt handler.
318pub struct InterruptHandler<T: Instance> { 349pub struct InterruptHandler<T: Instance> {
319 _uart: PhantomData<T>, 350 _uart: PhantomData<T>,
320} 351}
@@ -338,6 +369,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
338} 369}
339 370
340impl<'d, T: Instance> UartRx<'d, T, Async> { 371impl<'d, T: Instance> UartRx<'d, T, Async> {
372 /// Read from UART RX into the provided buffer.
341 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 373 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
342 // clear error flags before we drain the fifo. errors that have accumulated 374 // clear error flags before we drain the fifo. errors that have accumulated
343 // in the flags will also be present in the fifo. 375 // in the flags will also be present in the fifo.
@@ -458,6 +490,8 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
458 ) 490 )
459 } 491 }
460 492
493 /// Convert this uart instance into a buffered uart using the provided
494 /// irq, transmit and receive buffers.
461 pub fn into_buffered( 495 pub fn into_buffered(
462 self, 496 self,
463 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>, 497 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
@@ -667,22 +701,27 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
667} 701}
668 702
669impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { 703impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
704 /// Transmit the provided buffer blocking execution until done.
670 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 705 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
671 self.tx.blocking_write(buffer) 706 self.tx.blocking_write(buffer)
672 } 707 }
673 708
709 /// Flush UART TX blocking execution until done.
674 pub fn blocking_flush(&mut self) -> Result<(), Error> { 710 pub fn blocking_flush(&mut self) -> Result<(), Error> {
675 self.tx.blocking_flush() 711 self.tx.blocking_flush()
676 } 712 }
677 713
714 /// Read from UART RX blocking execution until done.
678 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 715 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
679 self.rx.blocking_read(buffer) 716 self.rx.blocking_read(buffer)
680 } 717 }
681 718
719 /// Check if UART is busy transmitting.
682 pub fn busy(&self) -> bool { 720 pub fn busy(&self) -> bool {
683 self.tx.busy() 721 self.tx.busy()
684 } 722 }
685 723
724 /// Wait until TX is empty and send break condition.
686 pub async fn send_break(&mut self, bits: u32) { 725 pub async fn send_break(&mut self, bits: u32) {
687 self.tx.send_break(bits).await 726 self.tx.send_break(bits).await
688 } 727 }
@@ -695,10 +734,12 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
695} 734}
696 735
697impl<'d, T: Instance> Uart<'d, T, Async> { 736impl<'d, T: Instance> Uart<'d, T, Async> {
737 /// Write to UART TX from the provided buffer.
698 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 738 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
699 self.tx.write(buffer).await 739 self.tx.write(buffer).await
700 } 740 }
701 741
742 /// Read from UART RX into the provided buffer.
702 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 743 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
703 self.rx.read(buffer).await 744 self.rx.read(buffer).await
704 } 745 }
@@ -820,6 +861,10 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T
820impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { 861impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> {
821 fn read(&mut self) -> nb::Result<u8, Self::Error> { 862 fn read(&mut self) -> nb::Result<u8, Self::Error> {
822 let r = T::regs(); 863 let r = T::regs();
864 if r.uartfr().read().rxfe() {
865 return Err(nb::Error::WouldBlock);
866 }
867
823 let dr = r.uartdr().read(); 868 let dr = r.uartdr().read();
824 869
825 if dr.oe() { 870 if dr.oe() {
@@ -830,10 +875,8 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M
830 Err(nb::Error::Other(Error::Parity)) 875 Err(nb::Error::Other(Error::Parity))
831 } else if dr.fe() { 876 } else if dr.fe() {
832 Err(nb::Error::Other(Error::Framing)) 877 Err(nb::Error::Other(Error::Framing))
833 } else if dr.fe() {
834 Ok(dr.data())
835 } else { 878 } else {
836 Err(nb::Error::WouldBlock) 879 Ok(dr.data())
837 } 880 }
838 } 881 }
839} 882}
@@ -887,6 +930,7 @@ mod sealed {
887 pub trait RtsPin<T: Instance> {} 930 pub trait RtsPin<T: Instance> {}
888} 931}
889 932
933/// UART mode.
890pub trait Mode: sealed::Mode {} 934pub trait Mode: sealed::Mode {}
891 935
892macro_rules! impl_mode { 936macro_rules! impl_mode {
@@ -896,12 +940,15 @@ macro_rules! impl_mode {
896 }; 940 };
897} 941}
898 942
943/// Blocking mode.
899pub struct Blocking; 944pub struct Blocking;
945/// Async mode.
900pub struct Async; 946pub struct Async;
901 947
902impl_mode!(Blocking); 948impl_mode!(Blocking);
903impl_mode!(Async); 949impl_mode!(Async);
904 950
951/// UART instance.
905pub trait Instance: sealed::Instance {} 952pub trait Instance: sealed::Instance {}
906 953
907macro_rules! impl_instance { 954macro_rules! impl_instance {
@@ -936,9 +983,13 @@ macro_rules! impl_instance {
936impl_instance!(UART0, UART0_IRQ, 20, 21); 983impl_instance!(UART0, UART0_IRQ, 20, 21);
937impl_instance!(UART1, UART1_IRQ, 22, 23); 984impl_instance!(UART1, UART1_IRQ, 22, 23);
938 985
986/// Trait for TX pins.
939pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 987pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
988/// Trait for RX pins.
940pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 989pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
990/// Trait for Clear To Send (CTS) pins.
941pub trait CtsPin<T: Instance>: sealed::CtsPin<T> + crate::gpio::Pin {} 991pub trait CtsPin<T: Instance>: sealed::CtsPin<T> + crate::gpio::Pin {}
992/// Trait for Request To Send (RTS) pins.
942pub trait RtsPin<T: Instance>: sealed::RtsPin<T> + crate::gpio::Pin {} 993pub trait RtsPin<T: Instance>: sealed::RtsPin<T> + crate::gpio::Pin {}
943 994
944macro_rules! impl_pin { 995macro_rules! impl_pin {
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index 4a74ee6f7..905661d64 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -1,3 +1,4 @@
1//! USB driver.
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::slice; 4use core::slice;
@@ -20,7 +21,9 @@ pub(crate) mod sealed {
20 } 21 }
21} 22}
22 23
24/// USB peripheral instance.
23pub trait Instance: sealed::Instance + 'static { 25pub trait Instance: sealed::Instance + 'static {
26 /// Interrupt for this peripheral.
24 type Interrupt: interrupt::typelevel::Interrupt; 27 type Interrupt: interrupt::typelevel::Interrupt;
25} 28}
26 29
@@ -96,6 +99,7 @@ impl EndpointData {
96 } 99 }
97} 100}
98 101
102/// RP2040 USB driver handle.
99pub struct Driver<'d, T: Instance> { 103pub struct Driver<'d, T: Instance> {
100 phantom: PhantomData<&'d mut T>, 104 phantom: PhantomData<&'d mut T>,
101 ep_in: [EndpointData; EP_COUNT], 105 ep_in: [EndpointData; EP_COUNT],
@@ -104,6 +108,7 @@ pub struct Driver<'d, T: Instance> {
104} 108}
105 109
106impl<'d, T: Instance> Driver<'d, T> { 110impl<'d, T: Instance> Driver<'d, T> {
111 /// Create a new USB driver.
107 pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self { 112 pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self {
108 T::Interrupt::unpend(); 113 T::Interrupt::unpend();
109 unsafe { T::Interrupt::enable() }; 114 unsafe { T::Interrupt::enable() };
@@ -240,6 +245,7 @@ impl<'d, T: Instance> Driver<'d, T> {
240 } 245 }
241} 246}
242 247
248/// USB interrupt handler.
243pub struct InterruptHandler<T: Instance> { 249pub struct InterruptHandler<T: Instance> {
244 _uart: PhantomData<T>, 250 _uart: PhantomData<T>,
245} 251}
@@ -342,6 +348,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
342 } 348 }
343} 349}
344 350
351/// Type representing the RP USB bus.
345pub struct Bus<'d, T: Instance> { 352pub struct Bus<'d, T: Instance> {
346 phantom: PhantomData<&'d mut T>, 353 phantom: PhantomData<&'d mut T>,
347 ep_out: [EndpointData; EP_COUNT], 354 ep_out: [EndpointData; EP_COUNT],
@@ -461,6 +468,7 @@ trait Dir {
461 fn waker(i: usize) -> &'static AtomicWaker; 468 fn waker(i: usize) -> &'static AtomicWaker;
462} 469}
463 470
471/// Type for In direction.
464pub enum In {} 472pub enum In {}
465impl Dir for In { 473impl Dir for In {
466 fn dir() -> Direction { 474 fn dir() -> Direction {
@@ -473,6 +481,7 @@ impl Dir for In {
473 } 481 }
474} 482}
475 483
484/// Type for Out direction.
476pub enum Out {} 485pub enum Out {}
477impl Dir for Out { 486impl Dir for Out {
478 fn dir() -> Direction { 487 fn dir() -> Direction {
@@ -485,6 +494,7 @@ impl Dir for Out {
485 } 494 }
486} 495}
487 496
497/// Endpoint for RP USB driver.
488pub struct Endpoint<'d, T: Instance, D> { 498pub struct Endpoint<'d, T: Instance, D> {
489 _phantom: PhantomData<(&'d mut T, D)>, 499 _phantom: PhantomData<(&'d mut T, D)>,
490 info: EndpointInfo, 500 info: EndpointInfo,
@@ -616,6 +626,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
616 } 626 }
617} 627}
618 628
629/// Control pipe for RP USB driver.
619pub struct ControlPipe<'d, T: Instance> { 630pub struct ControlPipe<'d, T: Instance> {
620 _phantom: PhantomData<&'d mut T>, 631 _phantom: PhantomData<&'d mut T>,
621 max_packet_size: u16, 632 max_packet_size: u16,
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index f887b8171..1780688cd 100644
--- a/embassy-stm32-wpan/Cargo.toml
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -26,7 +26,7 @@ aligned = "0.4.1"
26 26
27bit_field = "0.10.2" 27bit_field = "0.10.2"
28stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } 28stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
29stm32wb-hci = { version = "0.1.4", optional = true } 29stm32wb-hci = { git = "https://github.com/Dirbaio/stm32wb-hci", rev = "0aff47e009c30c5fc5d520672625173d75f7505c", optional = true }
30futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 30futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
31bitflags = { version = "2.3.3", optional = true } 31bitflags = { version = "2.3.3", optional = true }
32 32
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 4a7a2f2c9..83db7c4bf 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -56,9 +56,8 @@ cortex-m = "0.7.6"
56futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 56futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
57rand_core = "0.6.3" 57rand_core = "0.6.3"
58sdio-host = "0.5.0" 58sdio-host = "0.5.0"
59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
60critical-section = "1.1" 59critical-section = "1.1"
61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-91cee0d1fdcb4e447b65a09756b506f4af91b7e2" } 60stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c" }
62vcell = "0.1.3" 61vcell = "0.1.3"
63bxcan = "0.7.0" 62bxcan = "0.7.0"
64nb = "1.0.0" 63nb = "1.0.0"
@@ -76,7 +75,7 @@ critical-section = { version = "1.1", features = ["std"] }
76[build-dependencies] 75[build-dependencies]
77proc-macro2 = "1.0.36" 76proc-macro2 = "1.0.36"
78quote = "1.0.15" 77quote = "1.0.15"
79stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-91cee0d1fdcb4e447b65a09756b506f4af91b7e2", default-features = false, features = ["metadata"]} 78stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c", default-features = false, features = ["metadata"]}
80 79
81 80
82[features] 81[features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index bb60d244f..058b8a0fc 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -672,14 +672,14 @@ fn main() {
672 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), 672 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
673 (("lpuart", "CK"), quote!(crate::usart::CkPin)), 673 (("lpuart", "CK"), quote!(crate::usart::CkPin)),
674 (("lpuart", "DE"), quote!(crate::usart::DePin)), 674 (("lpuart", "DE"), quote!(crate::usart::DePin)),
675 (("sai", "SCK_A"), quote!(crate::sai::SckAPin)), 675 (("sai", "SCK_A"), quote!(crate::sai::SckPin<A>)),
676 (("sai", "SCK_B"), quote!(crate::sai::SckBPin)), 676 (("sai", "SCK_B"), quote!(crate::sai::SckPin<B>)),
677 (("sai", "FS_A"), quote!(crate::sai::FsAPin)), 677 (("sai", "FS_A"), quote!(crate::sai::FsPin<A>)),
678 (("sai", "FS_B"), quote!(crate::sai::FsBPin)), 678 (("sai", "FS_B"), quote!(crate::sai::FsPin<B>)),
679 (("sai", "SD_A"), quote!(crate::sai::SdAPin)), 679 (("sai", "SD_A"), quote!(crate::sai::SdPin<A>)),
680 (("sai", "SD_B"), quote!(crate::sai::SdBPin)), 680 (("sai", "SD_B"), quote!(crate::sai::SdPin<B>)),
681 (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)), 681 (("sai", "MCLK_A"), quote!(crate::sai::MclkPin<A>)),
682 (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)), 682 (("sai", "MCLK_B"), quote!(crate::sai::MclkPin<B>)),
683 (("sai", "WS"), quote!(crate::sai::WsPin)), 683 (("sai", "WS"), quote!(crate::sai::WsPin)),
684 (("spi", "SCK"), quote!(crate::spi::SckPin)), 684 (("spi", "SCK"), quote!(crate::spi::SckPin)),
685 (("spi", "MOSI"), quote!(crate::spi::MosiPin)), 685 (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
@@ -995,8 +995,8 @@ fn main() {
995 (("usart", "TX"), quote!(crate::usart::TxDma)), 995 (("usart", "TX"), quote!(crate::usart::TxDma)),
996 (("lpuart", "RX"), quote!(crate::usart::RxDma)), 996 (("lpuart", "RX"), quote!(crate::usart::RxDma)),
997 (("lpuart", "TX"), quote!(crate::usart::TxDma)), 997 (("lpuart", "TX"), quote!(crate::usart::TxDma)),
998 (("sai", "A"), quote!(crate::sai::DmaA)), 998 (("sai", "A"), quote!(crate::sai::Dma<A>)),
999 (("sai", "B"), quote!(crate::sai::DmaB)), 999 (("sai", "B"), quote!(crate::sai::Dma<B>)),
1000 (("spi", "RX"), quote!(crate::spi::RxDma)), 1000 (("spi", "RX"), quote!(crate::spi::RxDma)),
1001 (("spi", "TX"), quote!(crate::spi::TxDma)), 1001 (("spi", "TX"), quote!(crate::spi::TxDma)),
1002 (("i2c", "RX"), quote!(crate::i2c::RxDma)), 1002 (("i2c", "RX"), quote!(crate::i2c::RxDma)),
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index dbe53c807..e4dd35c34 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -1,4 +1,7 @@
1//! Analog to Digital Converter (ADC)
2
1#![macro_use] 3#![macro_use]
4#![allow(missing_docs)] // TODO
2 5
3#[cfg(not(adc_f3_v2))] 6#[cfg(not(adc_f3_v2))]
4#[cfg_attr(adc_f1, path = "f1.rs")] 7#[cfg_attr(adc_f1, path = "f1.rs")]
@@ -24,6 +27,7 @@ pub use sample_time::SampleTime;
24 27
25use crate::peripherals; 28use crate::peripherals;
26 29
30/// Analog to Digital driver.
27pub struct Adc<'d, T: Instance> { 31pub struct Adc<'d, T: Instance> {
28 #[allow(unused)] 32 #[allow(unused)]
29 adc: crate::PeripheralRef<'d, T>, 33 adc: crate::PeripheralRef<'d, T>,
@@ -75,12 +79,16 @@ pub(crate) mod sealed {
75 } 79 }
76} 80}
77 81
82/// ADC instance.
78#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))] 83#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
79pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 84pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
85/// ADC instance.
80#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] 86#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
81pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 87pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
82 88
89/// ADC pin.
83pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 90pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
91/// ADC internal channel.
84pub trait InternalChannel<T>: sealed::InternalChannel<T> {} 92pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
85 93
86foreach_adc!( 94foreach_adc!(
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs
index 383980b5a..64c25a776 100644
--- a/embassy-stm32/src/adc/resolution.rs
+++ b/embassy-stm32/src/adc/resolution.rs
@@ -1,3 +1,5 @@
1/// ADC resolution
2#[allow(missing_docs)]
1#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] 3#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
2#[derive(Clone, Copy, Debug, Eq, PartialEq)] 4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
3#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -8,6 +10,8 @@ pub enum Resolution {
8 SixBit, 10 SixBit,
9} 11}
10 12
13/// ADC resolution
14#[allow(missing_docs)]
11#[cfg(adc_v4)] 15#[cfg(adc_v4)]
12#[derive(Clone, Copy, Debug, Eq, PartialEq)] 16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))] 17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -49,6 +53,9 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
49} 53}
50 54
51impl Resolution { 55impl Resolution {
56 /// Get the maximum reading value for this resolution.
57 ///
58 /// This is `2**n - 1`.
52 pub fn to_max_count(&self) -> u32 { 59 pub fn to_max_count(&self) -> u32 {
53 match self { 60 match self {
54 #[cfg(adc_v4)] 61 #[cfg(adc_v4)]
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index d74617cb3..048e73184 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -32,6 +32,7 @@ const TEMP_CHANNEL: u8 = 18;
32const VBAT_CHANNEL: u8 = 17; 32const VBAT_CHANNEL: u8 = 17;
33 33
34// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs 34// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
35/// Internal voltage reference channel.
35pub struct VrefInt; 36pub struct VrefInt;
36impl<T: Instance> InternalChannel<T> for VrefInt {} 37impl<T: Instance> InternalChannel<T> for VrefInt {}
37impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { 38impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
@@ -40,6 +41,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
40 } 41 }
41} 42}
42 43
44/// Internal temperature channel.
43pub struct Temperature; 45pub struct Temperature;
44impl<T: Instance> InternalChannel<T> for Temperature {} 46impl<T: Instance> InternalChannel<T> for Temperature {}
45impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { 47impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
@@ -48,6 +50,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
48 } 50 }
49} 51}
50 52
53/// Internal battery voltage channel.
51pub struct Vbat; 54pub struct Vbat;
52impl<T: Instance> InternalChannel<T> for Vbat {} 55impl<T: Instance> InternalChannel<T> for Vbat {}
53impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { 56impl<T: Instance> super::sealed::InternalChannel<T> for Vbat {
@@ -125,6 +128,7 @@ impl Prescaler {
125} 128}
126 129
127impl<'d, T: Instance> Adc<'d, T> { 130impl<'d, T: Instance> Adc<'d, T> {
131 /// Create a new ADC driver.
128 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { 132 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
129 embassy_hal_internal::into_ref!(adc); 133 embassy_hal_internal::into_ref!(adc);
130 T::enable_and_reset(); 134 T::enable_and_reset();
@@ -212,6 +216,7 @@ impl<'d, T: Instance> Adc<'d, T> {
212 }); 216 });
213 } 217 }
214 218
219 /// Enable reading the voltage reference internal channel.
215 pub fn enable_vrefint(&self) -> VrefInt { 220 pub fn enable_vrefint(&self) -> VrefInt {
216 T::common_regs().ccr().modify(|reg| { 221 T::common_regs().ccr().modify(|reg| {
217 reg.set_vrefen(true); 222 reg.set_vrefen(true);
@@ -220,6 +225,7 @@ impl<'d, T: Instance> Adc<'d, T> {
220 VrefInt {} 225 VrefInt {}
221 } 226 }
222 227
228 /// Enable reading the temperature internal channel.
223 pub fn enable_temperature(&self) -> Temperature { 229 pub fn enable_temperature(&self) -> Temperature {
224 T::common_regs().ccr().modify(|reg| { 230 T::common_regs().ccr().modify(|reg| {
225 reg.set_vsenseen(true); 231 reg.set_vsenseen(true);
@@ -228,6 +234,7 @@ impl<'d, T: Instance> Adc<'d, T> {
228 Temperature {} 234 Temperature {}
229 } 235 }
230 236
237 /// Enable reading the vbat internal channel.
231 pub fn enable_vbat(&self) -> Vbat { 238 pub fn enable_vbat(&self) -> Vbat {
232 T::common_regs().ccr().modify(|reg| { 239 T::common_regs().ccr().modify(|reg| {
233 reg.set_vbaten(true); 240 reg.set_vbaten(true);
@@ -236,10 +243,12 @@ impl<'d, T: Instance> Adc<'d, T> {
236 Vbat {} 243 Vbat {}
237 } 244 }
238 245
246 /// Set the ADC sample time.
239 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 247 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
240 self.sample_time = sample_time; 248 self.sample_time = sample_time;
241 } 249 }
242 250
251 /// Set the ADC resolution.
243 pub fn set_resolution(&mut self, resolution: Resolution) { 252 pub fn set_resolution(&mut self, resolution: Resolution) {
244 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 253 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
245 } 254 }
@@ -263,6 +272,7 @@ impl<'d, T: Instance> Adc<'d, T> {
263 T::regs().dr().read().0 as u16 272 T::regs().dr().read().0 as u16
264 } 273 }
265 274
275 /// Read an ADC pin.
266 pub fn read<P>(&mut self, pin: &mut P) -> u16 276 pub fn read<P>(&mut self, pin: &mut P) -> u16
267 where 277 where
268 P: AdcPin<T>, 278 P: AdcPin<T>,
@@ -273,6 +283,7 @@ impl<'d, T: Instance> Adc<'d, T> {
273 self.read_channel(pin.channel()) 283 self.read_channel(pin.channel())
274 } 284 }
275 285
286 /// Read an ADC internal channel.
276 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { 287 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
277 self.read_channel(channel.channel()) 288 self.read_channel(channel.channel())
278 } 289 }
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 2f7417340..3c663b452 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -21,8 +21,10 @@ use crate::{interrupt, peripherals, Peripheral};
21#[derive(Debug, Clone, PartialEq, Eq)] 21#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))] 22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub struct Envelope { 23pub struct Envelope {
24 /// Reception time.
24 #[cfg(feature = "time")] 25 #[cfg(feature = "time")]
25 pub ts: embassy_time::Instant, 26 pub ts: embassy_time::Instant,
27 /// The actual CAN frame.
26 pub frame: bxcan::Frame, 28 pub frame: bxcan::Frame,
27} 29}
28 30
@@ -43,6 +45,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::TXInterrupt> for TxInterruptH
43 } 45 }
44} 46}
45 47
48/// RX0 interrupt handler.
46pub struct Rx0InterruptHandler<T: Instance> { 49pub struct Rx0InterruptHandler<T: Instance> {
47 _phantom: PhantomData<T>, 50 _phantom: PhantomData<T>,
48} 51}
@@ -54,6 +57,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0Interrup
54 } 57 }
55} 58}
56 59
60/// RX1 interrupt handler.
57pub struct Rx1InterruptHandler<T: Instance> { 61pub struct Rx1InterruptHandler<T: Instance> {
58 _phantom: PhantomData<T>, 62 _phantom: PhantomData<T>,
59} 63}
@@ -65,6 +69,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1Interrup
65 } 69 }
66} 70}
67 71
72/// SCE interrupt handler.
68pub struct SceInterruptHandler<T: Instance> { 73pub struct SceInterruptHandler<T: Instance> {
69 _phantom: PhantomData<T>, 74 _phantom: PhantomData<T>,
70} 75}
@@ -82,10 +87,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
82 } 87 }
83} 88}
84 89
90/// CAN driver
85pub struct Can<'d, T: Instance> { 91pub struct Can<'d, T: Instance> {
86 pub can: bxcan::Can<BxcanInstance<'d, T>>, 92 can: bxcan::Can<BxcanInstance<'d, T>>,
87} 93}
88 94
95/// CAN bus error
96#[allow(missing_docs)]
89#[derive(Debug)] 97#[derive(Debug)]
90#[cfg_attr(feature = "defmt", derive(defmt::Format))] 98#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91pub enum BusError { 99pub enum BusError {
@@ -101,6 +109,7 @@ pub enum BusError {
101 BusWarning, 109 BusWarning,
102} 110}
103 111
112/// Error returned by `try_read`
104#[derive(Debug)] 113#[derive(Debug)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))] 114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub enum TryReadError { 115pub enum TryReadError {
@@ -110,6 +119,7 @@ pub enum TryReadError {
110 Empty, 119 Empty,
111} 120}
112 121
122/// Error returned by `try_write`
113#[derive(Debug)] 123#[derive(Debug)]
114#[cfg_attr(feature = "defmt", derive(defmt::Format))] 124#[cfg_attr(feature = "defmt", derive(defmt::Format))]
115pub enum TryWriteError { 125pub enum TryWriteError {
@@ -177,6 +187,7 @@ impl<'d, T: Instance> Can<'d, T> {
177 Self { can } 187 Self { can }
178 } 188 }
179 189
190 /// Set CAN bit rate.
180 pub fn set_bitrate(&mut self, bitrate: u32) { 191 pub fn set_bitrate(&mut self, bitrate: u32) {
181 let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); 192 let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap();
182 self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); 193 self.can.modify_config().set_bit_timing(bit_timing).leave_disabled();
@@ -194,7 +205,9 @@ impl<'d, T: Instance> Can<'d, T> {
194 } 205 }
195 } 206 }
196 207
197 /// Queues the message to be sent but exerts backpressure 208 /// Queues the message to be sent.
209 ///
210 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
198 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { 211 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
199 self.split().0.write(frame).await 212 self.split().0.write(frame).await
200 } 213 }
@@ -221,12 +234,16 @@ impl<'d, T: Instance> Can<'d, T> {
221 CanTx::<T>::flush_all_inner().await 234 CanTx::<T>::flush_all_inner().await
222 } 235 }
223 236
237 /// Read a CAN frame.
238 ///
239 /// If no CAN frame is in the RX buffer, this will wait until there is one.
240 ///
224 /// Returns a tuple of the time the message was received and the message frame 241 /// Returns a tuple of the time the message was received and the message frame
225 pub async fn read(&mut self) -> Result<Envelope, BusError> { 242 pub async fn read(&mut self) -> Result<Envelope, BusError> {
226 self.split().1.read().await 243 self.split().1.read().await
227 } 244 }
228 245
229 /// Attempts to read a can frame without blocking. 246 /// Attempts to read a CAN frame without blocking.
230 /// 247 ///
231 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 248 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
232 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 249 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
@@ -288,7 +305,7 @@ impl<'d, T: Instance> Can<'d, T> {
288 } 305 }
289 } 306 }
290 307
291 pub const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> { 308 const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> {
292 const BS1_MAX: u8 = 16; 309 const BS1_MAX: u8 = 16;
293 const BS2_MAX: u8 = 8; 310 const BS2_MAX: u8 = 8;
294 const MAX_SAMPLE_POINT_PERMILL: u16 = 900; 311 const MAX_SAMPLE_POINT_PERMILL: u16 = 900;
@@ -379,21 +396,29 @@ impl<'d, T: Instance> Can<'d, T> {
379 Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1)) 396 Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1))
380 } 397 }
381 398
399 /// Split the CAN driver into transmit and receive halves.
400 ///
401 /// Useful for doing separate transmit/receive tasks.
382 pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { 402 pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) {
383 let (tx, rx0, rx1) = self.can.split_by_ref(); 403 let (tx, rx0, rx1) = self.can.split_by_ref();
384 (CanTx { tx }, CanRx { rx0, rx1 }) 404 (CanTx { tx }, CanRx { rx0, rx1 })
385 } 405 }
386 406
407 /// Get mutable access to the lower-level driver from the `bxcan` crate.
387 pub fn as_mut(&mut self) -> &mut bxcan::Can<BxcanInstance<'d, T>> { 408 pub fn as_mut(&mut self) -> &mut bxcan::Can<BxcanInstance<'d, T>> {
388 &mut self.can 409 &mut self.can
389 } 410 }
390} 411}
391 412
413/// CAN driver, transmit half.
392pub struct CanTx<'c, 'd, T: Instance> { 414pub struct CanTx<'c, 'd, T: Instance> {
393 tx: &'c mut bxcan::Tx<BxcanInstance<'d, T>>, 415 tx: &'c mut bxcan::Tx<BxcanInstance<'d, T>>,
394} 416}
395 417
396impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { 418impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
419 /// Queues the message to be sent.
420 ///
421 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
397 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { 422 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
398 poll_fn(|cx| { 423 poll_fn(|cx| {
399 T::state().tx_waker.register(cx.waker()); 424 T::state().tx_waker.register(cx.waker());
@@ -475,6 +500,7 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
475 } 500 }
476} 501}
477 502
503/// CAN driver, receive half.
478#[allow(dead_code)] 504#[allow(dead_code)]
479pub struct CanRx<'c, 'd, T: Instance> { 505pub struct CanRx<'c, 'd, T: Instance> {
480 rx0: &'c mut bxcan::Rx0<BxcanInstance<'d, T>>, 506 rx0: &'c mut bxcan::Rx0<BxcanInstance<'d, T>>,
@@ -482,6 +508,11 @@ pub struct CanRx<'c, 'd, T: Instance> {
482} 508}
483 509
484impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { 510impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
511 /// Read a CAN frame.
512 ///
513 /// If no CAN frame is in the RX buffer, this will wait until there is one.
514 ///
515 /// Returns a tuple of the time the message was received and the message frame
485 pub async fn read(&mut self) -> Result<Envelope, BusError> { 516 pub async fn read(&mut self) -> Result<Envelope, BusError> {
486 poll_fn(|cx| { 517 poll_fn(|cx| {
487 T::state().err_waker.register(cx.waker()); 518 T::state().err_waker.register(cx.waker());
@@ -585,30 +616,24 @@ pub(crate) mod sealed {
585 pub trait Instance { 616 pub trait Instance {
586 const REGISTERS: *mut bxcan::RegisterBlock; 617 const REGISTERS: *mut bxcan::RegisterBlock;
587 618
588 fn regs() -> &'static crate::pac::can::Can; 619 fn regs() -> crate::pac::can::Can;
589 fn state() -> &'static State; 620 fn state() -> &'static State;
590 } 621 }
591} 622}
592 623
593pub trait TXInstance { 624/// CAN instance trait.
625pub trait Instance: sealed::Instance + RccPeripheral + 'static {
626 /// TX interrupt for this instance.
594 type TXInterrupt: crate::interrupt::typelevel::Interrupt; 627 type TXInterrupt: crate::interrupt::typelevel::Interrupt;
595} 628 /// RX0 interrupt for this instance.
596
597pub trait RX0Instance {
598 type RX0Interrupt: crate::interrupt::typelevel::Interrupt; 629 type RX0Interrupt: crate::interrupt::typelevel::Interrupt;
599} 630 /// RX1 interrupt for this instance.
600
601pub trait RX1Instance {
602 type RX1Interrupt: crate::interrupt::typelevel::Interrupt; 631 type RX1Interrupt: crate::interrupt::typelevel::Interrupt;
603} 632 /// SCE interrupt for this instance.
604
605pub trait SCEInstance {
606 type SCEInterrupt: crate::interrupt::typelevel::Interrupt; 633 type SCEInterrupt: crate::interrupt::typelevel::Interrupt;
607} 634}
608 635
609pub trait InterruptableInstance: TXInstance + RX0Instance + RX1Instance + SCEInstance {} 636/// BXCAN instance newtype.
610pub trait Instance: sealed::Instance + RccPeripheral + InterruptableInstance + 'static {}
611
612pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>); 637pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>);
613 638
614unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { 639unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> {
@@ -620,8 +645,8 @@ foreach_peripheral!(
620 impl sealed::Instance for peripherals::$inst { 645 impl sealed::Instance for peripherals::$inst {
621 const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; 646 const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
622 647
623 fn regs() -> &'static crate::pac::can::Can { 648 fn regs() -> crate::pac::can::Can {
624 &crate::pac::$inst 649 crate::pac::$inst
625 } 650 }
626 651
627 fn state() -> &'static sealed::State { 652 fn state() -> &'static sealed::State {
@@ -630,32 +655,12 @@ foreach_peripheral!(
630 } 655 }
631 } 656 }
632 657
633 impl Instance for peripherals::$inst {} 658 impl Instance for peripherals::$inst {
634 659 type TXInterrupt = crate::_generated::peripheral_interrupts::$inst::TX;
635 foreach_interrupt!( 660 type RX0Interrupt = crate::_generated::peripheral_interrupts::$inst::RX0;
636 ($inst,can,CAN,TX,$irq:ident) => { 661 type RX1Interrupt = crate::_generated::peripheral_interrupts::$inst::RX1;
637 impl TXInstance for peripherals::$inst { 662 type SCEInterrupt = crate::_generated::peripheral_interrupts::$inst::SCE;
638 type TXInterrupt = crate::interrupt::typelevel::$irq; 663 }
639 }
640 };
641 ($inst,can,CAN,RX0,$irq:ident) => {
642 impl RX0Instance for peripherals::$inst {
643 type RX0Interrupt = crate::interrupt::typelevel::$irq;
644 }
645 };
646 ($inst,can,CAN,RX1,$irq:ident) => {
647 impl RX1Instance for peripherals::$inst {
648 type RX1Interrupt = crate::interrupt::typelevel::$irq;
649 }
650 };
651 ($inst,can,CAN,SCE,$irq:ident) => {
652 impl SCEInstance for peripherals::$inst {
653 type SCEInterrupt = crate::interrupt::typelevel::$irq;
654 }
655 };
656 );
657
658 impl InterruptableInstance for peripherals::$inst {}
659 }; 664 };
660); 665);
661 666
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index f77788db3..0cc2559cf 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -1,6 +1,3 @@
1pub use bxcan;
2use embassy_hal_internal::PeripheralRef;
3
4use crate::peripherals; 1use crate::peripherals;
5 2
6pub(crate) mod sealed { 3pub(crate) mod sealed {
@@ -25,27 +22,19 @@ pub(crate) mod sealed {
25 } 22 }
26 23
27 pub trait Instance { 24 pub trait Instance {
28 const REGISTERS: *mut bxcan::RegisterBlock;
29
30 fn regs() -> &'static crate::pac::can::Fdcan; 25 fn regs() -> &'static crate::pac::can::Fdcan;
31 fn state() -> &'static State; 26 fn state() -> &'static State;
32 } 27 }
33} 28}
34 29
30/// Interruptable FDCAN instance.
35pub trait InterruptableInstance {} 31pub trait InterruptableInstance {}
32/// FDCAN instance.
36pub trait Instance: sealed::Instance + InterruptableInstance + 'static {} 33pub trait Instance: sealed::Instance + InterruptableInstance + 'static {}
37 34
38pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>);
39
40unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> {
41 const REGISTERS: *mut bxcan::RegisterBlock = T::REGISTERS;
42}
43
44foreach_peripheral!( 35foreach_peripheral!(
45 (can, $inst:ident) => { 36 (can, $inst:ident) => {
46 impl sealed::Instance for peripherals::$inst { 37 impl sealed::Instance for peripherals::$inst {
47 const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
48
49 fn regs() -> &'static crate::pac::can::Fdcan { 38 fn regs() -> &'static crate::pac::can::Fdcan {
50 &crate::pac::$inst 39 &crate::pac::$inst
51 } 40 }
diff --git a/embassy-stm32/src/can/mod.rs b/embassy-stm32/src/can/mod.rs
index 425f9ac2e..915edb3a6 100644
--- a/embassy-stm32/src/can/mod.rs
+++ b/embassy-stm32/src/can/mod.rs
@@ -1,3 +1,4 @@
1//! Controller Area Network (CAN)
1#![macro_use] 2#![macro_use]
2 3
3#[cfg_attr(can_bxcan, path = "bxcan.rs")] 4#[cfg_attr(can_bxcan, path = "bxcan.rs")]
diff --git a/embassy-stm32/src/crc/mod.rs b/embassy-stm32/src/crc/mod.rs
index 63f7ad9ba..29523b92d 100644
--- a/embassy-stm32/src/crc/mod.rs
+++ b/embassy-stm32/src/crc/mod.rs
@@ -1,3 +1,4 @@
1//! Cyclic Redundancy Check (CRC)
1#[cfg_attr(crc_v1, path = "v1.rs")] 2#[cfg_attr(crc_v1, path = "v1.rs")]
2#[cfg_attr(crc_v2, path = "v2v3.rs")] 3#[cfg_attr(crc_v2, path = "v2v3.rs")]
3#[cfg_attr(crc_v3, path = "v2v3.rs")] 4#[cfg_attr(crc_v3, path = "v2v3.rs")]
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index c0f580830..0166ab819 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -5,6 +5,7 @@ use crate::peripherals::CRC;
5use crate::rcc::sealed::RccPeripheral; 5use crate::rcc::sealed::RccPeripheral;
6use crate::Peripheral; 6use crate::Peripheral;
7 7
8/// CRC driver.
8pub struct Crc<'d> { 9pub struct Crc<'d> {
9 _peri: PeripheralRef<'d, CRC>, 10 _peri: PeripheralRef<'d, CRC>,
10} 11}
@@ -34,6 +35,7 @@ impl<'d> Crc<'d> {
34 PAC_CRC.dr().write_value(word); 35 PAC_CRC.dr().write_value(word);
35 self.read() 36 self.read()
36 } 37 }
38
37 /// Feed a slice of words to the peripheral and return the result. 39 /// Feed a slice of words to the peripheral and return the result.
38 pub fn feed_words(&mut self, words: &[u32]) -> u32 { 40 pub fn feed_words(&mut self, words: &[u32]) -> u32 {
39 for word in words { 41 for word in words {
@@ -42,6 +44,8 @@ impl<'d> Crc<'d> {
42 44
43 self.read() 45 self.read()
44 } 46 }
47
48 /// Read the CRC result value.
45 pub fn read(&self) -> u32 { 49 pub fn read(&self) -> u32 {
46 PAC_CRC.dr().read() 50 PAC_CRC.dr().read()
47 } 51 }
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index b36f6018c..0c4ae55ce 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -6,15 +6,19 @@ use crate::peripherals::CRC;
6use crate::rcc::sealed::RccPeripheral; 6use crate::rcc::sealed::RccPeripheral;
7use crate::Peripheral; 7use crate::Peripheral;
8 8
9/// CRC driver.
9pub struct Crc<'d> { 10pub struct Crc<'d> {
10 _peripheral: PeripheralRef<'d, CRC>, 11 _peripheral: PeripheralRef<'d, CRC>,
11 _config: Config, 12 _config: Config,
12} 13}
13 14
15/// CRC configuration errlr
14pub enum ConfigError { 16pub enum ConfigError {
17 /// The selected polynomial is invalid.
15 InvalidPolynomial, 18 InvalidPolynomial,
16} 19}
17 20
21/// CRC configuration
18pub struct Config { 22pub struct Config {
19 reverse_in: InputReverseConfig, 23 reverse_in: InputReverseConfig,
20 reverse_out: bool, 24 reverse_out: bool,
@@ -25,14 +29,20 @@ pub struct Config {
25 crc_poly: u32, 29 crc_poly: u32,
26} 30}
27 31
32/// Input reverse configuration.
28pub enum InputReverseConfig { 33pub enum InputReverseConfig {
34 /// Don't reverse anything
29 None, 35 None,
36 /// Reverse bytes
30 Byte, 37 Byte,
38 /// Reverse 16-bit halfwords.
31 Halfword, 39 Halfword,
40 /// Reverse 32-bit words.
32 Word, 41 Word,
33} 42}
34 43
35impl Config { 44impl Config {
45 /// Create a new CRC config.
36 pub fn new( 46 pub fn new(
37 reverse_in: InputReverseConfig, 47 reverse_in: InputReverseConfig,
38 reverse_out: bool, 48 reverse_out: bool,
@@ -57,7 +67,9 @@ impl Config {
57 } 67 }
58} 68}
59 69
70/// Polynomial size
60#[cfg(crc_v3)] 71#[cfg(crc_v3)]
72#[allow(missing_docs)]
61pub enum PolySize { 73pub enum PolySize {
62 Width7, 74 Width7,
63 Width8, 75 Width8,
@@ -81,6 +93,7 @@ impl<'d> Crc<'d> {
81 instance 93 instance
82 } 94 }
83 95
96 /// Reset the CRC engine.
84 pub fn reset(&mut self) { 97 pub fn reset(&mut self) {
85 PAC_CRC.cr().modify(|w| w.set_reset(true)); 98 PAC_CRC.cr().modify(|w| w.set_reset(true));
86 } 99 }
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 500eac4c1..31dedf06e 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -1,4 +1,4 @@
1//! Provide access to the STM32 digital-to-analog converter (DAC). 1//! Digital to Analog Converter (DAC)
2#![macro_use] 2#![macro_use]
3 3
4use core::marker::PhantomData; 4use core::marker::PhantomData;
@@ -62,11 +62,11 @@ impl Mode {
62/// 62///
63/// 12-bit values outside the permitted range are silently truncated. 63/// 12-bit values outside the permitted range are silently truncated.
64pub enum Value { 64pub enum Value {
65 // 8 bit value 65 /// 8 bit value
66 Bit8(u8), 66 Bit8(u8),
67 // 12 bit value stored in a u16, left-aligned 67 /// 12 bit value stored in a u16, left-aligned
68 Bit12Left(u16), 68 Bit12Left(u16),
69 // 12 bit value stored in a u16, right-aligned 69 /// 12 bit value stored in a u16, right-aligned
70 Bit12Right(u16), 70 Bit12Right(u16),
71} 71}
72 72
@@ -76,11 +76,11 @@ pub enum Value {
76/// 76///
77/// 12-bit values outside the permitted range are silently truncated. 77/// 12-bit values outside the permitted range are silently truncated.
78pub enum DualValue { 78pub enum DualValue {
79 // 8 bit value 79 /// 8 bit value
80 Bit8(u8, u8), 80 Bit8(u8, u8),
81 // 12 bit value stored in a u16, left-aligned 81 /// 12 bit value stored in a u16, left-aligned
82 Bit12Left(u16, u16), 82 Bit12Left(u16, u16),
83 // 12 bit value stored in a u16, right-aligned 83 /// 12 bit value stored in a u16, right-aligned
84 Bit12Right(u16, u16), 84 Bit12Right(u16, u16),
85} 85}
86 86
@@ -88,11 +88,11 @@ pub enum DualValue {
88#[cfg_attr(feature = "defmt", derive(defmt::Format))] 88#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89/// Array variant of [`Value`]. 89/// Array variant of [`Value`].
90pub enum ValueArray<'a> { 90pub enum ValueArray<'a> {
91 // 8 bit values 91 /// 8 bit values
92 Bit8(&'a [u8]), 92 Bit8(&'a [u8]),
93 // 12 bit value stored in a u16, left-aligned 93 /// 12 bit value stored in a u16, left-aligned
94 Bit12Left(&'a [u16]), 94 Bit12Left(&'a [u16]),
95 // 12 bit values stored in a u16, right-aligned 95 /// 12 bit values stored in a u16, right-aligned
96 Bit12Right(&'a [u16]), 96 Bit12Right(&'a [u16]),
97} 97}
98 98
@@ -106,7 +106,9 @@ pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> {
106 dma: PeripheralRef<'d, DMA>, 106 dma: PeripheralRef<'d, DMA>,
107} 107}
108 108
109/// DAC channel 1 type alias.
109pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; 110pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>;
111/// DAC channel 2 type alias.
110pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; 112pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>;
111 113
112impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { 114impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
@@ -492,6 +494,7 @@ pub(crate) mod sealed {
492 } 494 }
493} 495}
494 496
497/// DAC instance.
495pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 498pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
496dma_trait!(DacDma1, Instance); 499dma_trait!(DacDma1, Instance);
497dma_trait!(DacDma2, Instance); 500dma_trait!(DacDma2, Instance);
diff --git a/embassy-stm32/src/dac/tsel.rs b/embassy-stm32/src/dac/tsel.rs
index f38dd8fd7..22d8d3dfa 100644
--- a/embassy-stm32/src/dac/tsel.rs
+++ b/embassy-stm32/src/dac/tsel.rs
@@ -1,3 +1,5 @@
1#![allow(missing_docs)]
2
1/// Trigger selection for STM32F0. 3/// Trigger selection for STM32F0.
2#[cfg(stm32f0)] 4#[cfg(stm32f0)]
3#[derive(Debug, Copy, Clone, Eq, PartialEq)] 5#[derive(Debug, Copy, Clone, Eq, PartialEq)]
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index b12230794..4d02284b2 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -1,3 +1,4 @@
1//! Digital Camera Interface (DCMI)
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
@@ -36,6 +37,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
36} 37}
37 38
38/// The level on the VSync pin when the data is not valid on the parallel interface. 39/// The level on the VSync pin when the data is not valid on the parallel interface.
40#[allow(missing_docs)]
39#[derive(Clone, Copy, PartialEq)] 41#[derive(Clone, Copy, PartialEq)]
40pub enum VSyncDataInvalidLevel { 42pub enum VSyncDataInvalidLevel {
41 Low, 43 Low,
@@ -43,6 +45,7 @@ pub enum VSyncDataInvalidLevel {
43} 45}
44 46
45/// The level on the VSync pin when the data is not valid on the parallel interface. 47/// The level on the VSync pin when the data is not valid on the parallel interface.
48#[allow(missing_docs)]
46#[derive(Clone, Copy, PartialEq)] 49#[derive(Clone, Copy, PartialEq)]
47pub enum HSyncDataInvalidLevel { 50pub enum HSyncDataInvalidLevel {
48 Low, 51 Low,
@@ -50,14 +53,16 @@ pub enum HSyncDataInvalidLevel {
50} 53}
51 54
52#[derive(Clone, Copy, PartialEq)] 55#[derive(Clone, Copy, PartialEq)]
56#[allow(missing_docs)]
53pub enum PixelClockPolarity { 57pub enum PixelClockPolarity {
54 RisingEdge, 58 RisingEdge,
55 FallingEdge, 59 FallingEdge,
56} 60}
57 61
58pub struct State { 62struct State {
59 waker: AtomicWaker, 63 waker: AtomicWaker,
60} 64}
65
61impl State { 66impl State {
62 const fn new() -> State { 67 const fn new() -> State {
63 State { 68 State {
@@ -68,18 +73,25 @@ impl State {
68 73
69static STATE: State = State::new(); 74static STATE: State = State::new();
70 75
76/// DCMI error.
71#[derive(Debug, Eq, PartialEq, Copy, Clone)] 77#[derive(Debug, Eq, PartialEq, Copy, Clone)]
72#[cfg_attr(feature = "defmt", derive(defmt::Format))] 78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
73#[non_exhaustive] 79#[non_exhaustive]
74pub enum Error { 80pub enum Error {
81 /// Overrun error: the hardware generated data faster than we could read it.
75 Overrun, 82 Overrun,
83 /// Internal peripheral error.
76 PeripheralError, 84 PeripheralError,
77} 85}
78 86
87/// DCMI configuration.
79#[non_exhaustive] 88#[non_exhaustive]
80pub struct Config { 89pub struct Config {
90 /// VSYNC level.
81 pub vsync_level: VSyncDataInvalidLevel, 91 pub vsync_level: VSyncDataInvalidLevel,
92 /// HSYNC level.
82 pub hsync_level: HSyncDataInvalidLevel, 93 pub hsync_level: HSyncDataInvalidLevel,
94 /// PIXCLK polarity.
83 pub pixclk_polarity: PixelClockPolarity, 95 pub pixclk_polarity: PixelClockPolarity,
84} 96}
85 97
@@ -105,6 +117,7 @@ macro_rules! config_pins {
105 }; 117 };
106} 118}
107 119
120/// DCMI driver.
108pub struct Dcmi<'d, T: Instance, Dma: FrameDma<T>> { 121pub struct Dcmi<'d, T: Instance, Dma: FrameDma<T>> {
109 inner: PeripheralRef<'d, T>, 122 inner: PeripheralRef<'d, T>,
110 dma: PeripheralRef<'d, Dma>, 123 dma: PeripheralRef<'d, Dma>,
@@ -115,6 +128,7 @@ where
115 T: Instance, 128 T: Instance,
116 Dma: FrameDma<T>, 129 Dma: FrameDma<T>,
117{ 130{
131 /// Create a new DCMI driver with 8 data bits.
118 pub fn new_8bit( 132 pub fn new_8bit(
119 peri: impl Peripheral<P = T> + 'd, 133 peri: impl Peripheral<P = T> + 'd,
120 dma: impl Peripheral<P = Dma> + 'd, 134 dma: impl Peripheral<P = Dma> + 'd,
@@ -139,6 +153,7 @@ where
139 Self::new_inner(peri, dma, config, false, 0b00) 153 Self::new_inner(peri, dma, config, false, 0b00)
140 } 154 }
141 155
156 /// Create a new DCMI driver with 10 data bits.
142 pub fn new_10bit( 157 pub fn new_10bit(
143 peri: impl Peripheral<P = T> + 'd, 158 peri: impl Peripheral<P = T> + 'd,
144 dma: impl Peripheral<P = Dma> + 'd, 159 dma: impl Peripheral<P = Dma> + 'd,
@@ -165,6 +180,7 @@ where
165 Self::new_inner(peri, dma, config, false, 0b01) 180 Self::new_inner(peri, dma, config, false, 0b01)
166 } 181 }
167 182
183 /// Create a new DCMI driver with 12 data bits.
168 pub fn new_12bit( 184 pub fn new_12bit(
169 peri: impl Peripheral<P = T> + 'd, 185 peri: impl Peripheral<P = T> + 'd,
170 dma: impl Peripheral<P = Dma> + 'd, 186 dma: impl Peripheral<P = Dma> + 'd,
@@ -193,6 +209,7 @@ where
193 Self::new_inner(peri, dma, config, false, 0b10) 209 Self::new_inner(peri, dma, config, false, 0b10)
194 } 210 }
195 211
212 /// Create a new DCMI driver with 14 data bits.
196 pub fn new_14bit( 213 pub fn new_14bit(
197 peri: impl Peripheral<P = T> + 'd, 214 peri: impl Peripheral<P = T> + 'd,
198 dma: impl Peripheral<P = Dma> + 'd, 215 dma: impl Peripheral<P = Dma> + 'd,
@@ -223,6 +240,7 @@ where
223 Self::new_inner(peri, dma, config, false, 0b11) 240 Self::new_inner(peri, dma, config, false, 0b11)
224 } 241 }
225 242
243 /// Create a new DCMI driver with 8 data bits, with embedded synchronization.
226 pub fn new_es_8bit( 244 pub fn new_es_8bit(
227 peri: impl Peripheral<P = T> + 'd, 245 peri: impl Peripheral<P = T> + 'd,
228 dma: impl Peripheral<P = Dma> + 'd, 246 dma: impl Peripheral<P = Dma> + 'd,
@@ -245,6 +263,7 @@ where
245 Self::new_inner(peri, dma, config, true, 0b00) 263 Self::new_inner(peri, dma, config, true, 0b00)
246 } 264 }
247 265
266 /// Create a new DCMI driver with 10 data bits, with embedded synchronization.
248 pub fn new_es_10bit( 267 pub fn new_es_10bit(
249 peri: impl Peripheral<P = T> + 'd, 268 peri: impl Peripheral<P = T> + 'd,
250 dma: impl Peripheral<P = Dma> + 'd, 269 dma: impl Peripheral<P = Dma> + 'd,
@@ -269,6 +288,7 @@ where
269 Self::new_inner(peri, dma, config, true, 0b01) 288 Self::new_inner(peri, dma, config, true, 0b01)
270 } 289 }
271 290
291 /// Create a new DCMI driver with 12 data bits, with embedded synchronization.
272 pub fn new_es_12bit( 292 pub fn new_es_12bit(
273 peri: impl Peripheral<P = T> + 'd, 293 peri: impl Peripheral<P = T> + 'd,
274 dma: impl Peripheral<P = Dma> + 'd, 294 dma: impl Peripheral<P = Dma> + 'd,
@@ -295,6 +315,7 @@ where
295 Self::new_inner(peri, dma, config, true, 0b10) 315 Self::new_inner(peri, dma, config, true, 0b10)
296 } 316 }
297 317
318 /// Create a new DCMI driver with 14 data bits, with embedded synchronization.
298 pub fn new_es_14bit( 319 pub fn new_es_14bit(
299 peri: impl Peripheral<P = T> + 'd, 320 peri: impl Peripheral<P = T> + 'd,
300 dma: impl Peripheral<P = Dma> + 'd, 321 dma: impl Peripheral<P = Dma> + 'd,
@@ -538,7 +559,9 @@ mod sealed {
538 } 559 }
539} 560}
540 561
562/// DCMI instance.
541pub trait Instance: sealed::Instance + 'static { 563pub trait Instance: sealed::Instance + 'static {
564 /// Interrupt for this instance.
542 type Interrupt: interrupt::typelevel::Interrupt; 565 type Interrupt: interrupt::typelevel::Interrupt;
543} 566}
544 567
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index a7422f66b..a2b83716d 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -1,4 +1,4 @@
1#![macro_use] 1//! Basic Direct Memory Acccess (BDMA)
2 2
3use core::future::Future; 3use core::future::Future;
4use core::pin::Pin; 4use core::pin::Pin;
@@ -17,11 +17,16 @@ use crate::interrupt::Priority;
17use crate::pac; 17use crate::pac;
18use crate::pac::bdma::{regs, vals}; 18use crate::pac::bdma::{regs, vals};
19 19
20/// BDMA transfer options.
20#[derive(Debug, Copy, Clone, PartialEq, Eq)] 21#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))] 22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22#[non_exhaustive] 23#[non_exhaustive]
23pub struct TransferOptions { 24pub struct TransferOptions {
24 /// Enable circular DMA 25 /// Enable circular DMA
26 ///
27 /// Note:
28 /// If you enable circular mode manually, you may want to build and `.await` the `Transfer` in a separate task.
29 /// Since DMA in circular mode need manually stop, `.await` in current task would block the task forever.
25 pub circular: bool, 30 pub circular: bool,
26 /// Enable half transfer interrupt 31 /// Enable half transfer interrupt
27 pub half_transfer_ir: bool, 32 pub half_transfer_ir: bool,
@@ -140,13 +145,17 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
140 STATE.ch_wakers[index].wake(); 145 STATE.ch_wakers[index].wake();
141} 146}
142 147
148/// DMA request type alias.
143#[cfg(any(bdma_v2, dmamux))] 149#[cfg(any(bdma_v2, dmamux))]
144pub type Request = u8; 150pub type Request = u8;
151/// DMA request type alias.
145#[cfg(not(any(bdma_v2, dmamux)))] 152#[cfg(not(any(bdma_v2, dmamux)))]
146pub type Request = (); 153pub type Request = ();
147 154
155/// DMA channel.
148#[cfg(dmamux)] 156#[cfg(dmamux)]
149pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} 157pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
158/// DMA channel.
150#[cfg(not(dmamux))] 159#[cfg(not(dmamux))]
151pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} 160pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
152 161
@@ -161,12 +170,14 @@ pub(crate) mod sealed {
161 } 170 }
162} 171}
163 172
173/// DMA transfer.
164#[must_use = "futures do nothing unless you `.await` or poll them"] 174#[must_use = "futures do nothing unless you `.await` or poll them"]
165pub struct Transfer<'a, C: Channel> { 175pub struct Transfer<'a, C: Channel> {
166 channel: PeripheralRef<'a, C>, 176 channel: PeripheralRef<'a, C>,
167} 177}
168 178
169impl<'a, C: Channel> Transfer<'a, C> { 179impl<'a, C: Channel> Transfer<'a, C> {
180 /// Create a new read DMA transfer (peripheral to memory).
170 pub unsafe fn new_read<W: Word>( 181 pub unsafe fn new_read<W: Word>(
171 channel: impl Peripheral<P = C> + 'a, 182 channel: impl Peripheral<P = C> + 'a,
172 request: Request, 183 request: Request,
@@ -177,6 +188,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
177 Self::new_read_raw(channel, request, peri_addr, buf, options) 188 Self::new_read_raw(channel, request, peri_addr, buf, options)
178 } 189 }
179 190
191 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
180 pub unsafe fn new_read_raw<W: Word>( 192 pub unsafe fn new_read_raw<W: Word>(
181 channel: impl Peripheral<P = C> + 'a, 193 channel: impl Peripheral<P = C> + 'a,
182 request: Request, 194 request: Request,
@@ -202,6 +214,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
202 ) 214 )
203 } 215 }
204 216
217 /// Create a new write DMA transfer (memory to peripheral).
205 pub unsafe fn new_write<W: Word>( 218 pub unsafe fn new_write<W: Word>(
206 channel: impl Peripheral<P = C> + 'a, 219 channel: impl Peripheral<P = C> + 'a,
207 request: Request, 220 request: Request,
@@ -212,6 +225,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
212 Self::new_write_raw(channel, request, buf, peri_addr, options) 225 Self::new_write_raw(channel, request, buf, peri_addr, options)
213 } 226 }
214 227
228 /// Create a new write DMA transfer (memory to peripheral), using raw pointers.
215 pub unsafe fn new_write_raw<W: Word>( 229 pub unsafe fn new_write_raw<W: Word>(
216 channel: impl Peripheral<P = C> + 'a, 230 channel: impl Peripheral<P = C> + 'a,
217 request: Request, 231 request: Request,
@@ -237,6 +251,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
237 ) 251 )
238 } 252 }
239 253
254 /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
240 pub unsafe fn new_write_repeated<W: Word>( 255 pub unsafe fn new_write_repeated<W: Word>(
241 channel: impl Peripheral<P = C> + 'a, 256 channel: impl Peripheral<P = C> + 'a,
242 request: Request, 257 request: Request,
@@ -292,20 +307,14 @@ impl<'a, C: Channel> Transfer<'a, C> {
292 ch.cr().write(|w| { 307 ch.cr().write(|w| {
293 w.set_psize(data_size.into()); 308 w.set_psize(data_size.into());
294 w.set_msize(data_size.into()); 309 w.set_msize(data_size.into());
295 if incr_mem { 310 w.set_minc(incr_mem);
296 w.set_minc(vals::Inc::ENABLED);
297 } else {
298 w.set_minc(vals::Inc::DISABLED);
299 }
300 w.set_dir(dir.into()); 311 w.set_dir(dir.into());
301 w.set_teie(true); 312 w.set_teie(true);
302 w.set_tcie(options.complete_transfer_ir); 313 w.set_tcie(options.complete_transfer_ir);
303 w.set_htie(options.half_transfer_ir); 314 w.set_htie(options.half_transfer_ir);
315 w.set_circ(options.circular);
304 if options.circular { 316 if options.circular {
305 w.set_circ(vals::Circ::ENABLED);
306 debug!("Setting circular mode"); 317 debug!("Setting circular mode");
307 } else {
308 w.set_circ(vals::Circ::DISABLED);
309 } 318 }
310 w.set_pl(vals::Pl::VERYHIGH); 319 w.set_pl(vals::Pl::VERYHIGH);
311 w.set_en(true); 320 w.set_en(true);
@@ -321,6 +330,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
321 }); 330 });
322 } 331 }
323 332
333 /// Request the transfer to stop.
334 ///
335 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
324 pub fn request_stop(&mut self) { 336 pub fn request_stop(&mut self) {
325 let ch = self.channel.regs().ch(self.channel.num()); 337 let ch = self.channel.regs().ch(self.channel.num());
326 338
@@ -331,21 +343,27 @@ impl<'a, C: Channel> Transfer<'a, C> {
331 }); 343 });
332 } 344 }
333 345
346 /// Return whether this transfer is still running.
347 ///
348 /// If this returns `false`, it can be because either the transfer finished, or
349 /// it was requested to stop early with [`request_stop`](Self::request_stop).
334 pub fn is_running(&mut self) -> bool { 350 pub fn is_running(&mut self) -> bool {
335 let ch = self.channel.regs().ch(self.channel.num()); 351 let ch = self.channel.regs().ch(self.channel.num());
336 let en = ch.cr().read().en(); 352 let en = ch.cr().read().en();
337 let circular = ch.cr().read().circ() == vals::Circ::ENABLED; 353 let circular = ch.cr().read().circ();
338 let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0; 354 let tcif = STATE.complete_count[self.channel.index()].load(Ordering::Acquire) != 0;
339 en && (circular || !tcif) 355 en && (circular || !tcif)
340 } 356 }
341 357
342 /// Gets the total remaining transfers for the channel 358 /// Get the total remaining transfers for the channel.
343 /// Note: this will be zero for transfers that completed without cancellation. 359 ///
360 /// This will be zero for transfers that completed instead of being canceled with [`request_stop`](Self::request_stop).
344 pub fn get_remaining_transfers(&self) -> u16 { 361 pub fn get_remaining_transfers(&self) -> u16 {
345 let ch = self.channel.regs().ch(self.channel.num()); 362 let ch = self.channel.regs().ch(self.channel.num());
346 ch.ndtr().read().ndt() 363 ch.ndtr().read().ndt()
347 } 364 }
348 365
366 /// Blocking wait until the transfer finishes.
349 pub fn blocking_wait(mut self) { 367 pub fn blocking_wait(mut self) {
350 while self.is_running() {} 368 while self.is_running() {}
351 self.request_stop(); 369 self.request_stop();
@@ -411,6 +429,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
411 } 429 }
412} 430}
413 431
432/// Ringbuffer for reading data using DMA circular mode.
414pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { 433pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
415 cr: regs::Cr, 434 cr: regs::Cr,
416 channel: PeripheralRef<'a, C>, 435 channel: PeripheralRef<'a, C>,
@@ -418,7 +437,8 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
418} 437}
419 438
420impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { 439impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
421 pub unsafe fn new_read( 440 /// Create a new ring buffer.
441 pub unsafe fn new(
422 channel: impl Peripheral<P = C> + 'a, 442 channel: impl Peripheral<P = C> + 'a,
423 _request: Request, 443 _request: Request,
424 peri_addr: *mut W, 444 peri_addr: *mut W,
@@ -445,12 +465,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
445 let mut w = regs::Cr(0); 465 let mut w = regs::Cr(0);
446 w.set_psize(data_size.into()); 466 w.set_psize(data_size.into());
447 w.set_msize(data_size.into()); 467 w.set_msize(data_size.into());
448 w.set_minc(vals::Inc::ENABLED); 468 w.set_minc(true);
449 w.set_dir(dir.into()); 469 w.set_dir(dir.into());
450 w.set_teie(true); 470 w.set_teie(true);
451 w.set_htie(true); 471 w.set_htie(true);
452 w.set_tcie(true); 472 w.set_tcie(true);
453 w.set_circ(vals::Circ::ENABLED); 473 w.set_circ(true);
454 w.set_pl(vals::Pl::VERYHIGH); 474 w.set_pl(vals::Pl::VERYHIGH);
455 w.set_en(true); 475 w.set_en(true);
456 476
@@ -473,11 +493,15 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
473 this 493 this
474 } 494 }
475 495
496 /// Start the ring buffer operation.
497 ///
498 /// You must call this after creating it for it to work.
476 pub fn start(&mut self) { 499 pub fn start(&mut self) {
477 let ch = self.channel.regs().ch(self.channel.num()); 500 let ch = self.channel.regs().ch(self.channel.num());
478 ch.cr().write_value(self.cr) 501 ch.cr().write_value(self.cr)
479 } 502 }
480 503
504 /// Clear all data in the ring buffer.
481 pub fn clear(&mut self) { 505 pub fn clear(&mut self) {
482 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 506 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
483 } 507 }
@@ -509,10 +533,11 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
509 } 533 }
510 534
511 /// The capacity of the ringbuffer. 535 /// The capacity of the ringbuffer.
512 pub const fn cap(&self) -> usize { 536 pub const fn capacity(&self) -> usize {
513 self.ringbuf.cap() 537 self.ringbuf.cap()
514 } 538 }
515 539
540 /// Set a waker to be woken when at least one byte is received.
516 pub fn set_waker(&mut self, waker: &Waker) { 541 pub fn set_waker(&mut self, waker: &Waker) {
517 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); 542 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
518 } 543 }
@@ -526,6 +551,9 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
526 }); 551 });
527 } 552 }
528 553
554 /// Request DMA to stop.
555 ///
556 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
529 pub fn request_stop(&mut self) { 557 pub fn request_stop(&mut self) {
530 let ch = self.channel.regs().ch(self.channel.num()); 558 let ch = self.channel.regs().ch(self.channel.num());
531 559
@@ -539,6 +567,10 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
539 }); 567 });
540 } 568 }
541 569
570 /// Return whether DMA is still running.
571 ///
572 /// If this returns `false`, it can be because either the transfer finished, or
573 /// it was requested to stop early with [`request_stop`](Self::request_stop).
542 pub fn is_running(&mut self) -> bool { 574 pub fn is_running(&mut self) -> bool {
543 let ch = self.channel.regs().ch(self.channel.num()); 575 let ch = self.channel.regs().ch(self.channel.num());
544 ch.cr().read().en() 576 ch.cr().read().en()
@@ -555,6 +587,7 @@ impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> {
555 } 587 }
556} 588}
557 589
590/// Ringbuffer for writing data using DMA circular mode.
558pub struct WritableRingBuffer<'a, C: Channel, W: Word> { 591pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
559 cr: regs::Cr, 592 cr: regs::Cr,
560 channel: PeripheralRef<'a, C>, 593 channel: PeripheralRef<'a, C>,
@@ -562,7 +595,8 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
562} 595}
563 596
564impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { 597impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
565 pub unsafe fn new_write( 598 /// Create a new ring buffer.
599 pub unsafe fn new(
566 channel: impl Peripheral<P = C> + 'a, 600 channel: impl Peripheral<P = C> + 'a,
567 _request: Request, 601 _request: Request,
568 peri_addr: *mut W, 602 peri_addr: *mut W,
@@ -589,12 +623,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
589 let mut w = regs::Cr(0); 623 let mut w = regs::Cr(0);
590 w.set_psize(data_size.into()); 624 w.set_psize(data_size.into());
591 w.set_msize(data_size.into()); 625 w.set_msize(data_size.into());
592 w.set_minc(vals::Inc::ENABLED); 626 w.set_minc(true);
593 w.set_dir(dir.into()); 627 w.set_dir(dir.into());
594 w.set_teie(true); 628 w.set_teie(true);
595 w.set_htie(true); 629 w.set_htie(true);
596 w.set_tcie(true); 630 w.set_tcie(true);
597 w.set_circ(vals::Circ::ENABLED); 631 w.set_circ(true);
598 w.set_pl(vals::Pl::VERYHIGH); 632 w.set_pl(vals::Pl::VERYHIGH);
599 w.set_en(true); 633 w.set_en(true);
600 634
@@ -617,11 +651,15 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
617 this 651 this
618 } 652 }
619 653
654 /// Start the ring buffer operation.
655 ///
656 /// You must call this after creating it for it to work.
620 pub fn start(&mut self) { 657 pub fn start(&mut self) {
621 let ch = self.channel.regs().ch(self.channel.num()); 658 let ch = self.channel.regs().ch(self.channel.num());
622 ch.cr().write_value(self.cr) 659 ch.cr().write_value(self.cr)
623 } 660 }
624 661
662 /// Clear all data in the ring buffer.
625 pub fn clear(&mut self) { 663 pub fn clear(&mut self) {
626 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 664 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
627 } 665 }
@@ -640,10 +678,11 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
640 } 678 }
641 679
642 /// The capacity of the ringbuffer. 680 /// The capacity of the ringbuffer.
643 pub const fn cap(&self) -> usize { 681 pub const fn capacity(&self) -> usize {
644 self.ringbuf.cap() 682 self.ringbuf.cap()
645 } 683 }
646 684
685 /// Set a waker to be woken when at least one byte is sent.
647 pub fn set_waker(&mut self, waker: &Waker) { 686 pub fn set_waker(&mut self, waker: &Waker) {
648 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); 687 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
649 } 688 }
@@ -657,6 +696,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
657 }); 696 });
658 } 697 }
659 698
699 /// Request DMA to stop.
700 ///
701 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
660 pub fn request_stop(&mut self) { 702 pub fn request_stop(&mut self) {
661 let ch = self.channel.regs().ch(self.channel.num()); 703 let ch = self.channel.regs().ch(self.channel.num());
662 704
@@ -670,6 +712,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
670 }); 712 });
671 } 713 }
672 714
715 /// Return whether DMA is still running.
716 ///
717 /// If this returns `false`, it can be because either the transfer finished, or
718 /// it was requested to stop early with [`request_stop`](Self::request_stop).
673 pub fn is_running(&mut self) -> bool { 719 pub fn is_running(&mut self) -> bool {
674 let ch = self.channel.regs().ch(self.channel.num()); 720 let ch = self.channel.regs().ch(self.channel.num());
675 ch.cr().read().en() 721 ch.cr().read().en()
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index cce0407c1..16d02f273 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -16,6 +16,7 @@ use crate::interrupt::Priority;
16use crate::pac::dma::{regs, vals}; 16use crate::pac::dma::{regs, vals};
17use crate::{interrupt, pac}; 17use crate::{interrupt, pac};
18 18
19/// DMA transfer options.
19#[derive(Debug, Copy, Clone, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[non_exhaustive] 22#[non_exhaustive]
@@ -29,6 +30,10 @@ pub struct TransferOptions {
29 /// FIFO threshold for DMA FIFO mode. If none, direct mode is used. 30 /// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
30 pub fifo_threshold: Option<FifoThreshold>, 31 pub fifo_threshold: Option<FifoThreshold>,
31 /// Enable circular DMA 32 /// Enable circular DMA
33 ///
34 /// Note:
35 /// If you enable circular mode manually, you may want to build and `.await` the `Transfer` in a separate task.
36 /// Since DMA in circular mode need manually stop, `.await` in current task would block the task forever.
32 pub circular: bool, 37 pub circular: bool,
33 /// Enable half transfer interrupt 38 /// Enable half transfer interrupt
34 pub half_transfer_ir: bool, 39 pub half_transfer_ir: bool,
@@ -69,6 +74,7 @@ impl From<Dir> for vals::Dir {
69 } 74 }
70} 75}
71 76
77/// DMA transfer burst setting.
72#[derive(Debug, Copy, Clone, PartialEq, Eq)] 78#[derive(Debug, Copy, Clone, PartialEq, Eq)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))] 79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74pub enum Burst { 80pub enum Burst {
@@ -93,6 +99,7 @@ impl From<Burst> for vals::Burst {
93 } 99 }
94} 100}
95 101
102/// DMA flow control setting.
96#[derive(Debug, Copy, Clone, PartialEq, Eq)] 103#[derive(Debug, Copy, Clone, PartialEq, Eq)]
97#[cfg_attr(feature = "defmt", derive(defmt::Format))] 104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
98pub enum FlowControl { 105pub enum FlowControl {
@@ -111,6 +118,7 @@ impl From<FlowControl> for vals::Pfctrl {
111 } 118 }
112} 119}
113 120
121/// DMA FIFO threshold.
114#[derive(Debug, Copy, Clone, PartialEq, Eq)] 122#[derive(Debug, Copy, Clone, PartialEq, Eq)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))] 123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116pub enum FifoThreshold { 124pub enum FifoThreshold {
@@ -208,13 +216,17 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: usize, index:
208 STATE.ch_wakers[index].wake(); 216 STATE.ch_wakers[index].wake();
209} 217}
210 218
219/// DMA request type alias. (also known as DMA channel number in some chips)
211#[cfg(any(dma_v2, dmamux))] 220#[cfg(any(dma_v2, dmamux))]
212pub type Request = u8; 221pub type Request = u8;
222/// DMA request type alias. (also known as DMA channel number in some chips)
213#[cfg(not(any(dma_v2, dmamux)))] 223#[cfg(not(any(dma_v2, dmamux)))]
214pub type Request = (); 224pub type Request = ();
215 225
226/// DMA channel.
216#[cfg(dmamux)] 227#[cfg(dmamux)]
217pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} 228pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
229/// DMA channel.
218#[cfg(not(dmamux))] 230#[cfg(not(dmamux))]
219pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} 231pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
220 232
@@ -229,12 +241,14 @@ pub(crate) mod sealed {
229 } 241 }
230} 242}
231 243
244/// DMA transfer.
232#[must_use = "futures do nothing unless you `.await` or poll them"] 245#[must_use = "futures do nothing unless you `.await` or poll them"]
233pub struct Transfer<'a, C: Channel> { 246pub struct Transfer<'a, C: Channel> {
234 channel: PeripheralRef<'a, C>, 247 channel: PeripheralRef<'a, C>,
235} 248}
236 249
237impl<'a, C: Channel> Transfer<'a, C> { 250impl<'a, C: Channel> Transfer<'a, C> {
251 /// Create a new read DMA transfer (peripheral to memory).
238 pub unsafe fn new_read<W: Word>( 252 pub unsafe fn new_read<W: Word>(
239 channel: impl Peripheral<P = C> + 'a, 253 channel: impl Peripheral<P = C> + 'a,
240 request: Request, 254 request: Request,
@@ -245,6 +259,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
245 Self::new_read_raw(channel, request, peri_addr, buf, options) 259 Self::new_read_raw(channel, request, peri_addr, buf, options)
246 } 260 }
247 261
262 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
248 pub unsafe fn new_read_raw<W: Word>( 263 pub unsafe fn new_read_raw<W: Word>(
249 channel: impl Peripheral<P = C> + 'a, 264 channel: impl Peripheral<P = C> + 'a,
250 request: Request, 265 request: Request,
@@ -270,6 +285,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
270 ) 285 )
271 } 286 }
272 287
288 /// Create a new write DMA transfer (memory to peripheral).
273 pub unsafe fn new_write<W: Word>( 289 pub unsafe fn new_write<W: Word>(
274 channel: impl Peripheral<P = C> + 'a, 290 channel: impl Peripheral<P = C> + 'a,
275 request: Request, 291 request: Request,
@@ -280,6 +296,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
280 Self::new_write_raw(channel, request, buf, peri_addr, options) 296 Self::new_write_raw(channel, request, buf, peri_addr, options)
281 } 297 }
282 298
299 /// Create a new write DMA transfer (memory to peripheral), using raw pointers.
283 pub unsafe fn new_write_raw<W: Word>( 300 pub unsafe fn new_write_raw<W: Word>(
284 channel: impl Peripheral<P = C> + 'a, 301 channel: impl Peripheral<P = C> + 'a,
285 request: Request, 302 request: Request,
@@ -305,6 +322,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
305 ) 322 )
306 } 323 }
307 324
325 /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
308 pub unsafe fn new_write_repeated<W: Word>( 326 pub unsafe fn new_write_repeated<W: Word>(
309 channel: impl Peripheral<P = C> + 'a, 327 channel: impl Peripheral<P = C> + 'a,
310 request: Request, 328 request: Request,
@@ -368,18 +386,13 @@ impl<'a, C: Channel> Transfer<'a, C> {
368 w.set_msize(data_size.into()); 386 w.set_msize(data_size.into());
369 w.set_psize(data_size.into()); 387 w.set_psize(data_size.into());
370 w.set_pl(vals::Pl::VERYHIGH); 388 w.set_pl(vals::Pl::VERYHIGH);
371 w.set_minc(match incr_mem { 389 w.set_minc(incr_mem);
372 true => vals::Inc::INCREMENTED, 390 w.set_pinc(false);
373 false => vals::Inc::FIXED,
374 });
375 w.set_pinc(vals::Inc::FIXED);
376 w.set_teie(true); 391 w.set_teie(true);
377 w.set_tcie(options.complete_transfer_ir); 392 w.set_tcie(options.complete_transfer_ir);
393 w.set_circ(options.circular);
378 if options.circular { 394 if options.circular {
379 w.set_circ(vals::Circ::ENABLED);
380 debug!("Setting circular mode"); 395 debug!("Setting circular mode");
381 } else {
382 w.set_circ(vals::Circ::DISABLED);
383 } 396 }
384 #[cfg(dma_v1)] 397 #[cfg(dma_v1)]
385 w.set_trbuff(true); 398 w.set_trbuff(true);
@@ -407,6 +420,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
407 }); 420 });
408 } 421 }
409 422
423 /// Request the transfer to stop.
424 ///
425 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
410 pub fn request_stop(&mut self) { 426 pub fn request_stop(&mut self) {
411 let ch = self.channel.regs().st(self.channel.num()); 427 let ch = self.channel.regs().st(self.channel.num());
412 428
@@ -417,6 +433,10 @@ impl<'a, C: Channel> Transfer<'a, C> {
417 }); 433 });
418 } 434 }
419 435
436 /// Return whether this transfer is still running.
437 ///
438 /// If this returns `false`, it can be because either the transfer finished, or
439 /// it was requested to stop early with [`request_stop`](Self::request_stop).
420 pub fn is_running(&mut self) -> bool { 440 pub fn is_running(&mut self) -> bool {
421 let ch = self.channel.regs().st(self.channel.num()); 441 let ch = self.channel.regs().st(self.channel.num());
422 ch.cr().read().en() 442 ch.cr().read().en()
@@ -429,6 +449,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
429 ch.ndtr().read().ndt() 449 ch.ndtr().read().ndt()
430 } 450 }
431 451
452 /// Blocking wait until the transfer finishes.
432 pub fn blocking_wait(mut self) { 453 pub fn blocking_wait(mut self) {
433 while self.is_running() {} 454 while self.is_running() {}
434 455
@@ -465,12 +486,14 @@ impl<'a, C: Channel> Future for Transfer<'a, C> {
465 486
466// ================================== 487// ==================================
467 488
489/// Double-buffered DMA transfer.
468pub struct DoubleBuffered<'a, C: Channel, W: Word> { 490pub struct DoubleBuffered<'a, C: Channel, W: Word> {
469 channel: PeripheralRef<'a, C>, 491 channel: PeripheralRef<'a, C>,
470 _phantom: PhantomData<W>, 492 _phantom: PhantomData<W>,
471} 493}
472 494
473impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { 495impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
496 /// Create a new read DMA transfer (peripheral to memory).
474 pub unsafe fn new_read( 497 pub unsafe fn new_read(
475 channel: impl Peripheral<P = C> + 'a, 498 channel: impl Peripheral<P = C> + 'a,
476 _request: Request, 499 _request: Request,
@@ -521,8 +544,8 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
521 w.set_msize(data_size.into()); 544 w.set_msize(data_size.into());
522 w.set_psize(data_size.into()); 545 w.set_psize(data_size.into());
523 w.set_pl(vals::Pl::VERYHIGH); 546 w.set_pl(vals::Pl::VERYHIGH);
524 w.set_minc(vals::Inc::INCREMENTED); 547 w.set_minc(true);
525 w.set_pinc(vals::Inc::FIXED); 548 w.set_pinc(false);
526 w.set_teie(true); 549 w.set_teie(true);
527 w.set_tcie(true); 550 w.set_tcie(true);
528 #[cfg(dma_v1)] 551 #[cfg(dma_v1)]
@@ -554,25 +577,36 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
554 }); 577 });
555 } 578 }
556 579
580 /// Set the first buffer address.
581 ///
582 /// You may call this while DMA is transferring the other buffer.
557 pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { 583 pub unsafe fn set_buffer0(&mut self, buffer: *mut W) {
558 let ch = self.channel.regs().st(self.channel.num()); 584 let ch = self.channel.regs().st(self.channel.num());
559 ch.m0ar().write_value(buffer as _); 585 ch.m0ar().write_value(buffer as _);
560 } 586 }
561 587
588 /// Set the second buffer address.
589 ///
590 /// You may call this while DMA is transferring the other buffer.
562 pub unsafe fn set_buffer1(&mut self, buffer: *mut W) { 591 pub unsafe fn set_buffer1(&mut self, buffer: *mut W) {
563 let ch = self.channel.regs().st(self.channel.num()); 592 let ch = self.channel.regs().st(self.channel.num());
564 ch.m1ar().write_value(buffer as _); 593 ch.m1ar().write_value(buffer as _);
565 } 594 }
566 595
596 /// Returh whether buffer0 is accessible (i.e. whether DMA is transferring buffer1 now)
567 pub fn is_buffer0_accessible(&mut self) -> bool { 597 pub fn is_buffer0_accessible(&mut self) -> bool {
568 let ch = self.channel.regs().st(self.channel.num()); 598 let ch = self.channel.regs().st(self.channel.num());
569 ch.cr().read().ct() == vals::Ct::MEMORY1 599 ch.cr().read().ct() == vals::Ct::MEMORY1
570 } 600 }
571 601
602 /// Set a waker to be woken when one of the buffers is being transferred.
572 pub fn set_waker(&mut self, waker: &Waker) { 603 pub fn set_waker(&mut self, waker: &Waker) {
573 STATE.ch_wakers[self.channel.index()].register(waker); 604 STATE.ch_wakers[self.channel.index()].register(waker);
574 } 605 }
575 606
607 /// Request the transfer to stop.
608 ///
609 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
576 pub fn request_stop(&mut self) { 610 pub fn request_stop(&mut self) {
577 let ch = self.channel.regs().st(self.channel.num()); 611 let ch = self.channel.regs().st(self.channel.num());
578 612
@@ -583,6 +617,10 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> {
583 }); 617 });
584 } 618 }
585 619
620 /// Return whether this transfer is still running.
621 ///
622 /// If this returns `false`, it can be because either the transfer finished, or
623 /// it was requested to stop early with [`request_stop`](Self::request_stop).
586 pub fn is_running(&mut self) -> bool { 624 pub fn is_running(&mut self) -> bool {
587 let ch = self.channel.regs().st(self.channel.num()); 625 let ch = self.channel.regs().st(self.channel.num());
588 ch.cr().read().en() 626 ch.cr().read().en()
@@ -629,6 +667,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
629 } 667 }
630} 668}
631 669
670/// Ringbuffer for receiving data using DMA circular mode.
632pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { 671pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
633 cr: regs::Cr, 672 cr: regs::Cr,
634 channel: PeripheralRef<'a, C>, 673 channel: PeripheralRef<'a, C>,
@@ -636,7 +675,8 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
636} 675}
637 676
638impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { 677impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
639 pub unsafe fn new_read( 678 /// Create a new ring buffer.
679 pub unsafe fn new(
640 channel: impl Peripheral<P = C> + 'a, 680 channel: impl Peripheral<P = C> + 'a,
641 _request: Request, 681 _request: Request,
642 peri_addr: *mut W, 682 peri_addr: *mut W,
@@ -662,12 +702,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
662 w.set_msize(data_size.into()); 702 w.set_msize(data_size.into());
663 w.set_psize(data_size.into()); 703 w.set_psize(data_size.into());
664 w.set_pl(vals::Pl::VERYHIGH); 704 w.set_pl(vals::Pl::VERYHIGH);
665 w.set_minc(vals::Inc::INCREMENTED); 705 w.set_minc(true);
666 w.set_pinc(vals::Inc::FIXED); 706 w.set_pinc(false);
667 w.set_teie(true); 707 w.set_teie(true);
668 w.set_htie(options.half_transfer_ir); 708 w.set_htie(options.half_transfer_ir);
669 w.set_tcie(true); 709 w.set_tcie(true);
670 w.set_circ(vals::Circ::ENABLED); 710 w.set_circ(true);
671 #[cfg(dma_v1)] 711 #[cfg(dma_v1)]
672 w.set_trbuff(true); 712 w.set_trbuff(true);
673 #[cfg(dma_v2)] 713 #[cfg(dma_v2)]
@@ -706,11 +746,15 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
706 this 746 this
707 } 747 }
708 748
749 /// Start the ring buffer operation.
750 ///
751 /// You must call this after creating it for it to work.
709 pub fn start(&mut self) { 752 pub fn start(&mut self) {
710 let ch = self.channel.regs().st(self.channel.num()); 753 let ch = self.channel.regs().st(self.channel.num());
711 ch.cr().write_value(self.cr); 754 ch.cr().write_value(self.cr);
712 } 755 }
713 756
757 /// Clear all data in the ring buffer.
714 pub fn clear(&mut self) { 758 pub fn clear(&mut self) {
715 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 759 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
716 } 760 }
@@ -741,11 +785,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
741 .await 785 .await
742 } 786 }
743 787
744 // The capacity of the ringbuffer 788 /// The capacity of the ringbuffer
745 pub const fn cap(&self) -> usize { 789 pub const fn capacity(&self) -> usize {
746 self.ringbuf.cap() 790 self.ringbuf.cap()
747 } 791 }
748 792
793 /// Set a waker to be woken when at least one byte is received.
749 pub fn set_waker(&mut self, waker: &Waker) { 794 pub fn set_waker(&mut self, waker: &Waker) {
750 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); 795 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
751 } 796 }
@@ -763,6 +808,9 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
763 }); 808 });
764 } 809 }
765 810
811 /// Request DMA to stop.
812 ///
813 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
766 pub fn request_stop(&mut self) { 814 pub fn request_stop(&mut self) {
767 let ch = self.channel.regs().st(self.channel.num()); 815 let ch = self.channel.regs().st(self.channel.num());
768 816
@@ -774,6 +822,10 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
774 }); 822 });
775 } 823 }
776 824
825 /// Return whether DMA is still running.
826 ///
827 /// If this returns `false`, it can be because either the transfer finished, or
828 /// it was requested to stop early with [`request_stop`](Self::request_stop).
777 pub fn is_running(&mut self) -> bool { 829 pub fn is_running(&mut self) -> bool {
778 let ch = self.channel.regs().st(self.channel.num()); 830 let ch = self.channel.regs().st(self.channel.num());
779 ch.cr().read().en() 831 ch.cr().read().en()
@@ -790,6 +842,7 @@ impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> {
790 } 842 }
791} 843}
792 844
845/// Ringbuffer for writing data using DMA circular mode.
793pub struct WritableRingBuffer<'a, C: Channel, W: Word> { 846pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
794 cr: regs::Cr, 847 cr: regs::Cr,
795 channel: PeripheralRef<'a, C>, 848 channel: PeripheralRef<'a, C>,
@@ -797,7 +850,8 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> {
797} 850}
798 851
799impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { 852impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
800 pub unsafe fn new_write( 853 /// Create a new ring buffer.
854 pub unsafe fn new(
801 channel: impl Peripheral<P = C> + 'a, 855 channel: impl Peripheral<P = C> + 'a,
802 _request: Request, 856 _request: Request,
803 peri_addr: *mut W, 857 peri_addr: *mut W,
@@ -823,12 +877,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
823 w.set_msize(data_size.into()); 877 w.set_msize(data_size.into());
824 w.set_psize(data_size.into()); 878 w.set_psize(data_size.into());
825 w.set_pl(vals::Pl::VERYHIGH); 879 w.set_pl(vals::Pl::VERYHIGH);
826 w.set_minc(vals::Inc::INCREMENTED); 880 w.set_minc(true);
827 w.set_pinc(vals::Inc::FIXED); 881 w.set_pinc(false);
828 w.set_teie(true); 882 w.set_teie(true);
829 w.set_htie(options.half_transfer_ir); 883 w.set_htie(options.half_transfer_ir);
830 w.set_tcie(true); 884 w.set_tcie(true);
831 w.set_circ(vals::Circ::ENABLED); 885 w.set_circ(true);
832 #[cfg(dma_v1)] 886 #[cfg(dma_v1)]
833 w.set_trbuff(true); 887 w.set_trbuff(true);
834 #[cfg(dma_v2)] 888 #[cfg(dma_v2)]
@@ -867,11 +921,15 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
867 this 921 this
868 } 922 }
869 923
924 /// Start the ring buffer operation.
925 ///
926 /// You must call this after creating it for it to work.
870 pub fn start(&mut self) { 927 pub fn start(&mut self) {
871 let ch = self.channel.regs().st(self.channel.num()); 928 let ch = self.channel.regs().st(self.channel.num());
872 ch.cr().write_value(self.cr); 929 ch.cr().write_value(self.cr);
873 } 930 }
874 931
932 /// Clear all data in the ring buffer.
875 pub fn clear(&mut self) { 933 pub fn clear(&mut self) {
876 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 934 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
877 } 935 }
@@ -889,11 +947,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
889 .await 947 .await
890 } 948 }
891 949
892 // The capacity of the ringbuffer 950 /// The capacity of the ringbuffer
893 pub const fn cap(&self) -> usize { 951 pub const fn capacity(&self) -> usize {
894 self.ringbuf.cap() 952 self.ringbuf.cap()
895 } 953 }
896 954
955 /// Set a waker to be woken when at least one byte is received.
897 pub fn set_waker(&mut self, waker: &Waker) { 956 pub fn set_waker(&mut self, waker: &Waker) {
898 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); 957 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
899 } 958 }
@@ -911,6 +970,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
911 }); 970 });
912 } 971 }
913 972
973 /// Request DMA to stop.
974 ///
975 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
914 pub fn request_stop(&mut self) { 976 pub fn request_stop(&mut self) {
915 let ch = self.channel.regs().st(self.channel.num()); 977 let ch = self.channel.regs().st(self.channel.num());
916 978
@@ -922,6 +984,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
922 }); 984 });
923 } 985 }
924 986
987 /// Return whether DMA is still running.
988 ///
989 /// If this returns `false`, it can be because either the transfer finished, or
990 /// it was requested to stop early with [`request_stop`](Self::request_stop).
925 pub fn is_running(&mut self) -> bool { 991 pub fn is_running(&mut self) -> bool {
926 let ch = self.channel.regs().st(self.channel.num()); 992 let ch = self.channel.regs().st(self.channel.num());
927 ch.cr().read().en() 993 ch.cr().read().en()
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index 20601dc86..9cd494724 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -22,11 +22,15 @@ pub(crate) mod dmamux_sealed {
22 } 22 }
23} 23}
24 24
25/// DMAMUX1 instance.
25pub struct DMAMUX1; 26pub struct DMAMUX1;
27/// DMAMUX2 instance.
26#[cfg(stm32h7)] 28#[cfg(stm32h7)]
27pub struct DMAMUX2; 29pub struct DMAMUX2;
28 30
31/// DMAMUX channel trait.
29pub trait MuxChannel: dmamux_sealed::MuxChannel { 32pub trait MuxChannel: dmamux_sealed::MuxChannel {
33 /// DMAMUX instance this channel is on.
30 type Mux; 34 type Mux;
31} 35}
32 36
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index b061415eb..34b2426b9 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -16,6 +16,7 @@ use crate::interrupt::Priority;
16use crate::pac; 16use crate::pac;
17use crate::pac::gpdma::vals; 17use crate::pac::gpdma::vals;
18 18
19/// GPDMA transfer options.
19#[derive(Debug, Copy, Clone, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[non_exhaustive] 22#[non_exhaustive]
@@ -113,10 +114,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in
113 } 114 }
114} 115}
115 116
117/// DMA request type alias. (also known as DMA channel number in some chips)
116pub type Request = u8; 118pub type Request = u8;
117 119
120/// DMA channel.
118#[cfg(dmamux)] 121#[cfg(dmamux)]
119pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} 122pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
123/// DMA channel.
120#[cfg(not(dmamux))] 124#[cfg(not(dmamux))]
121pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} 125pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
122 126
@@ -131,12 +135,14 @@ pub(crate) mod sealed {
131 } 135 }
132} 136}
133 137
138/// DMA transfer.
134#[must_use = "futures do nothing unless you `.await` or poll them"] 139#[must_use = "futures do nothing unless you `.await` or poll them"]
135pub struct Transfer<'a, C: Channel> { 140pub struct Transfer<'a, C: Channel> {
136 channel: PeripheralRef<'a, C>, 141 channel: PeripheralRef<'a, C>,
137} 142}
138 143
139impl<'a, C: Channel> Transfer<'a, C> { 144impl<'a, C: Channel> Transfer<'a, C> {
145 /// Create a new read DMA transfer (peripheral to memory).
140 pub unsafe fn new_read<W: Word>( 146 pub unsafe fn new_read<W: Word>(
141 channel: impl Peripheral<P = C> + 'a, 147 channel: impl Peripheral<P = C> + 'a,
142 request: Request, 148 request: Request,
@@ -147,6 +153,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
147 Self::new_read_raw(channel, request, peri_addr, buf, options) 153 Self::new_read_raw(channel, request, peri_addr, buf, options)
148 } 154 }
149 155
156 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
150 pub unsafe fn new_read_raw<W: Word>( 157 pub unsafe fn new_read_raw<W: Word>(
151 channel: impl Peripheral<P = C> + 'a, 158 channel: impl Peripheral<P = C> + 'a,
152 request: Request, 159 request: Request,
@@ -172,6 +179,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
172 ) 179 )
173 } 180 }
174 181
182 /// Create a new write DMA transfer (memory to peripheral).
175 pub unsafe fn new_write<W: Word>( 183 pub unsafe fn new_write<W: Word>(
176 channel: impl Peripheral<P = C> + 'a, 184 channel: impl Peripheral<P = C> + 'a,
177 request: Request, 185 request: Request,
@@ -182,6 +190,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
182 Self::new_write_raw(channel, request, buf, peri_addr, options) 190 Self::new_write_raw(channel, request, buf, peri_addr, options)
183 } 191 }
184 192
193 /// Create a new write DMA transfer (memory to peripheral), using raw pointers.
185 pub unsafe fn new_write_raw<W: Word>( 194 pub unsafe fn new_write_raw<W: Word>(
186 channel: impl Peripheral<P = C> + 'a, 195 channel: impl Peripheral<P = C> + 'a,
187 request: Request, 196 request: Request,
@@ -207,6 +216,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
207 ) 216 )
208 } 217 }
209 218
219 /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
210 pub unsafe fn new_write_repeated<W: Word>( 220 pub unsafe fn new_write_repeated<W: Word>(
211 channel: impl Peripheral<P = C> + 'a, 221 channel: impl Peripheral<P = C> + 'a,
212 request: Request, 222 request: Request,
@@ -297,6 +307,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
297 this 307 this
298 } 308 }
299 309
310 /// Request the transfer to stop.
311 ///
312 /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
300 pub fn request_stop(&mut self) { 313 pub fn request_stop(&mut self) {
301 let ch = self.channel.regs().ch(self.channel.num()); 314 let ch = self.channel.regs().ch(self.channel.num());
302 ch.cr().modify(|w| { 315 ch.cr().modify(|w| {
@@ -304,6 +317,10 @@ impl<'a, C: Channel> Transfer<'a, C> {
304 }) 317 })
305 } 318 }
306 319
320 /// Return whether this transfer is still running.
321 ///
322 /// If this returns `false`, it can be because either the transfer finished, or
323 /// it was requested to stop early with [`request_stop`](Self::request_stop).
307 pub fn is_running(&mut self) -> bool { 324 pub fn is_running(&mut self) -> bool {
308 let ch = self.channel.regs().ch(self.channel.num()); 325 let ch = self.channel.regs().ch(self.channel.num());
309 let sr = ch.sr().read(); 326 let sr = ch.sr().read();
@@ -317,6 +334,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
317 ch.br1().read().bndt() 334 ch.br1().read().bndt()
318 } 335 }
319 336
337 /// Blocking wait until the transfer finishes.
320 pub fn blocking_wait(mut self) { 338 pub fn blocking_wait(mut self) {
321 while self.is_running() {} 339 while self.is_running() {}
322 340
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 29fced8fc..38945ac33 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -1,3 +1,5 @@
1//! Direct Memory Access (DMA)
2
1#[cfg(dma)] 3#[cfg(dma)]
2pub(crate) mod dma; 4pub(crate) mod dma;
3#[cfg(dma)] 5#[cfg(dma)]
@@ -39,6 +41,13 @@ enum Dir {
39 PeripheralToMemory, 41 PeripheralToMemory,
40} 42}
41 43
44/// "No DMA" placeholder.
45///
46/// You may pass this in place of a real DMA channel when creating a driver
47/// to indicate it should not use DMA.
48///
49/// This often causes async functionality to not be available on the instance,
50/// leaving only blocking functionality.
42pub struct NoDma; 51pub struct NoDma;
43 52
44impl_peripheral!(NoDma); 53impl_peripheral!(NoDma);
diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs
index aef6e9700..a72c4b7d9 100644
--- a/embassy-stm32/src/dma/word.rs
+++ b/embassy-stm32/src/dma/word.rs
@@ -1,3 +1,6 @@
1//! DMA word sizes.
2
3#[allow(missing_docs)]
1#[derive(Debug, Copy, Clone, PartialEq, Eq)] 4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3pub enum WordSize { 6pub enum WordSize {
@@ -7,6 +10,7 @@ pub enum WordSize {
7} 10}
8 11
9impl WordSize { 12impl WordSize {
13 /// Amount of bytes of this word size.
10 pub fn bytes(&self) -> usize { 14 pub fn bytes(&self) -> usize {
11 match self { 15 match self {
12 Self::OneByte => 1, 16 Self::OneByte => 1,
@@ -20,8 +24,13 @@ mod sealed {
20 pub trait Word {} 24 pub trait Word {}
21} 25}
22 26
27/// DMA word trait.
28///
29/// This is implemented for u8, u16, u32, etc.
23pub trait Word: sealed::Word + Default + Copy + 'static { 30pub trait Word: sealed::Word + Default + Copy + 'static {
31 /// Word size
24 fn size() -> WordSize; 32 fn size() -> WordSize;
33 /// Amount of bits of this word size.
25 fn bits() -> usize; 34 fn bits() -> usize;
26} 35}
27 36
@@ -40,6 +49,7 @@ macro_rules! impl_word {
40 ($T:ident, $uX:ident, $bits:literal, $size:ident) => { 49 ($T:ident, $uX:ident, $bits:literal, $size:ident) => {
41 #[repr(transparent)] 50 #[repr(transparent)]
42 #[derive(Copy, Clone, Default)] 51 #[derive(Copy, Clone, Default)]
52 #[doc = concat!(stringify!($T), " word size")]
43 pub struct $T(pub $uX); 53 pub struct $T(pub $uX);
44 impl_word!(_, $T, $bits, $size); 54 impl_word!(_, $T, $bits, $size);
45 }; 55 };
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs
index 1e1094a1c..9c26e90f1 100644
--- a/embassy-stm32/src/eth/generic_smi.rs
+++ b/embassy-stm32/src/eth/generic_smi.rs
@@ -102,6 +102,7 @@ unsafe impl PHY for GenericSMI {
102 102
103/// Public functions for the PHY 103/// Public functions for the PHY
104impl GenericSMI { 104impl GenericSMI {
105 /// Set the SMI polling interval.
105 #[cfg(feature = "time")] 106 #[cfg(feature = "time")]
106 pub fn set_poll_interval(&mut self, poll_interval: Duration) { 107 pub fn set_poll_interval(&mut self, poll_interval: Duration) {
107 self.poll_interval = poll_interval 108 self.poll_interval = poll_interval
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 556aadd73..448405507 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -1,3 +1,4 @@
1//! Ethernet (ETH)
1#![macro_use] 2#![macro_use]
2 3
3#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] 4#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")]
@@ -22,6 +23,14 @@ const RX_BUFFER_SIZE: usize = 1536;
22#[derive(Copy, Clone)] 23#[derive(Copy, Clone)]
23pub(crate) struct Packet<const N: usize>([u8; N]); 24pub(crate) struct Packet<const N: usize>([u8; N]);
24 25
26/// Ethernet packet queue.
27///
28/// This struct owns the memory used for reading and writing packets.
29///
30/// `TX` is the number of packets in the transmit queue, `RX` in the receive
31/// queue. A bigger queue allows the hardware to receive more packets while the
32/// CPU is busy doing other things, which may increase performance (especially for RX)
33/// at the cost of more RAM usage.
25pub struct PacketQueue<const TX: usize, const RX: usize> { 34pub struct PacketQueue<const TX: usize, const RX: usize> {
26 tx_desc: [TDes; TX], 35 tx_desc: [TDes; TX],
27 rx_desc: [RDes; RX], 36 rx_desc: [RDes; RX],
@@ -30,6 +39,7 @@ pub struct PacketQueue<const TX: usize, const RX: usize> {
30} 39}
31 40
32impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> { 41impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> {
42 /// Create a new packet queue.
33 pub const fn new() -> Self { 43 pub const fn new() -> Self {
34 const NEW_TDES: TDes = TDes::new(); 44 const NEW_TDES: TDes = TDes::new();
35 const NEW_RDES: RDes = RDes::new(); 45 const NEW_RDES: RDes = RDes::new();
@@ -41,7 +51,18 @@ impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> {
41 } 51 }
42 } 52 }
43 53
44 // Allow to initialize a Self without requiring it to go on the stack 54 /// Initialize a packet queue in-place.
55 ///
56 /// This can be helpful to avoid accidentally stack-allocating the packet queue in the stack. The
57 /// Rust compiler can sometimes be a bit dumb when working with large owned values: if you call `new()`
58 /// and then store the returned PacketQueue in its final place (like a `static`), the compiler might
59 /// place it temporarily on the stack then move it. Since this struct is quite big, it may result
60 /// in a stack overflow.
61 ///
62 /// With this function, you can create an uninitialized `static` with type `MaybeUninit<PacketQueue<...>>`
63 /// and initialize it in-place, guaranteeing no stack usage.
64 ///
65 /// After calling this function, calling `assume_init` on the MaybeUninit is guaranteed safe.
45 pub fn init(this: &mut MaybeUninit<Self>) { 66 pub fn init(this: &mut MaybeUninit<Self>) {
46 unsafe { 67 unsafe {
47 this.as_mut_ptr().write_bytes(0u8, 1); 68 this.as_mut_ptr().write_bytes(0u8, 1);
@@ -93,6 +114,7 @@ impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P>
93 } 114 }
94} 115}
95 116
117/// `embassy-net` RX token.
96pub struct RxToken<'a, 'd> { 118pub struct RxToken<'a, 'd> {
97 rx: &'a mut RDesRing<'d>, 119 rx: &'a mut RDesRing<'d>,
98} 120}
@@ -110,6 +132,7 @@ impl<'a, 'd> embassy_net_driver::RxToken for RxToken<'a, 'd> {
110 } 132 }
111} 133}
112 134
135/// `embassy-net` TX token.
113pub struct TxToken<'a, 'd> { 136pub struct TxToken<'a, 'd> {
114 tx: &'a mut TDesRing<'d>, 137 tx: &'a mut TDesRing<'d>,
115} 138}
@@ -159,6 +182,7 @@ pub(crate) mod sealed {
159 } 182 }
160} 183}
161 184
185/// Ethernet instance.
162pub trait Instance: sealed::Instance + Send + 'static {} 186pub trait Instance: sealed::Instance + Send + 'static {}
163 187
164impl sealed::Instance for crate::peripherals::ETH { 188impl sealed::Instance for crate::peripherals::ETH {
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 13e53f687..2ce5b3927 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -43,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
43 } 43 }
44} 44}
45 45
46/// Ethernet driver.
46pub struct Ethernet<'d, T: Instance, P: PHY> { 47pub struct Ethernet<'d, T: Instance, P: PHY> {
47 _peri: PeripheralRef<'d, T>, 48 _peri: PeripheralRef<'d, T>,
48 pub(crate) tx: TDesRing<'d>, 49 pub(crate) tx: TDesRing<'d>,
@@ -266,6 +267,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
266 } 267 }
267} 268}
268 269
270/// Ethernet station management interface.
269pub struct EthernetStationManagement<T: Instance> { 271pub struct EthernetStationManagement<T: Instance> {
270 peri: PhantomData<T>, 272 peri: PhantomData<T>,
271 clock_range: Cr, 273 clock_range: Cr,
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index c77155fea..59745cba0 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -34,6 +34,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
34 } 34 }
35} 35}
36 36
37/// Ethernet driver.
37pub struct Ethernet<'d, T: Instance, P: PHY> { 38pub struct Ethernet<'d, T: Instance, P: PHY> {
38 _peri: PeripheralRef<'d, T>, 39 _peri: PeripheralRef<'d, T>,
39 pub(crate) tx: TDesRing<'d>, 40 pub(crate) tx: TDesRing<'d>,
@@ -56,6 +57,7 @@ macro_rules! config_pins {
56} 57}
57 58
58impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { 59impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
60 /// Create a new Ethernet driver.
59 pub fn new<const TX: usize, const RX: usize>( 61 pub fn new<const TX: usize, const RX: usize>(
60 queue: &'d mut PacketQueue<TX, RX>, 62 queue: &'d mut PacketQueue<TX, RX>,
61 peri: impl Peripheral<P = T> + 'd, 63 peri: impl Peripheral<P = T> + 'd,
@@ -237,6 +239,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
237 } 239 }
238} 240}
239 241
242/// Ethernet SMI driver.
240pub struct EthernetStationManagement<T: Instance> { 243pub struct EthernetStationManagement<T: Instance> {
241 peri: PhantomData<T>, 244 peri: PhantomData<T>,
242 clock_range: u8, 245 clock_range: u8,
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index e77ac30fb..f83bae3ff 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -1,3 +1,4 @@
1//! External Interrupts (EXTI)
1use core::convert::Infallible; 2use core::convert::Infallible;
2use core::future::Future; 3use core::future::Future;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
@@ -39,7 +40,7 @@ fn exticr_regs() -> pac::afio::Afio {
39 pac::AFIO 40 pac::AFIO
40} 41}
41 42
42pub unsafe fn on_irq() { 43unsafe fn on_irq() {
43 #[cfg(feature = "low-power")] 44 #[cfg(feature = "low-power")]
44 crate::low_power::on_wakeup_irq(); 45 crate::low_power::on_wakeup_irq();
45 46
@@ -85,7 +86,13 @@ impl Iterator for BitIter {
85 } 86 }
86} 87}
87 88
88/// EXTI input driver 89/// EXTI input driver.
90///
91/// This driver augments a GPIO `Input` with EXTI functionality. EXTI is not
92/// built into `Input` itself because it needs to take ownership of the corresponding
93/// EXTI channel, which is a limited resource.
94///
95/// Pins PA5, PB5, PC5... all use EXTI channel 5, so you can't use EXTI on, say, PA5 and PC5 at the same time.
89pub struct ExtiInput<'d, T: GpioPin> { 96pub struct ExtiInput<'d, T: GpioPin> {
90 pin: Input<'d, T>, 97 pin: Input<'d, T>,
91} 98}
@@ -93,23 +100,30 @@ pub struct ExtiInput<'d, T: GpioPin> {
93impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} 100impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {}
94 101
95impl<'d, T: GpioPin> ExtiInput<'d, T> { 102impl<'d, T: GpioPin> ExtiInput<'d, T> {
103 /// Create an EXTI input.
96 pub fn new(pin: Input<'d, T>, _ch: impl Peripheral<P = T::ExtiChannel> + 'd) -> Self { 104 pub fn new(pin: Input<'d, T>, _ch: impl Peripheral<P = T::ExtiChannel> + 'd) -> Self {
97 Self { pin } 105 Self { pin }
98 } 106 }
99 107
108 /// Get whether the pin is high.
100 pub fn is_high(&mut self) -> bool { 109 pub fn is_high(&mut self) -> bool {
101 self.pin.is_high() 110 self.pin.is_high()
102 } 111 }
103 112
113 /// Get whether the pin is low.
104 pub fn is_low(&mut self) -> bool { 114 pub fn is_low(&mut self) -> bool {
105 self.pin.is_low() 115 self.pin.is_low()
106 } 116 }
107 117
118 /// Get the pin level.
108 pub fn get_level(&mut self) -> Level { 119 pub fn get_level(&mut self) -> Level {
109 self.pin.get_level() 120 self.pin.get_level()
110 } 121 }
111 122
112 pub async fn wait_for_high<'a>(&'a mut self) { 123 /// Asynchronously wait until the pin is high.
124 ///
125 /// This returns immediately if the pin is already high.
126 pub async fn wait_for_high(&mut self) {
113 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); 127 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false);
114 if self.is_high() { 128 if self.is_high() {
115 return; 129 return;
@@ -117,7 +131,10 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
117 fut.await 131 fut.await
118 } 132 }
119 133
120 pub async fn wait_for_low<'a>(&'a mut self) { 134 /// Asynchronously wait until the pin is low.
135 ///
136 /// This returns immediately if the pin is already low.
137 pub async fn wait_for_low(&mut self) {
121 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true); 138 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true);
122 if self.is_low() { 139 if self.is_low() {
123 return; 140 return;
@@ -125,15 +142,22 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
125 fut.await 142 fut.await
126 } 143 }
127 144
128 pub async fn wait_for_rising_edge<'a>(&'a mut self) { 145 /// Asynchronously wait until the pin sees a rising edge.
146 ///
147 /// If the pin is already high, it will wait for it to go low then back high.
148 pub async fn wait_for_rising_edge(&mut self) {
129 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await 149 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await
130 } 150 }
131 151
132 pub async fn wait_for_falling_edge<'a>(&'a mut self) { 152 /// Asynchronously wait until the pin sees a falling edge.
153 ///
154 /// If the pin is already low, it will wait for it to go high then back low.
155 pub async fn wait_for_falling_edge(&mut self) {
133 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await 156 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await
134 } 157 }
135 158
136 pub async fn wait_for_any_edge<'a>(&'a mut self) { 159 /// Asynchronously wait until the pin sees any edge (either rising or falling).
160 pub async fn wait_for_any_edge(&mut self) {
137 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await 161 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await
138 } 162 }
139} 163}
@@ -284,6 +308,7 @@ macro_rules! foreach_exti_irq {
284 308
285macro_rules! impl_irq { 309macro_rules! impl_irq {
286 ($e:ident) => { 310 ($e:ident) => {
311 #[allow(non_snake_case)]
287 #[cfg(feature = "rt")] 312 #[cfg(feature = "rt")]
288 #[interrupt] 313 #[interrupt]
289 unsafe fn $e() { 314 unsafe fn $e() {
@@ -298,8 +323,16 @@ pub(crate) mod sealed {
298 pub trait Channel {} 323 pub trait Channel {}
299} 324}
300 325
326/// EXTI channel trait.
301pub trait Channel: sealed::Channel + Sized { 327pub trait Channel: sealed::Channel + Sized {
328 /// Get the EXTI channel number.
302 fn number(&self) -> usize; 329 fn number(&self) -> usize;
330
331 /// Type-erase (degrade) this channel into an `AnyChannel`.
332 ///
333 /// This converts EXTI channel singletons (`EXTI0`, `EXTI1`, ...), which
334 /// are all different types, into the same type. It is useful for
335 /// creating arrays of channels, or avoiding generics.
303 fn degrade(self) -> AnyChannel { 336 fn degrade(self) -> AnyChannel {
304 AnyChannel { 337 AnyChannel {
305 number: self.number() as u8, 338 number: self.number() as u8,
@@ -307,9 +340,13 @@ pub trait Channel: sealed::Channel + Sized {
307 } 340 }
308} 341}
309 342
343/// Type-erased (degraded) EXTI channel.
344///
345/// This represents ownership over any EXTI channel, known at runtime.
310pub struct AnyChannel { 346pub struct AnyChannel {
311 number: u8, 347 number: u8,
312} 348}
349
313impl_peripheral!(AnyChannel); 350impl_peripheral!(AnyChannel);
314impl sealed::Channel for AnyChannel {} 351impl sealed::Channel for AnyChannel {}
315impl Channel for AnyChannel { 352impl Channel for AnyChannel {
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs
index eae40c7ec..97eaece81 100644
--- a/embassy-stm32/src/flash/asynch.rs
+++ b/embassy-stm32/src/flash/asynch.rs
@@ -17,6 +17,7 @@ use crate::{interrupt, Peripheral};
17pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(()); 17pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
18 18
19impl<'d> Flash<'d, Async> { 19impl<'d> Flash<'d, Async> {
20 /// Create a new flash driver with async capabilities.
20 pub fn new( 21 pub fn new(
21 p: impl Peripheral<P = FLASH> + 'd, 22 p: impl Peripheral<P = FLASH> + 'd,
22 _irq: impl interrupt::typelevel::Binding<crate::interrupt::typelevel::FLASH, InterruptHandler> + 'd, 23 _irq: impl interrupt::typelevel::Binding<crate::interrupt::typelevel::FLASH, InterruptHandler> + 'd,
@@ -32,15 +33,26 @@ impl<'d> Flash<'d, Async> {
32 } 33 }
33 } 34 }
34 35
36 /// Split this flash driver into one instance per flash memory region.
37 ///
38 /// See module-level documentation for details on how memory regions work.
35 pub fn into_regions(self) -> FlashLayout<'d, Async> { 39 pub fn into_regions(self) -> FlashLayout<'d, Async> {
36 assert!(family::is_default_layout()); 40 assert!(family::is_default_layout());
37 FlashLayout::new(self.inner) 41 FlashLayout::new(self.inner)
38 } 42 }
39 43
44 /// Async write.
45 ///
46 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
47 /// For example, to write address `0x0800_1234` you have to use offset `0x1234`.
40 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 48 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
41 unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } 49 unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await }
42 } 50 }
43 51
52 /// Async erase.
53 ///
54 /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address.
55 /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`.
44 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 56 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
45 unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } 57 unsafe { erase_sectored(FLASH_BASE as u32, from, to).await }
46 } 58 }
@@ -59,7 +71,7 @@ impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> {
59 const READ_SIZE: usize = super::READ_SIZE; 71 const READ_SIZE: usize = super::READ_SIZE;
60 72
61 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 73 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
62 self.read(offset, bytes) 74 self.blocking_read(offset, bytes)
63 } 75 }
64 76
65 fn capacity(&self) -> usize { 77 fn capacity(&self) -> usize {
@@ -141,15 +153,20 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu
141foreach_flash_region! { 153foreach_flash_region! {
142 ($type_name:ident, $write_size:literal, $erase_size:literal) => { 154 ($type_name:ident, $write_size:literal, $erase_size:literal) => {
143 impl crate::_generated::flash_regions::$type_name<'_, Async> { 155 impl crate::_generated::flash_regions::$type_name<'_, Async> {
156 /// Async read.
157 ///
158 /// Note: reading from flash can't actually block, so this is the same as `blocking_read`.
144 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 159 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
145 blocking_read(self.0.base, self.0.size, offset, bytes) 160 blocking_read(self.0.base, self.0.size, offset, bytes)
146 } 161 }
147 162
163 /// Async write.
148 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 164 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
149 let _guard = REGION_ACCESS.lock().await; 165 let _guard = REGION_ACCESS.lock().await;
150 unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } 166 unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await }
151 } 167 }
152 168
169 /// Async erase.
153 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 170 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
154 let _guard = REGION_ACCESS.lock().await; 171 let _guard = REGION_ACCESS.lock().await;
155 unsafe { erase_sectored(self.0.base, from, to).await } 172 unsafe { erase_sectored(self.0.base, from, to).await }
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index 8acad1c7c..f8561edb3 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -12,12 +12,14 @@ use super::{
12use crate::peripherals::FLASH; 12use crate::peripherals::FLASH;
13use crate::Peripheral; 13use crate::Peripheral;
14 14
15/// Internal flash memory driver.
15pub struct Flash<'d, MODE = Async> { 16pub struct Flash<'d, MODE = Async> {
16 pub(crate) inner: PeripheralRef<'d, FLASH>, 17 pub(crate) inner: PeripheralRef<'d, FLASH>,
17 pub(crate) _mode: PhantomData<MODE>, 18 pub(crate) _mode: PhantomData<MODE>,
18} 19}
19 20
20impl<'d> Flash<'d, Blocking> { 21impl<'d> Flash<'d, Blocking> {
22 /// Create a new flash driver, usable in blocking mode.
21 pub fn new_blocking(p: impl Peripheral<P = FLASH> + 'd) -> Self { 23 pub fn new_blocking(p: impl Peripheral<P = FLASH> + 'd) -> Self {
22 into_ref!(p); 24 into_ref!(p);
23 25
@@ -29,15 +31,26 @@ impl<'d> Flash<'d, Blocking> {
29} 31}
30 32
31impl<'d, MODE> Flash<'d, MODE> { 33impl<'d, MODE> Flash<'d, MODE> {
34 /// Split this flash driver into one instance per flash memory region.
35 ///
36 /// See module-level documentation for details on how memory regions work.
32 pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { 37 pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> {
33 assert!(family::is_default_layout()); 38 assert!(family::is_default_layout());
34 FlashLayout::new(self.inner) 39 FlashLayout::new(self.inner)
35 } 40 }
36 41
37 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 42 /// Blocking read.
43 ///
44 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
45 /// For example, to read address `0x0800_1234` you have to use offset `0x1234`.
46 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
38 blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) 47 blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes)
39 } 48 }
40 49
50 /// Blocking write.
51 ///
52 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
53 /// For example, to write address `0x0800_1234` you have to use offset `0x1234`.
41 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 54 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
42 unsafe { 55 unsafe {
43 blocking_write( 56 blocking_write(
@@ -50,6 +63,10 @@ impl<'d, MODE> Flash<'d, MODE> {
50 } 63 }
51 } 64 }
52 65
66 /// Blocking erase.
67 ///
68 /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address.
69 /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`.
53 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 70 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
54 unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) } 71 unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) }
55 } 72 }
@@ -206,7 +223,7 @@ impl<MODE> embedded_storage::nor_flash::ReadNorFlash for Flash<'_, MODE> {
206 const READ_SIZE: usize = READ_SIZE; 223 const READ_SIZE: usize = READ_SIZE;
207 224
208 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 225 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
209 self.read(offset, bytes) 226 self.blocking_read(offset, bytes)
210 } 227 }
211 228
212 fn capacity(&self) -> usize { 229 fn capacity(&self) -> usize {
@@ -230,16 +247,28 @@ impl<MODE> embedded_storage::nor_flash::NorFlash for Flash<'_, MODE> {
230foreach_flash_region! { 247foreach_flash_region! {
231 ($type_name:ident, $write_size:literal, $erase_size:literal) => { 248 ($type_name:ident, $write_size:literal, $erase_size:literal) => {
232 impl<MODE> crate::_generated::flash_regions::$type_name<'_, MODE> { 249 impl<MODE> crate::_generated::flash_regions::$type_name<'_, MODE> {
250 /// Blocking read.
251 ///
252 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
253 /// For example, to read address `0x0800_1234` you have to use offset `0x1234`.
233 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 254 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
234 blocking_read(self.0.base, self.0.size, offset, bytes) 255 blocking_read(self.0.base, self.0.size, offset, bytes)
235 } 256 }
236 } 257 }
237 258
238 impl crate::_generated::flash_regions::$type_name<'_, Blocking> { 259 impl crate::_generated::flash_regions::$type_name<'_, Blocking> {
260 /// Blocking write.
261 ///
262 /// NOTE: `offset` is an offset from the flash start, NOT an absolute address.
263 /// For example, to write address `0x0800_1234` you have to use offset `0x1234`.
239 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 264 pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
240 unsafe { blocking_write(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } 265 unsafe { blocking_write(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) }
241 } 266 }
242 267
268 /// Blocking erase.
269 ///
270 /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address.
271 /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`.
243 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 272 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
244 unsafe { blocking_erase(self.0.base, from, to, erase_sector_with_critical_section) } 273 unsafe { blocking_erase(self.0.base, from, to, erase_sector_with_critical_section) }
245 } 274 }
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs
index 80d2a8166..c0a8d7022 100644
--- a/embassy-stm32/src/flash/f0.rs
+++ b/embassy-stm32/src/flash/f0.rs
@@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
6use crate::flash::Error; 6use crate::flash::Error;
7use crate::pac; 7use crate::pac;
8 8
9pub const fn is_default_layout() -> bool { 9pub(crate) const fn is_default_layout() -> bool {
10 true 10 true
11} 11}
12 12
13pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 13pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
14 &FLASH_REGIONS 14 &FLASH_REGIONS
15} 15}
16 16
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs
index 27d5281a7..817ccef4d 100644
--- a/embassy-stm32/src/flash/f3.rs
+++ b/embassy-stm32/src/flash/f3.rs
@@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
6use crate::flash::Error; 6use crate::flash::Error;
7use crate::pac; 7use crate::pac;
8 8
9pub const fn is_default_layout() -> bool { 9pub(crate) const fn is_default_layout() -> bool {
10 true 10 true
11} 11}
12 12
13pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 13pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
14 &FLASH_REGIONS 14 &FLASH_REGIONS
15} 15}
16 16
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index f442c5894..2671dfb04 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -9,7 +9,7 @@ use pac::FLASH_SIZE;
9use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; 9use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
10use crate::flash::Error; 10use crate::flash::Error;
11use crate::pac; 11use crate::pac;
12 12#[allow(missing_docs)] // TODO
13#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] 13#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))]
14mod alt_regions { 14mod alt_regions {
15 use core::marker::PhantomData; 15 use core::marker::PhantomData;
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs
index 017393e80..6b3e66ac6 100644
--- a/embassy-stm32/src/flash/f7.rs
+++ b/embassy-stm32/src/flash/f7.rs
@@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
6use crate::flash::Error; 6use crate::flash::Error;
7use crate::pac; 7use crate::pac;
8 8
9pub const fn is_default_layout() -> bool { 9pub(crate) const fn is_default_layout() -> bool {
10 true 10 true
11} 11}
12 12
13pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 13pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
14 &FLASH_REGIONS 14 &FLASH_REGIONS
15} 15}
16 16
diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs
index 08145e9c4..d97b4a932 100644
--- a/embassy-stm32/src/flash/g.rs
+++ b/embassy-stm32/src/flash/g.rs
@@ -8,11 +8,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
8use crate::flash::Error; 8use crate::flash::Error;
9use crate::pac; 9use crate::pac;
10 10
11pub const fn is_default_layout() -> bool { 11pub(crate) const fn is_default_layout() -> bool {
12 true 12 true
13} 13}
14 14
15pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 15pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
16 &FLASH_REGIONS 16 &FLASH_REGIONS
17} 17}
18 18
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs
index 555f8d155..65d163d29 100644
--- a/embassy-stm32/src/flash/h7.rs
+++ b/embassy-stm32/src/flash/h7.rs
@@ -6,7 +6,7 @@ use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE};
6use crate::flash::Error; 6use crate::flash::Error;
7use crate::pac; 7use crate::pac;
8 8
9pub const fn is_default_layout() -> bool { 9pub(crate) const fn is_default_layout() -> bool {
10 true 10 true
11} 11}
12 12
@@ -14,7 +14,7 @@ const fn is_dual_bank() -> bool {
14 FLASH_REGIONS.len() >= 2 14 FLASH_REGIONS.len() >= 2
15} 15}
16 16
17pub fn get_flash_regions() -> &'static [&'static FlashRegion] { 17pub(crate) fn get_flash_regions() -> &'static [&'static FlashRegion] {
18 &FLASH_REGIONS 18 &FLASH_REGIONS
19} 19}
20 20
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs
index e0159a3f6..0b332dc61 100644
--- a/embassy-stm32/src/flash/l.rs
+++ b/embassy-stm32/src/flash/l.rs
@@ -5,11 +5,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
5use crate::flash::Error; 5use crate::flash::Error;
6use crate::pac; 6use crate::pac;
7 7
8pub const fn is_default_layout() -> bool { 8pub(crate) const fn is_default_layout() -> bool {
9 true 9 true
10} 10}
11 11
12pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 12pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
13 &FLASH_REGIONS 13 &FLASH_REGIONS
14} 14}
15 15
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 3e8f2830b..cbf5c25b2 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -1,3 +1,4 @@
1//! Flash memory (FLASH)
1use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; 2use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind};
2 3
3#[cfg(flash_f4)] 4#[cfg(flash_f4)]
@@ -14,50 +15,84 @@ pub use crate::_generated::flash_regions::*;
14pub use crate::_generated::MAX_ERASE_SIZE; 15pub use crate::_generated::MAX_ERASE_SIZE;
15pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; 16pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE};
16 17
18/// Get whether the default flash layout is being used.
19///
20/// In some chips, dual-bank is not default. This will then return `false`
21/// when dual-bank is enabled.
22pub fn is_default_layout() -> bool {
23 family::is_default_layout()
24}
25
26/// Get all flash regions.
27pub fn get_flash_regions() -> &'static [&'static FlashRegion] {
28 family::get_flash_regions()
29}
30
31/// Read size (always 1)
17pub const READ_SIZE: usize = 1; 32pub const READ_SIZE: usize = 1;
18 33
19pub struct Blocking; 34/// Blocking flash mode typestate.
20pub struct Async; 35pub enum Blocking {}
36/// Async flash mode typestate.
37pub enum Async {}
21 38
39/// Flash memory region
22#[derive(Debug)] 40#[derive(Debug)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))] 41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub struct FlashRegion { 42pub struct FlashRegion {
43 /// Bank number.
25 pub bank: FlashBank, 44 pub bank: FlashBank,
45 /// Absolute base address.
26 pub base: u32, 46 pub base: u32,
47 /// Size in bytes.
27 pub size: u32, 48 pub size: u32,
49 /// Erase size (sector size).
28 pub erase_size: u32, 50 pub erase_size: u32,
51 /// Minimum write size.
29 pub write_size: u32, 52 pub write_size: u32,
53 /// Erase value (usually `0xFF`, but is `0x00` in some chips)
30 pub erase_value: u8, 54 pub erase_value: u8,
31 pub(crate) _ensure_internal: (), 55 pub(crate) _ensure_internal: (),
32} 56}
33 57
58impl FlashRegion {
59 /// Absolute end address.
60 pub const fn end(&self) -> u32 {
61 self.base + self.size
62 }
63
64 /// Number of sectors in the region.
65 pub const fn sectors(&self) -> u8 {
66 (self.size / self.erase_size) as u8
67 }
68}
69
70/// Flash sector.
34#[derive(Debug, PartialEq)] 71#[derive(Debug, PartialEq)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))] 72#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub struct FlashSector { 73pub struct FlashSector {
74 /// Bank number.
37 pub bank: FlashBank, 75 pub bank: FlashBank,
76 /// Sector number within the bank.
38 pub index_in_bank: u8, 77 pub index_in_bank: u8,
78 /// Absolute start address.
39 pub start: u32, 79 pub start: u32,
80 /// Size in bytes.
40 pub size: u32, 81 pub size: u32,
41} 82}
42 83
84/// Flash bank.
43#[derive(Clone, Copy, Debug, PartialEq)] 85#[derive(Clone, Copy, Debug, PartialEq)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))] 86#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub enum FlashBank { 87pub enum FlashBank {
88 /// Bank 1
46 Bank1 = 0, 89 Bank1 = 0,
90 /// Bank 2
47 Bank2 = 1, 91 Bank2 = 1,
92 /// OTP region
48 Otp, 93 Otp,
49} 94}
50 95
51impl FlashRegion {
52 pub const fn end(&self) -> u32 {
53 self.base + self.size
54 }
55
56 pub const fn sectors(&self) -> u8 {
57 (self.size / self.erase_size) as u8
58 }
59}
60
61#[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")] 96#[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")]
62#[cfg_attr(flash_f0, path = "f0.rs")] 97#[cfg_attr(flash_f0, path = "f0.rs")]
63#[cfg_attr(flash_f3, path = "f3.rs")] 98#[cfg_attr(flash_f3, path = "f3.rs")]
@@ -78,6 +113,10 @@ mod family;
78#[allow(unused_imports)] 113#[allow(unused_imports)]
79pub use family::*; 114pub use family::*;
80 115
116/// Flash error
117///
118/// See STM32 Reference Manual for your chip for details.
119#[allow(missing_docs)]
81#[derive(Debug, Copy, Clone, PartialEq, Eq)] 120#[derive(Debug, Copy, Clone, PartialEq, Eq)]
82#[cfg_attr(feature = "defmt", derive(defmt::Format))] 121#[cfg_attr(feature = "defmt", derive(defmt::Format))]
83pub enum Error { 122pub enum Error {
diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs
index a7e8d1d57..20f84a72f 100644
--- a/embassy-stm32/src/flash/other.rs
+++ b/embassy-stm32/src/flash/other.rs
@@ -2,11 +2,11 @@
2 2
3use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; 3use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
4 4
5pub const fn is_default_layout() -> bool { 5pub(crate) const fn is_default_layout() -> bool {
6 true 6 true
7} 7}
8 8
9pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { 9pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
10 &FLASH_REGIONS 10 &FLASH_REGIONS
11} 11}
12 12
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index dd0d27217..873c8a70c 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -1,3 +1,4 @@
1//! Flexible Memory Controller (FMC) / Flexible Static Memory Controller (FSMC)
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_hal_internal::into_ref; 4use embassy_hal_internal::into_ref;
@@ -6,6 +7,7 @@ use crate::gpio::sealed::AFType;
6use crate::gpio::{Pull, Speed}; 7use crate::gpio::{Pull, Speed};
7use crate::Peripheral; 8use crate::Peripheral;
8 9
10/// FMC driver
9pub struct Fmc<'d, T: Instance> { 11pub struct Fmc<'d, T: Instance> {
10 peri: PhantomData<&'d mut T>, 12 peri: PhantomData<&'d mut T>,
11} 13}
@@ -38,6 +40,7 @@ where
38 T::REGS.bcr1().modify(|r| r.set_fmcen(true)); 40 T::REGS.bcr1().modify(|r| r.set_fmcen(true));
39 } 41 }
40 42
43 /// Get the kernel clock currently in use for this FMC instance.
41 pub fn source_clock_hz(&self) -> u32 { 44 pub fn source_clock_hz(&self) -> u32 {
42 <T as crate::rcc::sealed::RccPeripheral>::frequency().0 45 <T as crate::rcc::sealed::RccPeripheral>::frequency().0
43 } 46 }
@@ -85,6 +88,7 @@ macro_rules! fmc_sdram_constructor {
85 nbl: [$(($nbl_pin_name:ident: $nbl_signal:ident)),*], 88 nbl: [$(($nbl_pin_name:ident: $nbl_signal:ident)),*],
86 ctrl: [$(($ctrl_pin_name:ident: $ctrl_signal:ident)),*] 89 ctrl: [$(($ctrl_pin_name:ident: $ctrl_signal:ident)),*]
87 )) => { 90 )) => {
91 /// Create a new FMC instance.
88 pub fn $name<CHIP: stm32_fmc::SdramChip>( 92 pub fn $name<CHIP: stm32_fmc::SdramChip>(
89 _instance: impl Peripheral<P = T> + 'd, 93 _instance: impl Peripheral<P = T> + 'd,
90 $($addr_pin_name: impl Peripheral<P = impl $addr_signal<T>> + 'd),*, 94 $($addr_pin_name: impl Peripheral<P = impl $addr_signal<T>> + 'd),*,
@@ -199,6 +203,7 @@ pub(crate) mod sealed {
199 } 203 }
200} 204}
201 205
206/// FMC instance trait.
202pub trait Instance: sealed::Instance + 'static {} 207pub trait Instance: sealed::Instance + 'static {}
203 208
204foreach_peripheral!( 209foreach_peripheral!(
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index bb3cf2bc4..c300a079e 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -1,3 +1,5 @@
1//! General-purpose Input/Output (GPIO)
2
1#![macro_use] 3#![macro_use]
2use core::convert::Infallible; 4use core::convert::Infallible;
3 5
@@ -29,6 +31,11 @@ impl<'d, T: Pin> Flex<'d, T> {
29 Self { pin } 31 Self { pin }
30 } 32 }
31 33
34 /// Type-erase (degrade) this pin into an `AnyPin`.
35 ///
36 /// This converts pin singletons (`PA5`, `PB6`, ...), which
37 /// are all different types, into the same type. It is useful for
38 /// creating arrays of pins, or avoiding generics.
32 #[inline] 39 #[inline]
33 pub fn degrade(self) -> Flex<'d, AnyPin> { 40 pub fn degrade(self) -> Flex<'d, AnyPin> {
34 // Safety: We are about to drop the other copy of this pin, so 41 // Safety: We are about to drop the other copy of this pin, so
@@ -141,11 +148,13 @@ impl<'d, T: Pin> Flex<'d, T> {
141 }); 148 });
142 } 149 }
143 150
151 /// Get whether the pin input level is high.
144 #[inline] 152 #[inline]
145 pub fn is_high(&mut self) -> bool { 153 pub fn is_high(&mut self) -> bool {
146 !self.ref_is_low() 154 !self.ref_is_low()
147 } 155 }
148 156
157 /// Get whether the pin input level is low.
149 #[inline] 158 #[inline]
150 pub fn is_low(&mut self) -> bool { 159 pub fn is_low(&mut self) -> bool {
151 self.ref_is_low() 160 self.ref_is_low()
@@ -157,17 +166,19 @@ impl<'d, T: Pin> Flex<'d, T> {
157 state == vals::Idr::LOW 166 state == vals::Idr::LOW
158 } 167 }
159 168
169 /// Get the current pin input level.
160 #[inline] 170 #[inline]
161 pub fn get_level(&mut self) -> Level { 171 pub fn get_level(&mut self) -> Level {
162 self.is_high().into() 172 self.is_high().into()
163 } 173 }
164 174
175 /// Get whether the output level is set to high.
165 #[inline] 176 #[inline]
166 pub fn is_set_high(&mut self) -> bool { 177 pub fn is_set_high(&mut self) -> bool {
167 !self.ref_is_set_low() 178 !self.ref_is_set_low()
168 } 179 }
169 180
170 /// Is the output pin set as low? 181 /// Get whether the output level is set to low.
171 #[inline] 182 #[inline]
172 pub fn is_set_low(&mut self) -> bool { 183 pub fn is_set_low(&mut self) -> bool {
173 self.ref_is_set_low() 184 self.ref_is_set_low()
@@ -179,12 +190,13 @@ impl<'d, T: Pin> Flex<'d, T> {
179 state == vals::Odr::LOW 190 state == vals::Odr::LOW
180 } 191 }
181 192
182 /// What level output is set to 193 /// Get the current output level.
183 #[inline] 194 #[inline]
184 pub fn get_output_level(&mut self) -> Level { 195 pub fn get_output_level(&mut self) -> Level {
185 self.is_set_high().into() 196 self.is_set_high().into()
186 } 197 }
187 198
199 /// Set the output as high.
188 #[inline] 200 #[inline]
189 pub fn set_high(&mut self) { 201 pub fn set_high(&mut self) {
190 self.pin.set_high(); 202 self.pin.set_high();
@@ -196,6 +208,7 @@ impl<'d, T: Pin> Flex<'d, T> {
196 self.pin.set_low(); 208 self.pin.set_low();
197 } 209 }
198 210
211 /// Set the output level.
199 #[inline] 212 #[inline]
200 pub fn set_level(&mut self, level: Level) { 213 pub fn set_level(&mut self, level: Level) {
201 match level { 214 match level {
@@ -204,7 +217,7 @@ impl<'d, T: Pin> Flex<'d, T> {
204 } 217 }
205 } 218 }
206 219
207 /// Toggle pin output 220 /// Toggle the output level.
208 #[inline] 221 #[inline]
209 pub fn toggle(&mut self) { 222 pub fn toggle(&mut self) {
210 if self.is_set_low() { 223 if self.is_set_low() {
@@ -242,8 +255,11 @@ impl<'d, T: Pin> Drop for Flex<'d, T> {
242#[derive(Debug, Eq, PartialEq, Copy, Clone)] 255#[derive(Debug, Eq, PartialEq, Copy, Clone)]
243#[cfg_attr(feature = "defmt", derive(defmt::Format))] 256#[cfg_attr(feature = "defmt", derive(defmt::Format))]
244pub enum Pull { 257pub enum Pull {
258 /// No pull
245 None, 259 None,
260 /// Pull up
246 Up, 261 Up,
262 /// Pull down
247 Down, 263 Down,
248} 264}
249 265
@@ -261,6 +277,9 @@ impl From<Pull> for vals::Pupdr {
261} 277}
262 278
263/// Speed settings 279/// Speed settings
280///
281/// These vary dpeending on the chip, ceck the reference manual or datasheet for details.
282#[allow(missing_docs)]
264#[derive(Debug, Copy, Clone)] 283#[derive(Debug, Copy, Clone)]
265#[cfg_attr(feature = "defmt", derive(defmt::Format))] 284#[cfg_attr(feature = "defmt", derive(defmt::Format))]
266pub enum Speed { 285pub enum Speed {
@@ -305,6 +324,7 @@ pub struct Input<'d, T: Pin> {
305} 324}
306 325
307impl<'d, T: Pin> Input<'d, T> { 326impl<'d, T: Pin> Input<'d, T> {
327 /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
308 #[inline] 328 #[inline]
309 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { 329 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
310 let mut pin = Flex::new(pin); 330 let mut pin = Flex::new(pin);
@@ -312,6 +332,11 @@ impl<'d, T: Pin> Input<'d, T> {
312 Self { pin } 332 Self { pin }
313 } 333 }
314 334
335 /// Type-erase (degrade) this pin into an `AnyPin`.
336 ///
337 /// This converts pin singletons (`PA5`, `PB6`, ...), which
338 /// are all different types, into the same type. It is useful for
339 /// creating arrays of pins, or avoiding generics.
315 #[inline] 340 #[inline]
316 pub fn degrade(self) -> Input<'d, AnyPin> { 341 pub fn degrade(self) -> Input<'d, AnyPin> {
317 Input { 342 Input {
@@ -319,16 +344,19 @@ impl<'d, T: Pin> Input<'d, T> {
319 } 344 }
320 } 345 }
321 346
347 /// Get whether the pin input level is high.
322 #[inline] 348 #[inline]
323 pub fn is_high(&mut self) -> bool { 349 pub fn is_high(&mut self) -> bool {
324 self.pin.is_high() 350 self.pin.is_high()
325 } 351 }
326 352
353 /// Get whether the pin input level is low.
327 #[inline] 354 #[inline]
328 pub fn is_low(&mut self) -> bool { 355 pub fn is_low(&mut self) -> bool {
329 self.pin.is_low() 356 self.pin.is_low()
330 } 357 }
331 358
359 /// Get the current pin input level.
332 #[inline] 360 #[inline]
333 pub fn get_level(&mut self) -> Level { 361 pub fn get_level(&mut self) -> Level {
334 self.pin.get_level() 362 self.pin.get_level()
@@ -339,7 +367,9 @@ impl<'d, T: Pin> Input<'d, T> {
339#[derive(Debug, Eq, PartialEq, Copy, Clone)] 367#[derive(Debug, Eq, PartialEq, Copy, Clone)]
340#[cfg_attr(feature = "defmt", derive(defmt::Format))] 368#[cfg_attr(feature = "defmt", derive(defmt::Format))]
341pub enum Level { 369pub enum Level {
370 /// Low
342 Low, 371 Low,
372 /// High
343 High, 373 High,
344} 374}
345 375
@@ -371,6 +401,7 @@ pub struct Output<'d, T: Pin> {
371} 401}
372 402
373impl<'d, T: Pin> Output<'d, T> { 403impl<'d, T: Pin> Output<'d, T> {
404 /// Create GPIO output driver for a [Pin] with the provided [Level] and [Speed] configuration.
374 #[inline] 405 #[inline]
375 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed) -> Self { 406 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed) -> Self {
376 let mut pin = Flex::new(pin); 407 let mut pin = Flex::new(pin);
@@ -382,6 +413,11 @@ impl<'d, T: Pin> Output<'d, T> {
382 Self { pin } 413 Self { pin }
383 } 414 }
384 415
416 /// Type-erase (degrade) this pin into an `AnyPin`.
417 ///
418 /// This converts pin singletons (`PA5`, `PB6`, ...), which
419 /// are all different types, into the same type. It is useful for
420 /// creating arrays of pins, or avoiding generics.
385 #[inline] 421 #[inline]
386 pub fn degrade(self) -> Output<'d, AnyPin> { 422 pub fn degrade(self) -> Output<'d, AnyPin> {
387 Output { 423 Output {
@@ -442,6 +478,7 @@ pub struct OutputOpenDrain<'d, T: Pin> {
442} 478}
443 479
444impl<'d, T: Pin> OutputOpenDrain<'d, T> { 480impl<'d, T: Pin> OutputOpenDrain<'d, T> {
481 /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed], [Pull] configuration.
445 #[inline] 482 #[inline]
446 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { 483 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self {
447 let mut pin = Flex::new(pin); 484 let mut pin = Flex::new(pin);
@@ -455,6 +492,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
455 Self { pin } 492 Self { pin }
456 } 493 }
457 494
495 /// Type-erase (degrade) this pin into an `AnyPin`.
496 ///
497 /// This converts pin singletons (`PA5`, `PB6`, ...), which
498 /// are all different types, into the same type. It is useful for
499 /// creating arrays of pins, or avoiding generics.
458 #[inline] 500 #[inline]
459 pub fn degrade(self) -> Output<'d, AnyPin> { 501 pub fn degrade(self) -> Output<'d, AnyPin> {
460 Output { 502 Output {
@@ -462,17 +504,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
462 } 504 }
463 } 505 }
464 506
507 /// Get whether the pin input level is high.
465 #[inline] 508 #[inline]
466 pub fn is_high(&mut self) -> bool { 509 pub fn is_high(&mut self) -> bool {
467 !self.pin.is_low() 510 !self.pin.is_low()
468 } 511 }
469 512
513 /// Get whether the pin input level is low.
470 #[inline] 514 #[inline]
471 pub fn is_low(&mut self) -> bool { 515 pub fn is_low(&mut self) -> bool {
472 self.pin.is_low() 516 self.pin.is_low()
473 } 517 }
474 518
475 /// Returns current pin level 519 /// Get the current pin input level.
476 #[inline] 520 #[inline]
477 pub fn get_level(&mut self) -> Level { 521 pub fn get_level(&mut self) -> Level {
478 self.pin.get_level() 522 self.pin.get_level()
@@ -496,19 +540,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
496 self.pin.set_level(level); 540 self.pin.set_level(level);
497 } 541 }
498 542
499 /// Is the output pin set as high? 543 /// Get whether the output level is set to high.
500 #[inline] 544 #[inline]
501 pub fn is_set_high(&mut self) -> bool { 545 pub fn is_set_high(&mut self) -> bool {
502 self.pin.is_set_high() 546 self.pin.is_set_high()
503 } 547 }
504 548
505 /// Is the output pin set as low? 549 /// Get whether the output level is set to low.
506 #[inline] 550 #[inline]
507 pub fn is_set_low(&mut self) -> bool { 551 pub fn is_set_low(&mut self) -> bool {
508 self.pin.is_set_low() 552 self.pin.is_set_low()
509 } 553 }
510 554
511 /// What level output is set to 555 /// Get the current output level.
512 #[inline] 556 #[inline]
513 pub fn get_output_level(&mut self) -> Level { 557 pub fn get_output_level(&mut self) -> Level {
514 self.pin.get_output_level() 558 self.pin.get_output_level()
@@ -521,8 +565,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
521 } 565 }
522} 566}
523 567
568/// GPIO output type
524pub enum OutputType { 569pub enum OutputType {
570 /// Drive the pin both high or low.
525 PushPull, 571 PushPull,
572 /// Drive the pin low, or don't drive it at all if the output level is high.
526 OpenDrain, 573 OpenDrain,
527} 574}
528 575
@@ -535,6 +582,7 @@ impl From<OutputType> for sealed::AFType {
535 } 582 }
536} 583}
537 584
585#[allow(missing_docs)]
538pub(crate) mod sealed { 586pub(crate) mod sealed {
539 use super::*; 587 use super::*;
540 588
@@ -542,8 +590,11 @@ pub(crate) mod sealed {
542 #[derive(Debug, Copy, Clone)] 590 #[derive(Debug, Copy, Clone)]
543 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 591 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
544 pub enum AFType { 592 pub enum AFType {
593 /// Input
545 Input, 594 Input,
595 /// Output, drive the pin both high or low.
546 OutputPushPull, 596 OutputPushPull,
597 /// Output, drive the pin low, or don't drive it at all if the output level is high.
547 OutputOpenDrain, 598 OutputOpenDrain,
548 } 599 }
549 600
@@ -686,7 +737,11 @@ pub(crate) mod sealed {
686 } 737 }
687} 738}
688 739
740/// GPIO pin trait.
689pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 741pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
742 /// EXTI channel assigned to this pin.
743 ///
744 /// For example, PC4 uses EXTI4.
690 #[cfg(feature = "exti")] 745 #[cfg(feature = "exti")]
691 type ExtiChannel: crate::exti::Channel; 746 type ExtiChannel: crate::exti::Channel;
692 747
@@ -702,7 +757,11 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
702 self._port() 757 self._port()
703 } 758 }
704 759
705 /// Convert from concrete pin type PX_XX to type erased `AnyPin`. 760 /// Type-erase (degrade) this pin into an `AnyPin`.
761 ///
762 /// This converts pin singletons (`PA5`, `PB6`, ...), which
763 /// are all different types, into the same type. It is useful for
764 /// creating arrays of pins, or avoiding generics.
706 #[inline] 765 #[inline]
707 fn degrade(self) -> AnyPin { 766 fn degrade(self) -> AnyPin {
708 AnyPin { 767 AnyPin {
@@ -711,12 +770,15 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
711 } 770 }
712} 771}
713 772
714// Type-erased GPIO pin 773/// Type-erased GPIO pin
715pub struct AnyPin { 774pub struct AnyPin {
716 pin_port: u8, 775 pin_port: u8,
717} 776}
718 777
719impl AnyPin { 778impl AnyPin {
779 /// Unsafely create an `AnyPin` from a pin+port number.
780 ///
781 /// `pin_port` is `port_num * 16 + pin_num`, where `port_num` is 0 for port `A`, 1 for port `B`, etc...
720 #[inline] 782 #[inline]
721 pub unsafe fn steal(pin_port: u8) -> Self { 783 pub unsafe fn steal(pin_port: u8) -> Self {
722 Self { pin_port } 784 Self { pin_port }
@@ -727,6 +789,8 @@ impl AnyPin {
727 self.pin_port / 16 789 self.pin_port / 16
728 } 790 }
729 791
792 /// Get the GPIO register block for this pin.
793 #[cfg(feature = "unstable-pac")]
730 #[inline] 794 #[inline]
731 pub fn block(&self) -> gpio::Gpio { 795 pub fn block(&self) -> gpio::Gpio {
732 pac::GPIO(self._port() as _) 796 pac::GPIO(self._port() as _)
@@ -1072,6 +1136,7 @@ impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Flex<'d, T> {
1072 } 1136 }
1073} 1137}
1074 1138
1139/// Low-level GPIO manipulation.
1075#[cfg(feature = "unstable-pac")] 1140#[cfg(feature = "unstable-pac")]
1076pub mod low_level { 1141pub mod low_level {
1077 pub use super::sealed::*; 1142 pub use super::sealed::*;
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 17096d48c..faefaabbc 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -1,3 +1,5 @@
1//! High Resolution Timer (HRTIM)
2
1mod traits; 3mod traits;
2 4
3use core::marker::PhantomData; 5use core::marker::PhantomData;
@@ -13,38 +15,42 @@ use crate::rcc::get_freqs;
13use crate::time::Hertz; 15use crate::time::Hertz;
14use crate::Peripheral; 16use crate::Peripheral;
15 17
16pub enum Source { 18/// HRTIM burst controller instance.
17 Master,
18 ChA,
19 ChB,
20 ChC,
21 ChD,
22 ChE,
23 #[cfg(hrtim_v2)]
24 ChF,
25}
26
27pub struct BurstController<T: Instance> { 19pub struct BurstController<T: Instance> {
28 phantom: PhantomData<T>, 20 phantom: PhantomData<T>,
29} 21}
22
23/// HRTIM master instance.
30pub struct Master<T: Instance> { 24pub struct Master<T: Instance> {
31 phantom: PhantomData<T>, 25 phantom: PhantomData<T>,
32} 26}
27
28/// HRTIM channel A instance.
33pub struct ChA<T: Instance> { 29pub struct ChA<T: Instance> {
34 phantom: PhantomData<T>, 30 phantom: PhantomData<T>,
35} 31}
32
33/// HRTIM channel B instance.
36pub struct ChB<T: Instance> { 34pub struct ChB<T: Instance> {
37 phantom: PhantomData<T>, 35 phantom: PhantomData<T>,
38} 36}
37
38/// HRTIM channel C instance.
39pub struct ChC<T: Instance> { 39pub struct ChC<T: Instance> {
40 phantom: PhantomData<T>, 40 phantom: PhantomData<T>,
41} 41}
42
43/// HRTIM channel D instance.
42pub struct ChD<T: Instance> { 44pub struct ChD<T: Instance> {
43 phantom: PhantomData<T>, 45 phantom: PhantomData<T>,
44} 46}
47
48/// HRTIM channel E instance.
45pub struct ChE<T: Instance> { 49pub struct ChE<T: Instance> {
46 phantom: PhantomData<T>, 50 phantom: PhantomData<T>,
47} 51}
52
53/// HRTIM channel F instance.
48#[cfg(hrtim_v2)] 54#[cfg(hrtim_v2)]
49pub struct ChF<T: Instance> { 55pub struct ChF<T: Instance> {
50 phantom: PhantomData<T>, 56 phantom: PhantomData<T>,
@@ -58,22 +64,26 @@ mod sealed {
58 } 64 }
59} 65}
60 66
67/// Advanced channel instance trait.
61pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {} 68pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
62 69
63pub struct PwmPin<'d, Perip, Channel> { 70/// HRTIM PWM pin.
71pub struct PwmPin<'d, T, C> {
64 _pin: PeripheralRef<'d, AnyPin>, 72 _pin: PeripheralRef<'d, AnyPin>,
65 phantom: PhantomData<(Perip, Channel)>, 73 phantom: PhantomData<(T, C)>,
66} 74}
67 75
68pub struct ComplementaryPwmPin<'d, Perip, Channel> { 76/// HRTIM complementary PWM pin.
77pub struct ComplementaryPwmPin<'d, T, C> {
69 _pin: PeripheralRef<'d, AnyPin>, 78 _pin: PeripheralRef<'d, AnyPin>,
70 phantom: PhantomData<(Perip, Channel)>, 79 phantom: PhantomData<(T, C)>,
71} 80}
72 81
73macro_rules! advanced_channel_impl { 82macro_rules! advanced_channel_impl {
74 ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => { 83 ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
75 impl<'d, Perip: Instance> PwmPin<'d, Perip, $channel<Perip>> { 84 impl<'d, T: Instance> PwmPin<'d, T, $channel<T>> {
76 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { 85 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
86 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
77 into_ref!(pin); 87 into_ref!(pin);
78 critical_section::with(|_| { 88 critical_section::with(|_| {
79 pin.set_low(); 89 pin.set_low();
@@ -88,8 +98,9 @@ macro_rules! advanced_channel_impl {
88 } 98 }
89 } 99 }
90 100
91 impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> { 101 impl<'d, T: Instance> ComplementaryPwmPin<'d, T, $channel<T>> {
92 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { 102 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
103 pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<T>> + 'd) -> Self {
93 into_ref!(pin); 104 into_ref!(pin);
94 critical_section::with(|_| { 105 critical_section::with(|_| {
95 pin.set_low(); 106 pin.set_low();
@@ -124,18 +135,29 @@ advanced_channel_impl!(new_chf, ChF, 5, ChannelFPin, ChannelFComplementaryPin);
124/// Struct used to divide a high resolution timer into multiple channels 135/// Struct used to divide a high resolution timer into multiple channels
125pub struct AdvancedPwm<'d, T: Instance> { 136pub struct AdvancedPwm<'d, T: Instance> {
126 _inner: PeripheralRef<'d, T>, 137 _inner: PeripheralRef<'d, T>,
138 /// Master instance.
127 pub master: Master<T>, 139 pub master: Master<T>,
140 /// Burst controller.
128 pub burst_controller: BurstController<T>, 141 pub burst_controller: BurstController<T>,
142 /// Channel A.
129 pub ch_a: ChA<T>, 143 pub ch_a: ChA<T>,
144 /// Channel B.
130 pub ch_b: ChB<T>, 145 pub ch_b: ChB<T>,
146 /// Channel C.
131 pub ch_c: ChC<T>, 147 pub ch_c: ChC<T>,
148 /// Channel D.
132 pub ch_d: ChD<T>, 149 pub ch_d: ChD<T>,
150 /// Channel E.
133 pub ch_e: ChE<T>, 151 pub ch_e: ChE<T>,
152 /// Channel F.
134 #[cfg(hrtim_v2)] 153 #[cfg(hrtim_v2)]
135 pub ch_f: ChF<T>, 154 pub ch_f: ChF<T>,
136} 155}
137 156
138impl<'d, T: Instance> AdvancedPwm<'d, T> { 157impl<'d, T: Instance> AdvancedPwm<'d, T> {
158 /// Create a new HRTIM driver.
159 ///
160 /// This splits the HRTIM into its constituent parts, which you can then use individually.
139 pub fn new( 161 pub fn new(
140 tim: impl Peripheral<P = T> + 'd, 162 tim: impl Peripheral<P = T> + 'd,
141 _cha: Option<PwmPin<'d, T, ChA<T>>>, 163 _cha: Option<PwmPin<'d, T, ChA<T>>>,
@@ -198,13 +220,7 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
198 } 220 }
199} 221}
200 222
201impl<T: Instance> BurstController<T> { 223/// Fixed-frequency bridge converter driver.
202 pub fn set_source(&mut self, _source: Source) {
203 todo!("burst mode control registers not implemented")
204 }
205}
206
207/// Represents a fixed-frequency bridge converter
208/// 224///
209/// Our implementation of the bridge converter uses a single channel and three compare registers, 225/// Our implementation of the bridge converter uses a single channel and three compare registers,
210/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous 226/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
@@ -223,6 +239,7 @@ pub struct BridgeConverter<T: Instance, C: AdvancedChannel<T>> {
223} 239}
224 240
225impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> { 241impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
242 /// Create a new HRTIM bridge converter driver.
226 pub fn new(_channel: C, frequency: Hertz) -> Self { 243 pub fn new(_channel: C, frequency: Hertz) -> Self {
227 use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect}; 244 use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect};
228 245
@@ -279,14 +296,17 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
279 } 296 }
280 } 297 }
281 298
299 /// Start HRTIM.
282 pub fn start(&mut self) { 300 pub fn start(&mut self) {
283 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true)); 301 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
284 } 302 }
285 303
304 /// Stop HRTIM.
286 pub fn stop(&mut self) { 305 pub fn stop(&mut self) {
287 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false)); 306 T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
288 } 307 }
289 308
309 /// Enable burst mode.
290 pub fn enable_burst_mode(&mut self) { 310 pub fn enable_burst_mode(&mut self) {
291 T::regs().tim(C::raw()).outr().modify(|w| { 311 T::regs().tim(C::raw()).outr().modify(|w| {
292 // Enable Burst Mode 312 // Enable Burst Mode
@@ -299,6 +319,7 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
299 }) 319 })
300 } 320 }
301 321
322 /// Disable burst mode.
302 pub fn disable_burst_mode(&mut self) { 323 pub fn disable_burst_mode(&mut self) {
303 T::regs().tim(C::raw()).outr().modify(|w| { 324 T::regs().tim(C::raw()).outr().modify(|w| {
304 // Disable Burst Mode 325 // Disable Burst Mode
@@ -355,7 +376,7 @@ impl<T: Instance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
355 } 376 }
356} 377}
357 378
358/// Represents a variable-frequency resonant converter 379/// Variable-frequency resonant converter driver.
359/// 380///
360/// This implementation of a resonsant converter is appropriate for a half or full bridge, 381/// This implementation of a resonsant converter is appropriate for a half or full bridge,
361/// but does not include secondary rectification, which is appropriate for applications 382/// but does not include secondary rectification, which is appropriate for applications
@@ -368,6 +389,7 @@ pub struct ResonantConverter<T: Instance, C: AdvancedChannel<T>> {
368} 389}
369 390
370impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> { 391impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
392 /// Create a new variable-frequency resonant converter driver.
371 pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self { 393 pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
372 T::set_channel_frequency(C::raw(), min_frequency); 394 T::set_channel_frequency(C::raw(), min_frequency);
373 395
@@ -406,6 +428,7 @@ impl<T: Instance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
406 T::set_channel_dead_time(C::raw(), value); 428 T::set_channel_dead_time(C::raw(), value);
407 } 429 }
408 430
431 /// Set the timer period.
409 pub fn set_period(&mut self, period: u16) { 432 pub fn set_period(&mut self, period: u16) {
410 assert!(period < self.max_period); 433 assert!(period < self.max_period);
411 assert!(period > self.min_period); 434 assert!(period > self.min_period);
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
index 34a363a1f..cfd31c47c 100644
--- a/embassy-stm32/src/hrtim/traits.rs
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -125,7 +125,6 @@ pub(crate) mod sealed {
125 } 125 }
126 126
127 /// Set the dead time as a proportion of max_duty 127 /// Set the dead time as a proportion of max_duty
128
129 fn set_channel_dead_time(channel: usize, dead_time: u16) { 128 fn set_channel_dead_time(channel: usize, dead_time: u16) {
130 let regs = Self::regs(); 129 let regs = Self::regs();
131 130
@@ -148,13 +147,10 @@ pub(crate) mod sealed {
148 w.set_dtr(dt_val as u16); 147 w.set_dtr(dt_val as u16);
149 }); 148 });
150 } 149 }
151
152 // fn enable_outputs(enable: bool);
153 //
154 // fn enable_channel(&mut self, channel: usize, enable: bool);
155 } 150 }
156} 151}
157 152
153/// HRTIM instance trait.
158pub trait Instance: sealed::Instance + 'static {} 154pub trait Instance: sealed::Instance + 'static {}
159 155
160foreach_interrupt! { 156foreach_interrupt! {
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index d2a50cf7e..2416005b5 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -1,30 +1,180 @@
1//! Inter-Integrated-Circuit (I2C)
1#![macro_use] 2#![macro_use]
2 3
3use core::marker::PhantomData;
4
5use crate::dma::NoDma;
6use crate::interrupt;
7
8#[cfg_attr(i2c_v1, path = "v1.rs")] 4#[cfg_attr(i2c_v1, path = "v1.rs")]
9#[cfg_attr(i2c_v2, path = "v2.rs")] 5#[cfg_attr(i2c_v2, path = "v2.rs")]
10mod _version; 6mod _version;
11pub use _version::*; 7
8use core::future::Future;
9use core::marker::PhantomData;
10
11use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant};
13 15
14use crate::peripherals; 16use crate::dma::NoDma;
17use crate::gpio::sealed::AFType;
18use crate::gpio::Pull;
19use crate::interrupt::typelevel::Interrupt;
20use crate::time::Hertz;
21use crate::{interrupt, peripherals};
15 22
23/// I2C error.
16#[derive(Debug, PartialEq, Eq)] 24#[derive(Debug, PartialEq, Eq)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))] 25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub enum Error { 26pub enum Error {
27 /// Bus error
19 Bus, 28 Bus,
29 /// Arbitration lost
20 Arbitration, 30 Arbitration,
31 /// ACK not received (either to the address or to a data byte)
21 Nack, 32 Nack,
33 /// Timeout
22 Timeout, 34 Timeout,
35 /// CRC error
23 Crc, 36 Crc,
37 /// Overrun error
24 Overrun, 38 Overrun,
39 /// Zero-length transfers are not allowed.
25 ZeroLengthTransfer, 40 ZeroLengthTransfer,
26} 41}
27 42
43/// I2C config
44#[non_exhaustive]
45#[derive(Copy, Clone)]
46pub struct Config {
47 /// Enable internal pullup on SDA.
48 ///
49 /// Using external pullup resistors is recommended for I2C. If you do
50 /// have external pullups you should not enable this.
51 pub sda_pullup: bool,
52 /// Enable internal pullup on SCL.
53 ///
54 /// Using external pullup resistors is recommended for I2C. If you do
55 /// have external pullups you should not enable this.
56 pub scl_pullup: bool,
57 /// Timeout.
58 #[cfg(feature = "time")]
59 pub timeout: embassy_time::Duration,
60}
61
62impl Default for Config {
63 fn default() -> Self {
64 Self {
65 sda_pullup: false,
66 scl_pullup: false,
67 #[cfg(feature = "time")]
68 timeout: embassy_time::Duration::from_millis(1000),
69 }
70 }
71}
72
73/// I2C driver.
74pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
75 _peri: PeripheralRef<'d, T>,
76 #[allow(dead_code)]
77 tx_dma: PeripheralRef<'d, TXDMA>,
78 #[allow(dead_code)]
79 rx_dma: PeripheralRef<'d, RXDMA>,
80 #[cfg(feature = "time")]
81 timeout: Duration,
82}
83
84impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
85 /// Create a new I2C driver.
86 pub fn new(
87 peri: impl Peripheral<P = T> + 'd,
88 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
89 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
90 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
91 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
92 + 'd,
93 tx_dma: impl Peripheral<P = TXDMA> + 'd,
94 rx_dma: impl Peripheral<P = RXDMA> + 'd,
95 freq: Hertz,
96 config: Config,
97 ) -> Self {
98 into_ref!(peri, scl, sda, tx_dma, rx_dma);
99
100 T::enable_and_reset();
101
102 scl.set_as_af_pull(
103 scl.af_num(),
104 AFType::OutputOpenDrain,
105 match config.scl_pullup {
106 true => Pull::Up,
107 false => Pull::None,
108 },
109 );
110 sda.set_as_af_pull(
111 sda.af_num(),
112 AFType::OutputOpenDrain,
113 match config.sda_pullup {
114 true => Pull::Up,
115 false => Pull::None,
116 },
117 );
118
119 unsafe { T::EventInterrupt::enable() };
120 unsafe { T::ErrorInterrupt::enable() };
121
122 let mut this = Self {
123 _peri: peri,
124 tx_dma,
125 rx_dma,
126 #[cfg(feature = "time")]
127 timeout: config.timeout,
128 };
129
130 this.init(freq, config);
131
132 this
133 }
134
135 fn timeout(&self) -> Timeout {
136 Timeout {
137 #[cfg(feature = "time")]
138 deadline: Instant::now() + self.timeout,
139 }
140 }
141}
142
143#[derive(Copy, Clone)]
144struct Timeout {
145 #[cfg(feature = "time")]
146 deadline: Instant,
147}
148
149#[allow(dead_code)]
150impl Timeout {
151 #[inline]
152 fn check(self) -> Result<(), Error> {
153 #[cfg(feature = "time")]
154 if Instant::now() > self.deadline {
155 return Err(Error::Timeout);
156 }
157
158 Ok(())
159 }
160
161 #[inline]
162 fn with<R>(self, fut: impl Future<Output = Result<R, Error>>) -> impl Future<Output = Result<R, Error>> {
163 #[cfg(feature = "time")]
164 {
165 use futures::FutureExt;
166
167 embassy_futures::select::select(embassy_time::Timer::at(self.deadline), fut).map(|r| match r {
168 embassy_futures::select::Either::First(_) => Err(Error::Timeout),
169 embassy_futures::select::Either::Second(r) => r,
170 })
171 }
172
173 #[cfg(not(feature = "time"))]
174 fut
175 }
176}
177
28pub(crate) mod sealed { 178pub(crate) mod sealed {
29 use super::*; 179 use super::*;
30 180
@@ -47,8 +197,11 @@ pub(crate) mod sealed {
47 } 197 }
48} 198}
49 199
200/// I2C peripheral instance
50pub trait Instance: sealed::Instance + 'static { 201pub trait Instance: sealed::Instance + 'static {
202 /// Event interrupt for this instance
51 type EventInterrupt: interrupt::typelevel::Interrupt; 203 type EventInterrupt: interrupt::typelevel::Interrupt;
204 /// Error interrupt for this instance
52 type ErrorInterrupt: interrupt::typelevel::Interrupt; 205 type ErrorInterrupt: interrupt::typelevel::Interrupt;
53} 206}
54 207
@@ -57,7 +210,7 @@ pin_trait!(SdaPin, Instance);
57dma_trait!(RxDma, Instance); 210dma_trait!(RxDma, Instance);
58dma_trait!(TxDma, Instance); 211dma_trait!(TxDma, Instance);
59 212
60/// Interrupt handler. 213/// Event interrupt handler.
61pub struct EventInterruptHandler<T: Instance> { 214pub struct EventInterruptHandler<T: Instance> {
62 _phantom: PhantomData<T>, 215 _phantom: PhantomData<T>,
63} 216}
@@ -68,6 +221,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::EventInterrupt> for EventInte
68 } 221 }
69} 222}
70 223
224/// Error interrupt handler.
71pub struct ErrorInterruptHandler<T: Instance> { 225pub struct ErrorInterruptHandler<T: Instance> {
72 _phantom: PhantomData<T>, 226 _phantom: PhantomData<T>,
73} 227}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index b62ee8246..df5b44c2d 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -1,20 +1,14 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll; 2use core::task::Poll;
4 3
5use embassy_embedded_hal::SetConfig; 4use embassy_embedded_hal::SetConfig;
6use embassy_futures::select::{select, Either}; 5use embassy_futures::select::{select, Either};
7use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
8use embassy_hal_internal::{into_ref, PeripheralRef};
9 7
10use super::*; 8use super::*;
11use crate::dma::{NoDma, Transfer}; 9use crate::dma::Transfer;
12use crate::gpio::sealed::AFType;
13use crate::gpio::Pull;
14use crate::interrupt::typelevel::Interrupt;
15use crate::pac::i2c; 10use crate::pac::i2c;
16use crate::time::Hertz; 11use crate::time::Hertz;
17use crate::{interrupt, Peripheral};
18 12
19pub unsafe fn on_interrupt<T: Instance>() { 13pub unsafe fn on_interrupt<T: Instance>() {
20 let regs = T::regs(); 14 let regs = T::regs();
@@ -30,55 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() {
30 }); 24 });
31} 25}
32 26
33#[non_exhaustive]
34#[derive(Copy, Clone, Default)]
35pub struct Config {
36 pub sda_pullup: bool,
37 pub scl_pullup: bool,
38}
39
40pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
41 phantom: PhantomData<&'d mut T>,
42 #[allow(dead_code)]
43 tx_dma: PeripheralRef<'d, TXDMA>,
44 #[allow(dead_code)]
45 rx_dma: PeripheralRef<'d, RXDMA>,
46}
47
48impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 27impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
49 pub fn new( 28 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
50 _peri: impl Peripheral<P = T> + 'd,
51 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
52 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
53 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
54 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
55 + 'd,
56 tx_dma: impl Peripheral<P = TXDMA> + 'd,
57 rx_dma: impl Peripheral<P = RXDMA> + 'd,
58 freq: Hertz,
59 config: Config,
60 ) -> Self {
61 into_ref!(scl, sda, tx_dma, rx_dma);
62
63 T::enable_and_reset();
64
65 scl.set_as_af_pull(
66 scl.af_num(),
67 AFType::OutputOpenDrain,
68 match config.scl_pullup {
69 true => Pull::Up,
70 false => Pull::None,
71 },
72 );
73 sda.set_as_af_pull(
74 sda.af_num(),
75 AFType::OutputOpenDrain,
76 match config.sda_pullup {
77 true => Pull::Up,
78 false => Pull::None,
79 },
80 );
81
82 T::regs().cr1().modify(|reg| { 29 T::regs().cr1().modify(|reg| {
83 reg.set_pe(false); 30 reg.set_pe(false);
84 //reg.set_anfoff(false); 31 //reg.set_anfoff(false);
@@ -101,15 +48,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
101 T::regs().cr1().modify(|reg| { 48 T::regs().cr1().modify(|reg| {
102 reg.set_pe(true); 49 reg.set_pe(true);
103 }); 50 });
104
105 unsafe { T::EventInterrupt::enable() };
106 unsafe { T::ErrorInterrupt::enable() };
107
108 Self {
109 phantom: PhantomData,
110 tx_dma,
111 rx_dma,
112 }
113 } 51 }
114 52
115 fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> { 53 fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> {
@@ -169,12 +107,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
169 Ok(sr1) 107 Ok(sr1)
170 } 108 }
171 109
172 fn write_bytes( 110 fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout) -> Result<(), Error> {
173 &mut self,
174 addr: u8,
175 bytes: &[u8],
176 check_timeout: impl Fn() -> Result<(), Error>,
177 ) -> Result<(), Error> {
178 // Send a START condition 111 // Send a START condition
179 112
180 T::regs().cr1().modify(|reg| { 113 T::regs().cr1().modify(|reg| {
@@ -183,7 +116,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
183 116
184 // Wait until START condition was generated 117 // Wait until START condition was generated
185 while !Self::check_and_clear_error_flags()?.start() { 118 while !Self::check_and_clear_error_flags()?.start() {
186 check_timeout()?; 119 timeout.check()?;
187 } 120 }
188 121
189 // Also wait until signalled we're master and everything is waiting for us 122 // Also wait until signalled we're master and everything is waiting for us
@@ -193,7 +126,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
193 let sr2 = T::regs().sr2().read(); 126 let sr2 = T::regs().sr2().read();
194 !sr2.msl() && !sr2.busy() 127 !sr2.msl() && !sr2.busy()
195 } { 128 } {
196 check_timeout()?; 129 timeout.check()?;
197 } 130 }
198 131
199 // Set up current address, we're trying to talk to 132 // Set up current address, we're trying to talk to
@@ -203,7 +136,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
203 // Wait for the address to be acknowledged 136 // Wait for the address to be acknowledged
204 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 137 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
205 while !Self::check_and_clear_error_flags()?.addr() { 138 while !Self::check_and_clear_error_flags()?.addr() {
206 check_timeout()?; 139 timeout.check()?;
207 } 140 }
208 141
209 // Clear condition by reading SR2 142 // Clear condition by reading SR2
@@ -211,20 +144,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
211 144
212 // Send bytes 145 // Send bytes
213 for c in bytes { 146 for c in bytes {
214 self.send_byte(*c, &check_timeout)?; 147 self.send_byte(*c, timeout)?;
215 } 148 }
216 149
217 // Fallthrough is success 150 // Fallthrough is success
218 Ok(()) 151 Ok(())
219 } 152 }
220 153
221 fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 154 fn send_byte(&self, byte: u8, timeout: Timeout) -> Result<(), Error> {
222 // Wait until we're ready for sending 155 // Wait until we're ready for sending
223 while { 156 while {
224 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 157 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
225 !Self::check_and_clear_error_flags()?.txe() 158 !Self::check_and_clear_error_flags()?.txe()
226 } { 159 } {
227 check_timeout()?; 160 timeout.check()?;
228 } 161 }
229 162
230 // Push out a byte of data 163 // Push out a byte of data
@@ -235,32 +168,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
235 // Check for any potential error conditions. 168 // Check for any potential error conditions.
236 !Self::check_and_clear_error_flags()?.btf() 169 !Self::check_and_clear_error_flags()?.btf()
237 } { 170 } {
238 check_timeout()?; 171 timeout.check()?;
239 } 172 }
240 173
241 Ok(()) 174 Ok(())
242 } 175 }
243 176
244 fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { 177 fn recv_byte(&self, timeout: Timeout) -> Result<u8, Error> {
245 while { 178 while {
246 // Check for any potential error conditions. 179 // Check for any potential error conditions.
247 Self::check_and_clear_error_flags()?; 180 Self::check_and_clear_error_flags()?;
248 181
249 !T::regs().sr1().read().rxne() 182 !T::regs().sr1().read().rxne()
250 } { 183 } {
251 check_timeout()?; 184 timeout.check()?;
252 } 185 }
253 186
254 let value = T::regs().dr().read().dr(); 187 let value = T::regs().dr().read().dr();
255 Ok(value) 188 Ok(value)
256 } 189 }
257 190
258 pub fn blocking_read_timeout( 191 fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Timeout) -> Result<(), Error> {
259 &mut self,
260 addr: u8,
261 buffer: &mut [u8],
262 check_timeout: impl Fn() -> Result<(), Error>,
263 ) -> Result<(), Error> {
264 if let Some((last, buffer)) = buffer.split_last_mut() { 192 if let Some((last, buffer)) = buffer.split_last_mut() {
265 // Send a START condition and set ACK bit 193 // Send a START condition and set ACK bit
266 T::regs().cr1().modify(|reg| { 194 T::regs().cr1().modify(|reg| {
@@ -270,7 +198,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
270 198
271 // Wait until START condition was generated 199 // Wait until START condition was generated
272 while !Self::check_and_clear_error_flags()?.start() { 200 while !Self::check_and_clear_error_flags()?.start() {
273 check_timeout()?; 201 timeout.check()?;
274 } 202 }
275 203
276 // Also wait until signalled we're master and everything is waiting for us 204 // Also wait until signalled we're master and everything is waiting for us
@@ -278,7 +206,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
278 let sr2 = T::regs().sr2().read(); 206 let sr2 = T::regs().sr2().read();
279 !sr2.msl() && !sr2.busy() 207 !sr2.msl() && !sr2.busy()
280 } { 208 } {
281 check_timeout()?; 209 timeout.check()?;
282 } 210 }
283 211
284 // Set up current address, we're trying to talk to 212 // Set up current address, we're trying to talk to
@@ -287,7 +215,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
287 // Wait until address was sent 215 // Wait until address was sent
288 // Wait for the address to be acknowledged 216 // Wait for the address to be acknowledged
289 while !Self::check_and_clear_error_flags()?.addr() { 217 while !Self::check_and_clear_error_flags()?.addr() {
290 check_timeout()?; 218 timeout.check()?;
291 } 219 }
292 220
293 // Clear condition by reading SR2 221 // Clear condition by reading SR2
@@ -295,7 +223,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
295 223
296 // Receive bytes into buffer 224 // Receive bytes into buffer
297 for c in buffer { 225 for c in buffer {
298 *c = self.recv_byte(&check_timeout)?; 226 *c = self.recv_byte(timeout)?;
299 } 227 }
300 228
301 // Prepare to send NACK then STOP after next byte 229 // Prepare to send NACK then STOP after next byte
@@ -305,11 +233,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
305 }); 233 });
306 234
307 // Receive last byte 235 // Receive last byte
308 *last = self.recv_byte(&check_timeout)?; 236 *last = self.recv_byte(timeout)?;
309 237
310 // Wait for the STOP to be sent. 238 // Wait for the STOP to be sent.
311 while T::regs().cr1().read().stop() { 239 while T::regs().cr1().read().stop() {
312 check_timeout()?; 240 timeout.check()?;
313 } 241 }
314 242
315 // Fallthrough is success 243 // Fallthrough is success
@@ -319,49 +247,37 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
319 } 247 }
320 } 248 }
321 249
250 /// Blocking read.
322 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { 251 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
323 self.blocking_read_timeout(addr, read, || Ok(())) 252 self.blocking_read_timeout(addr, read, self.timeout())
324 } 253 }
325 254
326 pub fn blocking_write_timeout( 255 /// Blocking write.
327 &mut self, 256 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
328 addr: u8, 257 let timeout = self.timeout();
329 write: &[u8], 258
330 check_timeout: impl Fn() -> Result<(), Error>, 259 self.write_bytes(addr, write, timeout)?;
331 ) -> Result<(), Error> {
332 self.write_bytes(addr, write, &check_timeout)?;
333 // Send a STOP condition 260 // Send a STOP condition
334 T::regs().cr1().modify(|reg| reg.set_stop(true)); 261 T::regs().cr1().modify(|reg| reg.set_stop(true));
335 // Wait for STOP condition to transmit. 262 // Wait for STOP condition to transmit.
336 while T::regs().cr1().read().stop() { 263 while T::regs().cr1().read().stop() {
337 check_timeout()?; 264 timeout.check()?;
338 } 265 }
339 266
340 // Fallthrough is success 267 // Fallthrough is success
341 Ok(()) 268 Ok(())
342 } 269 }
343 270
344 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { 271 /// Blocking write, restart, read.
345 self.blocking_write_timeout(addr, write, || Ok(())) 272 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
346 } 273 let timeout = self.timeout();
347 274
348 pub fn blocking_write_read_timeout( 275 self.write_bytes(addr, write, timeout)?;
349 &mut self, 276 self.blocking_read_timeout(addr, read, timeout)?;
350 addr: u8,
351 write: &[u8],
352 read: &mut [u8],
353 check_timeout: impl Fn() -> Result<(), Error>,
354 ) -> Result<(), Error> {
355 self.write_bytes(addr, write, &check_timeout)?;
356 self.blocking_read_timeout(addr, read, &check_timeout)?;
357 277
358 Ok(()) 278 Ok(())
359 } 279 }
360 280
361 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
362 self.blocking_write_read_timeout(addr, write, read, || Ok(()))
363 }
364
365 // Async 281 // Async
366 282
367 #[inline] // pretty sure this should always be inlined 283 #[inline] // pretty sure this should always be inlined
@@ -522,6 +438,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
522 Ok(()) 438 Ok(())
523 } 439 }
524 440
441 /// Write.
525 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 442 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
526 where 443 where
527 TXDMA: crate::i2c::TxDma<T>, 444 TXDMA: crate::i2c::TxDma<T>,
@@ -544,6 +461,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
544 Ok(()) 461 Ok(())
545 } 462 }
546 463
464 /// Read.
547 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 465 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
548 where 466 where
549 RXDMA: crate::i2c::RxDma<T>, 467 RXDMA: crate::i2c::RxDma<T>,
@@ -703,6 +621,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
703 Ok(()) 621 Ok(())
704 } 622 }
705 623
624 /// Write, restart, read.
706 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 625 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
707 where 626 where
708 RXDMA: crate::i2c::RxDma<T>, 627 RXDMA: crate::i2c::RxDma<T>,
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 8c20e1c54..bd3abaac1 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -4,37 +4,13 @@ use core::task::Poll;
4 4
5use embassy_embedded_hal::SetConfig; 5use embassy_embedded_hal::SetConfig;
6use embassy_hal_internal::drop::OnDrop; 6use embassy_hal_internal::drop::OnDrop;
7use embassy_hal_internal::{into_ref, PeripheralRef};
8#[cfg(feature = "time")]
9use embassy_time::{Duration, Instant};
10 7
11use super::*; 8use super::*;
12use crate::dma::{NoDma, Transfer}; 9use crate::dma::Transfer;
13use crate::gpio::sealed::AFType;
14use crate::gpio::Pull;
15use crate::interrupt::typelevel::Interrupt;
16use crate::pac::i2c; 10use crate::pac::i2c;
17use crate::time::Hertz; 11use crate::time::Hertz;
18use crate::{interrupt, Peripheral};
19
20#[cfg(feature = "time")]
21fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
22 let deadline = Instant::now() + timeout;
23 move || {
24 if Instant::now() > deadline {
25 Err(Error::Timeout)
26 } else {
27 Ok(())
28 }
29 }
30}
31
32#[cfg(not(feature = "time"))]
33pub fn no_timeout_fn() -> impl Fn() -> Result<(), Error> {
34 move || Ok(())
35}
36 12
37pub unsafe fn on_interrupt<T: Instance>() { 13pub(crate) unsafe fn on_interrupt<T: Instance>() {
38 let regs = T::regs(); 14 let regs = T::regs();
39 let isr = regs.isr().read(); 15 let isr = regs.isr().read();
40 16
@@ -48,70 +24,8 @@ pub unsafe fn on_interrupt<T: Instance>() {
48 }); 24 });
49} 25}
50 26
51#[non_exhaustive]
52#[derive(Copy, Clone)]
53pub struct Config {
54 pub sda_pullup: bool,
55 pub scl_pullup: bool,
56 #[cfg(feature = "time")]
57 pub transaction_timeout: Duration,
58}
59
60impl Default for Config {
61 fn default() -> Self {
62 Self {
63 sda_pullup: false,
64 scl_pullup: false,
65 #[cfg(feature = "time")]
66 transaction_timeout: Duration::from_millis(100),
67 }
68 }
69}
70
71pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
72 _peri: PeripheralRef<'d, T>,
73 #[allow(dead_code)]
74 tx_dma: PeripheralRef<'d, TXDMA>,
75 #[allow(dead_code)]
76 rx_dma: PeripheralRef<'d, RXDMA>,
77 #[cfg(feature = "time")]
78 timeout: Duration,
79}
80
81impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 27impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
82 pub fn new( 28 pub(crate) fn init(&mut self, freq: Hertz, _config: Config) {
83 peri: impl Peripheral<P = T> + 'd,
84 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
85 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
86 _irq: impl interrupt::typelevel::Binding<T::EventInterrupt, EventInterruptHandler<T>>
87 + interrupt::typelevel::Binding<T::ErrorInterrupt, ErrorInterruptHandler<T>>
88 + 'd,
89 tx_dma: impl Peripheral<P = TXDMA> + 'd,
90 rx_dma: impl Peripheral<P = RXDMA> + 'd,
91 freq: Hertz,
92 config: Config,
93 ) -> Self {
94 into_ref!(peri, scl, sda, tx_dma, rx_dma);
95
96 T::enable_and_reset();
97
98 scl.set_as_af_pull(
99 scl.af_num(),
100 AFType::OutputOpenDrain,
101 match config.scl_pullup {
102 true => Pull::Up,
103 false => Pull::None,
104 },
105 );
106 sda.set_as_af_pull(
107 sda.af_num(),
108 AFType::OutputOpenDrain,
109 match config.sda_pullup {
110 true => Pull::Up,
111 false => Pull::None,
112 },
113 );
114
115 T::regs().cr1().modify(|reg| { 29 T::regs().cr1().modify(|reg| {
116 reg.set_pe(false); 30 reg.set_pe(false);
117 reg.set_anfoff(false); 31 reg.set_anfoff(false);
@@ -130,17 +44,6 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
130 T::regs().cr1().modify(|reg| { 44 T::regs().cr1().modify(|reg| {
131 reg.set_pe(true); 45 reg.set_pe(true);
132 }); 46 });
133
134 unsafe { T::EventInterrupt::enable() };
135 unsafe { T::ErrorInterrupt::enable() };
136
137 Self {
138 _peri: peri,
139 tx_dma,
140 rx_dma,
141 #[cfg(feature = "time")]
142 timeout: config.transaction_timeout,
143 }
144 } 47 }
145 48
146 fn master_stop(&mut self) { 49 fn master_stop(&mut self) {
@@ -153,7 +56,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
153 stop: Stop, 56 stop: Stop,
154 reload: bool, 57 reload: bool,
155 restart: bool, 58 restart: bool,
156 check_timeout: impl Fn() -> Result<(), Error>, 59 timeout: Timeout,
157 ) -> Result<(), Error> { 60 ) -> Result<(), Error> {
158 assert!(length < 256); 61 assert!(length < 256);
159 62
@@ -162,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
162 // automatically. This could be up to 50% of a bus 65 // automatically. This could be up to 50% of a bus
163 // cycle (ie. up to 0.5/freq) 66 // cycle (ie. up to 0.5/freq)
164 while T::regs().cr2().read().start() { 67 while T::regs().cr2().read().start() {
165 check_timeout()?; 68 timeout.check()?;
166 } 69 }
167 } 70 }
168 71
@@ -189,20 +92,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
189 Ok(()) 92 Ok(())
190 } 93 }
191 94
192 fn master_write( 95 fn master_write(address: u8, length: usize, stop: Stop, reload: bool, timeout: Timeout) -> Result<(), Error> {
193 address: u8,
194 length: usize,
195 stop: Stop,
196 reload: bool,
197 check_timeout: impl Fn() -> Result<(), Error>,
198 ) -> Result<(), Error> {
199 assert!(length < 256); 96 assert!(length < 256);
200 97
201 // Wait for any previous address sequence to end 98 // Wait for any previous address sequence to end
202 // automatically. This could be up to 50% of a bus 99 // automatically. This could be up to 50% of a bus
203 // cycle (ie. up to 0.5/freq) 100 // cycle (ie. up to 0.5/freq)
204 while T::regs().cr2().read().start() { 101 while T::regs().cr2().read().start() {
205 check_timeout()?; 102 timeout.check()?;
206 } 103 }
207 104
208 let reload = if reload { 105 let reload = if reload {
@@ -227,15 +124,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
227 Ok(()) 124 Ok(())
228 } 125 }
229 126
230 fn master_continue( 127 fn master_continue(length: usize, reload: bool, timeout: Timeout) -> Result<(), Error> {
231 length: usize,
232 reload: bool,
233 check_timeout: impl Fn() -> Result<(), Error>,
234 ) -> Result<(), Error> {
235 assert!(length < 256 && length > 0); 128 assert!(length < 256 && length > 0);
236 129
237 while !T::regs().isr().read().tcr() { 130 while !T::regs().isr().read().tcr() {
238 check_timeout()?; 131 timeout.check()?;
239 } 132 }
240 133
241 let reload = if reload { 134 let reload = if reload {
@@ -261,7 +154,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
261 } 154 }
262 } 155 }
263 156
264 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 157 fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> {
265 loop { 158 loop {
266 let isr = T::regs().isr().read(); 159 let isr = T::regs().isr().read();
267 if isr.txe() { 160 if isr.txe() {
@@ -278,11 +171,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
278 return Err(Error::Nack); 171 return Err(Error::Nack);
279 } 172 }
280 173
281 check_timeout()?; 174 timeout.check()?;
282 } 175 }
283 } 176 }
284 177
285 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 178 fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> {
286 loop { 179 loop {
287 let isr = T::regs().isr().read(); 180 let isr = T::regs().isr().read();
288 if isr.rxne() { 181 if isr.rxne() {
@@ -299,11 +192,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
299 return Err(Error::Nack); 192 return Err(Error::Nack);
300 } 193 }
301 194
302 check_timeout()?; 195 timeout.check()?;
303 } 196 }
304 } 197 }
305 198
306 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> { 199 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
307 loop { 200 loop {
308 let isr = T::regs().isr().read(); 201 let isr = T::regs().isr().read();
309 if isr.tc() { 202 if isr.tc() {
@@ -320,17 +213,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
320 return Err(Error::Nack); 213 return Err(Error::Nack);
321 } 214 }
322 215
323 check_timeout()?; 216 timeout.check()?;
324 } 217 }
325 } 218 }
326 219
327 fn read_internal( 220 fn read_internal(&mut self, address: u8, read: &mut [u8], restart: bool, timeout: Timeout) -> Result<(), Error> {
328 &mut self,
329 address: u8,
330 read: &mut [u8],
331 restart: bool,
332 check_timeout: impl Fn() -> Result<(), Error>,
333 ) -> Result<(), Error> {
334 let completed_chunks = read.len() / 255; 221 let completed_chunks = read.len() / 255;
335 let total_chunks = if completed_chunks * 255 == read.len() { 222 let total_chunks = if completed_chunks * 255 == read.len() {
336 completed_chunks 223 completed_chunks
@@ -345,17 +232,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
345 Stop::Automatic, 232 Stop::Automatic,
346 last_chunk_idx != 0, 233 last_chunk_idx != 0,
347 restart, 234 restart,
348 &check_timeout, 235 timeout,
349 )?; 236 )?;
350 237
351 for (number, chunk) in read.chunks_mut(255).enumerate() { 238 for (number, chunk) in read.chunks_mut(255).enumerate() {
352 if number != 0 { 239 if number != 0 {
353 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; 240 Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
354 } 241 }
355 242
356 for byte in chunk { 243 for byte in chunk {
357 // Wait until we have received something 244 // Wait until we have received something
358 self.wait_rxne(&check_timeout)?; 245 self.wait_rxne(timeout)?;
359 246
360 *byte = T::regs().rxdr().read().rxdata(); 247 *byte = T::regs().rxdr().read().rxdata();
361 } 248 }
@@ -363,13 +250,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
363 Ok(()) 250 Ok(())
364 } 251 }
365 252
366 fn write_internal( 253 fn write_internal(&mut self, address: u8, write: &[u8], send_stop: bool, timeout: Timeout) -> Result<(), Error> {
367 &mut self,
368 address: u8,
369 write: &[u8],
370 send_stop: bool,
371 check_timeout: impl Fn() -> Result<(), Error>,
372 ) -> Result<(), Error> {
373 let completed_chunks = write.len() / 255; 254 let completed_chunks = write.len() / 255;
374 let total_chunks = if completed_chunks * 255 == write.len() { 255 let total_chunks = if completed_chunks * 255 == write.len() {
375 completed_chunks 256 completed_chunks
@@ -386,7 +267,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
386 write.len().min(255), 267 write.len().min(255),
387 Stop::Software, 268 Stop::Software,
388 last_chunk_idx != 0, 269 last_chunk_idx != 0,
389 &check_timeout, 270 timeout,
390 ) { 271 ) {
391 if send_stop { 272 if send_stop {
392 self.master_stop(); 273 self.master_stop();
@@ -396,14 +277,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
396 277
397 for (number, chunk) in write.chunks(255).enumerate() { 278 for (number, chunk) in write.chunks(255).enumerate() {
398 if number != 0 { 279 if number != 0 {
399 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?; 280 Self::master_continue(chunk.len(), number != last_chunk_idx, timeout)?;
400 } 281 }
401 282
402 for byte in chunk { 283 for byte in chunk {
403 // Wait until we are allowed to send data 284 // Wait until we are allowed to send data
404 // (START has been ACKed or last byte when 285 // (START has been ACKed or last byte when
405 // through) 286 // through)
406 if let Err(err) = self.wait_txe(&check_timeout) { 287 if let Err(err) = self.wait_txe(timeout) {
407 if send_stop { 288 if send_stop {
408 self.master_stop(); 289 self.master_stop();
409 } 290 }
@@ -414,7 +295,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
414 } 295 }
415 } 296 }
416 // Wait until the write finishes 297 // Wait until the write finishes
417 let result = self.wait_tc(&check_timeout); 298 let result = self.wait_tc(timeout);
418 if send_stop { 299 if send_stop {
419 self.master_stop(); 300 self.master_stop();
420 } 301 }
@@ -427,7 +308,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
427 write: &[u8], 308 write: &[u8],
428 first_slice: bool, 309 first_slice: bool,
429 last_slice: bool, 310 last_slice: bool,
430 check_timeout: impl Fn() -> Result<(), Error>, 311 timeout: Timeout,
431 ) -> Result<(), Error> 312 ) -> Result<(), Error>
432 where 313 where
433 TXDMA: crate::i2c::TxDma<T>, 314 TXDMA: crate::i2c::TxDma<T>,
@@ -473,10 +354,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
473 total_len.min(255), 354 total_len.min(255),
474 Stop::Software, 355 Stop::Software,
475 (total_len > 255) || !last_slice, 356 (total_len > 255) || !last_slice,
476 &check_timeout, 357 timeout,
477 )?; 358 )?;
478 } else { 359 } else {
479 Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, &check_timeout)?; 360 Self::master_continue(total_len.min(255), (total_len > 255) || !last_slice, timeout)?;
480 T::regs().cr1().modify(|w| w.set_tcie(true)); 361 T::regs().cr1().modify(|w| w.set_tcie(true));
481 } 362 }
482 } else if !(isr.tcr() || isr.tc()) { 363 } else if !(isr.tcr() || isr.tc()) {
@@ -487,7 +368,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
487 } else { 368 } else {
488 let last_piece = (remaining_len <= 255) && last_slice; 369 let last_piece = (remaining_len <= 255) && last_slice;
489 370
490 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { 371 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
491 return Poll::Ready(Err(e)); 372 return Poll::Ready(Err(e));
492 } 373 }
493 T::regs().cr1().modify(|w| w.set_tcie(true)); 374 T::regs().cr1().modify(|w| w.set_tcie(true));
@@ -502,7 +383,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
502 383
503 if last_slice { 384 if last_slice {
504 // This should be done already 385 // This should be done already
505 self.wait_tc(&check_timeout)?; 386 self.wait_tc(timeout)?;
506 self.master_stop(); 387 self.master_stop();
507 } 388 }
508 389
@@ -516,7 +397,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
516 address: u8, 397 address: u8,
517 buffer: &mut [u8], 398 buffer: &mut [u8],
518 restart: bool, 399 restart: bool,
519 check_timeout: impl Fn() -> Result<(), Error>, 400 timeout: Timeout,
520 ) -> Result<(), Error> 401 ) -> Result<(), Error>
521 where 402 where
522 RXDMA: crate::i2c::RxDma<T>, 403 RXDMA: crate::i2c::RxDma<T>,
@@ -558,7 +439,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
558 Stop::Software, 439 Stop::Software,
559 total_len > 255, 440 total_len > 255,
560 restart, 441 restart,
561 &check_timeout, 442 timeout,
562 )?; 443 )?;
563 } else if !(isr.tcr() || isr.tc()) { 444 } else if !(isr.tcr() || isr.tc()) {
564 // poll_fn was woken without an interrupt present 445 // poll_fn was woken without an interrupt present
@@ -568,7 +449,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
568 } else { 449 } else {
569 let last_piece = remaining_len <= 255; 450 let last_piece = remaining_len <= 255;
570 451
571 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) { 452 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, timeout) {
572 return Poll::Ready(Err(e)); 453 return Poll::Ready(Err(e));
573 } 454 }
574 T::regs().cr1().modify(|w| w.set_tcie(true)); 455 T::regs().cr1().modify(|w| w.set_tcie(true));
@@ -582,7 +463,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
582 dma_transfer.await; 463 dma_transfer.await;
583 464
584 // This should be done already 465 // This should be done already
585 self.wait_tc(&check_timeout)?; 466 self.wait_tc(timeout)?;
586 self.master_stop(); 467 self.master_stop();
587 468
588 drop(on_drop); 469 drop(on_drop);
@@ -592,69 +473,31 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
592 473
593 // ========================= 474 // =========================
594 // Async public API 475 // Async public API
595 #[cfg(feature = "time")]
596 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
597 where
598 TXDMA: crate::i2c::TxDma<T>,
599 {
600 if write.is_empty() {
601 self.write_internal(address, write, true, timeout_fn(self.timeout))
602 } else {
603 embassy_time::with_timeout(
604 self.timeout,
605 self.write_dma_internal(address, write, true, true, timeout_fn(self.timeout)),
606 )
607 .await
608 .unwrap_or(Err(Error::Timeout))
609 }
610 }
611 476
612 #[cfg(not(feature = "time"))] 477 /// Write.
613 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 478 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
614 where 479 where
615 TXDMA: crate::i2c::TxDma<T>, 480 TXDMA: crate::i2c::TxDma<T>,
616 { 481 {
482 let timeout = self.timeout();
617 if write.is_empty() { 483 if write.is_empty() {
618 self.write_internal(address, write, true, no_timeout_fn()) 484 self.write_internal(address, write, true, timeout)
619 } else { 485 } else {
620 self.write_dma_internal(address, write, true, true, no_timeout_fn()) 486 timeout
487 .with(self.write_dma_internal(address, write, true, true, timeout))
621 .await 488 .await
622 } 489 }
623 } 490 }
624 491
625 #[cfg(feature = "time")] 492 /// Write multiple buffers.
493 ///
494 /// The buffers are concatenated in a single write transaction.
626 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> 495 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
627 where 496 where
628 TXDMA: crate::i2c::TxDma<T>, 497 TXDMA: crate::i2c::TxDma<T>,
629 { 498 {
630 if write.is_empty() { 499 let timeout = self.timeout();
631 return Err(Error::ZeroLengthTransfer);
632 }
633 let mut iter = write.iter();
634
635 let mut first = true;
636 let mut current = iter.next();
637 while let Some(c) = current {
638 let next = iter.next();
639 let is_last = next.is_none();
640
641 embassy_time::with_timeout(
642 self.timeout,
643 self.write_dma_internal(address, c, first, is_last, timeout_fn(self.timeout)),
644 )
645 .await
646 .unwrap_or(Err(Error::Timeout))?;
647 first = false;
648 current = next;
649 }
650 Ok(())
651 }
652 500
653 #[cfg(not(feature = "time"))]
654 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
655 where
656 TXDMA: crate::i2c::TxDma<T>,
657 {
658 if write.is_empty() { 501 if write.is_empty() {
659 return Err(Error::ZeroLengthTransfer); 502 return Err(Error::ZeroLengthTransfer);
660 } 503 }
@@ -666,95 +509,49 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
666 let next = iter.next(); 509 let next = iter.next();
667 let is_last = next.is_none(); 510 let is_last = next.is_none();
668 511
669 self.write_dma_internal(address, c, first, is_last, no_timeout_fn()) 512 let fut = self.write_dma_internal(address, c, first, is_last, timeout);
670 .await?; 513 timeout.with(fut).await?;
671 first = false; 514 first = false;
672 current = next; 515 current = next;
673 } 516 }
674 Ok(()) 517 Ok(())
675 } 518 }
676 519
677 #[cfg(feature = "time")] 520 /// Read.
678 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 521 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
679 where 522 where
680 RXDMA: crate::i2c::RxDma<T>, 523 RXDMA: crate::i2c::RxDma<T>,
681 { 524 {
682 if buffer.is_empty() { 525 let timeout = self.timeout();
683 self.read_internal(address, buffer, false, timeout_fn(self.timeout))
684 } else {
685 embassy_time::with_timeout(
686 self.timeout,
687 self.read_dma_internal(address, buffer, false, timeout_fn(self.timeout)),
688 )
689 .await
690 .unwrap_or(Err(Error::Timeout))
691 }
692 }
693 526
694 #[cfg(not(feature = "time"))]
695 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
696 where
697 RXDMA: crate::i2c::RxDma<T>,
698 {
699 if buffer.is_empty() { 527 if buffer.is_empty() {
700 self.read_internal(address, buffer, false, no_timeout_fn()) 528 self.read_internal(address, buffer, false, timeout)
701 } else { 529 } else {
702 self.read_dma_internal(address, buffer, false, no_timeout_fn()).await 530 let fut = self.read_dma_internal(address, buffer, false, timeout);
531 timeout.with(fut).await
703 } 532 }
704 } 533 }
705 534
706 #[cfg(feature = "time")] 535 /// Write, restart, read.
707 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 536 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
708 where 537 where
709 TXDMA: super::TxDma<T>, 538 TXDMA: super::TxDma<T>,
710 RXDMA: super::RxDma<T>, 539 RXDMA: super::RxDma<T>,
711 { 540 {
712 let start_instant = Instant::now(); 541 let timeout = self.timeout();
713 let check_timeout = timeout_fn(self.timeout);
714 if write.is_empty() {
715 self.write_internal(address, write, false, &check_timeout)?;
716 } else {
717 embassy_time::with_timeout(
718 self.timeout,
719 self.write_dma_internal(address, write, true, true, &check_timeout),
720 )
721 .await
722 .unwrap_or(Err(Error::Timeout))?;
723 }
724
725 let time_left_until_timeout = self.timeout - Instant::now().duration_since(start_instant);
726 542
727 if read.is_empty() {
728 self.read_internal(address, read, true, &check_timeout)?;
729 } else {
730 embassy_time::with_timeout(
731 time_left_until_timeout,
732 self.read_dma_internal(address, read, true, &check_timeout),
733 )
734 .await
735 .unwrap_or(Err(Error::Timeout))?;
736 }
737
738 Ok(())
739 }
740
741 #[cfg(not(feature = "time"))]
742 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
743 where
744 TXDMA: super::TxDma<T>,
745 RXDMA: super::RxDma<T>,
746 {
747 let no_timeout = no_timeout_fn();
748 if write.is_empty() { 543 if write.is_empty() {
749 self.write_internal(address, write, false, &no_timeout)?; 544 self.write_internal(address, write, false, timeout)?;
750 } else { 545 } else {
751 self.write_dma_internal(address, write, true, true, &no_timeout).await?; 546 let fut = self.write_dma_internal(address, write, true, true, timeout);
547 timeout.with(fut).await?;
752 } 548 }
753 549
754 if read.is_empty() { 550 if read.is_empty() {
755 self.read_internal(address, read, true, &no_timeout)?; 551 self.read_internal(address, read, true, timeout)?;
756 } else { 552 } else {
757 self.read_dma_internal(address, read, true, &no_timeout).await?; 553 let fut = self.read_dma_internal(address, read, true, timeout);
554 timeout.with(fut).await?;
758 } 555 }
759 556
760 Ok(()) 557 Ok(())
@@ -763,105 +560,35 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
763 // ========================= 560 // =========================
764 // Blocking public API 561 // Blocking public API
765 562
766 #[cfg(feature = "time")] 563 /// Blocking read.
767 pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
768 self.read_internal(address, read, false, timeout_fn(timeout))
769 // Automatic Stop
770 }
771
772 #[cfg(not(feature = "time"))]
773 pub fn blocking_read_timeout(
774 &mut self,
775 address: u8,
776 read: &mut [u8],
777 check_timeout: impl Fn() -> Result<(), Error>,
778 ) -> Result<(), Error> {
779 self.read_internal(address, read, false, check_timeout)
780 // Automatic Stop
781 }
782
783 #[cfg(feature = "time")]
784 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
785 self.blocking_read_timeout(address, read, self.timeout)
786 }
787
788 #[cfg(not(feature = "time"))]
789 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 564 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
790 self.blocking_read_timeout(address, read, || Ok(())) 565 self.read_internal(address, read, false, self.timeout())
791 }
792
793 #[cfg(feature = "time")]
794 pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> {
795 self.write_internal(address, write, true, timeout_fn(timeout))
796 }
797
798 #[cfg(not(feature = "time"))]
799 pub fn blocking_write_timeout(
800 &mut self,
801 address: u8,
802 write: &[u8],
803 check_timeout: impl Fn() -> Result<(), Error>,
804 ) -> Result<(), Error> {
805 self.write_internal(address, write, true, check_timeout)
806 }
807
808 #[cfg(feature = "time")]
809 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
810 self.blocking_write_timeout(address, write, self.timeout)
811 }
812
813 #[cfg(not(feature = "time"))]
814 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
815 self.blocking_write_timeout(address, write, || Ok(()))
816 }
817
818 #[cfg(feature = "time")]
819 pub fn blocking_write_read_timeout(
820 &mut self,
821 address: u8,
822 write: &[u8],
823 read: &mut [u8],
824 timeout: Duration,
825 ) -> Result<(), Error> {
826 let check_timeout = timeout_fn(timeout);
827 self.write_internal(address, write, false, &check_timeout)?;
828 self.read_internal(address, read, true, &check_timeout)
829 // Automatic Stop 566 // Automatic Stop
830 } 567 }
831 568
832 #[cfg(not(feature = "time"))] 569 /// Blocking write.
833 pub fn blocking_write_read_timeout( 570 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
834 &mut self, 571 self.write_internal(address, write, true, self.timeout())
835 address: u8,
836 write: &[u8],
837 read: &mut [u8],
838 check_timeout: impl Fn() -> Result<(), Error>,
839 ) -> Result<(), Error> {
840 self.write_internal(address, write, false, &check_timeout)?;
841 self.read_internal(address, read, true, &check_timeout)
842 // Automatic Stop
843 }
844
845 #[cfg(feature = "time")]
846 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
847 self.blocking_write_read_timeout(address, write, read, self.timeout)
848 } 572 }
849 573
850 #[cfg(not(feature = "time"))] 574 /// Blocking write, restart, read.
851 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 575 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
852 self.blocking_write_read_timeout(address, write, read, || Ok(())) 576 let timeout = self.timeout();
577 self.write_internal(address, write, false, timeout)?;
578 self.read_internal(address, read, true, timeout)
579 // Automatic Stop
853 } 580 }
854 581
855 fn blocking_write_vectored_with_timeout( 582 /// Blocking write multiple buffers.
856 &mut self, 583 ///
857 address: u8, 584 /// The buffers are concatenated in a single write transaction.
858 write: &[&[u8]], 585 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
859 check_timeout: impl Fn() -> Result<(), Error>,
860 ) -> Result<(), Error> {
861 if write.is_empty() { 586 if write.is_empty() {
862 return Err(Error::ZeroLengthTransfer); 587 return Err(Error::ZeroLengthTransfer);
863 } 588 }
864 589
590 let timeout = self.timeout();
591
865 let first_length = write[0].len(); 592 let first_length = write[0].len();
866 let last_slice_index = write.len() - 1; 593 let last_slice_index = write.len() - 1;
867 594
@@ -870,7 +597,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
870 first_length.min(255), 597 first_length.min(255),
871 Stop::Software, 598 Stop::Software,
872 (first_length > 255) || (last_slice_index != 0), 599 (first_length > 255) || (last_slice_index != 0),
873 &check_timeout, 600 timeout,
874 ) { 601 ) {
875 self.master_stop(); 602 self.master_stop();
876 return Err(err); 603 return Err(err);
@@ -890,7 +617,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
890 if let Err(err) = Self::master_continue( 617 if let Err(err) = Self::master_continue(
891 slice_len.min(255), 618 slice_len.min(255),
892 (idx != last_slice_index) || (slice_len > 255), 619 (idx != last_slice_index) || (slice_len > 255),
893 &check_timeout, 620 timeout,
894 ) { 621 ) {
895 self.master_stop(); 622 self.master_stop();
896 return Err(err); 623 return Err(err);
@@ -902,7 +629,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
902 if let Err(err) = Self::master_continue( 629 if let Err(err) = Self::master_continue(
903 chunk.len(), 630 chunk.len(),
904 (number != last_chunk_idx) || (idx != last_slice_index), 631 (number != last_chunk_idx) || (idx != last_slice_index),
905 &check_timeout, 632 timeout,
906 ) { 633 ) {
907 self.master_stop(); 634 self.master_stop();
908 return Err(err); 635 return Err(err);
@@ -913,7 +640,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
913 // Wait until we are allowed to send data 640 // Wait until we are allowed to send data
914 // (START has been ACKed or last byte when 641 // (START has been ACKed or last byte when
915 // through) 642 // through)
916 if let Err(err) = self.wait_txe(&check_timeout) { 643 if let Err(err) = self.wait_txe(timeout) {
917 self.master_stop(); 644 self.master_stop();
918 return Err(err); 645 return Err(err);
919 } 646 }
@@ -925,41 +652,10 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
925 } 652 }
926 } 653 }
927 // Wait until the write finishes 654 // Wait until the write finishes
928 let result = self.wait_tc(&check_timeout); 655 let result = self.wait_tc(timeout);
929 self.master_stop(); 656 self.master_stop();
930 result 657 result
931 } 658 }
932
933 #[cfg(feature = "time")]
934 pub fn blocking_write_vectored_timeout(
935 &mut self,
936 address: u8,
937 write: &[&[u8]],
938 timeout: Duration,
939 ) -> Result<(), Error> {
940 let check_timeout = timeout_fn(timeout);
941 self.blocking_write_vectored_with_timeout(address, write, check_timeout)
942 }
943
944 #[cfg(not(feature = "time"))]
945 pub fn blocking_write_vectored_timeout(
946 &mut self,
947 address: u8,
948 write: &[&[u8]],
949 check_timeout: impl Fn() -> Result<(), Error>,
950 ) -> Result<(), Error> {
951 self.blocking_write_vectored_with_timeout(address, write, check_timeout)
952 }
953
954 #[cfg(feature = "time")]
955 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
956 self.blocking_write_vectored_timeout(address, write, self.timeout)
957 }
958
959 #[cfg(not(feature = "time"))]
960 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
961 self.blocking_write_vectored_timeout(address, write, || Ok(()))
962 }
963} 659}
964 660
965impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { 661impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 67d40c479..1f85c0bc5 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -1,3 +1,4 @@
1//! Inter-IC Sound (I2S)
1use embassy_hal_internal::into_ref; 2use embassy_hal_internal::into_ref;
2 3
3use crate::gpio::sealed::{AFType, Pin as _}; 4use crate::gpio::sealed::{AFType, Pin as _};
@@ -8,30 +9,42 @@ use crate::spi::{Config as SpiConfig, *};
8use crate::time::Hertz; 9use crate::time::Hertz;
9use crate::{Peripheral, PeripheralRef}; 10use crate::{Peripheral, PeripheralRef};
10 11
12/// I2S mode
11#[derive(Copy, Clone)] 13#[derive(Copy, Clone)]
12pub enum Mode { 14pub enum Mode {
15 /// Master mode
13 Master, 16 Master,
17 /// Slave mode
14 Slave, 18 Slave,
15} 19}
16 20
21/// I2S function
17#[derive(Copy, Clone)] 22#[derive(Copy, Clone)]
18pub enum Function { 23pub enum Function {
24 /// Transmit audio data
19 Transmit, 25 Transmit,
26 /// Receive audio data
20 Receive, 27 Receive,
21} 28}
22 29
30/// I2C standard
23#[derive(Copy, Clone)] 31#[derive(Copy, Clone)]
24pub enum Standard { 32pub enum Standard {
33 /// Philips
25 Philips, 34 Philips,
35 /// Most significant bit first.
26 MsbFirst, 36 MsbFirst,
37 /// Least significant bit first.
27 LsbFirst, 38 LsbFirst,
39 /// PCM with long sync.
28 PcmLongSync, 40 PcmLongSync,
41 /// PCM with short sync.
29 PcmShortSync, 42 PcmShortSync,
30} 43}
31 44
32impl Standard { 45impl Standard {
33 #[cfg(any(spi_v1, spi_f1))] 46 #[cfg(any(spi_v1, spi_f1))]
34 pub const fn i2sstd(&self) -> vals::I2sstd { 47 const fn i2sstd(&self) -> vals::I2sstd {
35 match self { 48 match self {
36 Standard::Philips => vals::I2sstd::PHILIPS, 49 Standard::Philips => vals::I2sstd::PHILIPS,
37 Standard::MsbFirst => vals::I2sstd::MSB, 50 Standard::MsbFirst => vals::I2sstd::MSB,
@@ -42,7 +55,7 @@ impl Standard {
42 } 55 }
43 56
44 #[cfg(any(spi_v1, spi_f1))] 57 #[cfg(any(spi_v1, spi_f1))]
45 pub const fn pcmsync(&self) -> vals::Pcmsync { 58 const fn pcmsync(&self) -> vals::Pcmsync {
46 match self { 59 match self {
47 Standard::PcmLongSync => vals::Pcmsync::LONG, 60 Standard::PcmLongSync => vals::Pcmsync::LONG,
48 _ => vals::Pcmsync::SHORT, 61 _ => vals::Pcmsync::SHORT,
@@ -50,6 +63,7 @@ impl Standard {
50 } 63 }
51} 64}
52 65
66/// I2S data format.
53#[derive(Copy, Clone)] 67#[derive(Copy, Clone)]
54pub enum Format { 68pub enum Format {
55 /// 16 bit data length on 16 bit wide channel 69 /// 16 bit data length on 16 bit wide channel
@@ -64,7 +78,7 @@ pub enum Format {
64 78
65impl Format { 79impl Format {
66 #[cfg(any(spi_v1, spi_f1))] 80 #[cfg(any(spi_v1, spi_f1))]
67 pub const fn datlen(&self) -> vals::Datlen { 81 const fn datlen(&self) -> vals::Datlen {
68 match self { 82 match self {
69 Format::Data16Channel16 => vals::Datlen::SIXTEENBIT, 83 Format::Data16Channel16 => vals::Datlen::SIXTEENBIT,
70 Format::Data16Channel32 => vals::Datlen::SIXTEENBIT, 84 Format::Data16Channel32 => vals::Datlen::SIXTEENBIT,
@@ -74,7 +88,7 @@ impl Format {
74 } 88 }
75 89
76 #[cfg(any(spi_v1, spi_f1))] 90 #[cfg(any(spi_v1, spi_f1))]
77 pub const fn chlen(&self) -> vals::Chlen { 91 const fn chlen(&self) -> vals::Chlen {
78 match self { 92 match self {
79 Format::Data16Channel16 => vals::Chlen::SIXTEENBIT, 93 Format::Data16Channel16 => vals::Chlen::SIXTEENBIT,
80 Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT, 94 Format::Data16Channel32 => vals::Chlen::THIRTYTWOBIT,
@@ -84,15 +98,18 @@ impl Format {
84 } 98 }
85} 99}
86 100
101/// Clock polarity
87#[derive(Copy, Clone)] 102#[derive(Copy, Clone)]
88pub enum ClockPolarity { 103pub enum ClockPolarity {
104 /// Low on idle.
89 IdleLow, 105 IdleLow,
106 /// High on idle.
90 IdleHigh, 107 IdleHigh,
91} 108}
92 109
93impl ClockPolarity { 110impl ClockPolarity {
94 #[cfg(any(spi_v1, spi_f1))] 111 #[cfg(any(spi_v1, spi_f1))]
95 pub const fn ckpol(&self) -> vals::Ckpol { 112 const fn ckpol(&self) -> vals::Ckpol {
96 match self { 113 match self {
97 ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH, 114 ClockPolarity::IdleHigh => vals::Ckpol::IDLEHIGH,
98 ClockPolarity::IdleLow => vals::Ckpol::IDLELOW, 115 ClockPolarity::IdleLow => vals::Ckpol::IDLELOW,
@@ -109,11 +126,17 @@ impl ClockPolarity {
109#[non_exhaustive] 126#[non_exhaustive]
110#[derive(Copy, Clone)] 127#[derive(Copy, Clone)]
111pub struct Config { 128pub struct Config {
129 /// Mode
112 pub mode: Mode, 130 pub mode: Mode,
131 /// Function (transmit, receive)
113 pub function: Function, 132 pub function: Function,
133 /// Which I2S standard to use.
114 pub standard: Standard, 134 pub standard: Standard,
135 /// Data format.
115 pub format: Format, 136 pub format: Format,
137 /// Clock polarity.
116 pub clock_polarity: ClockPolarity, 138 pub clock_polarity: ClockPolarity,
139 /// True to eanble master clock output from this instance.
117 pub master_clock: bool, 140 pub master_clock: bool,
118} 141}
119 142
@@ -130,6 +153,7 @@ impl Default for Config {
130 } 153 }
131} 154}
132 155
156/// I2S driver.
133pub struct I2S<'d, T: Instance, Tx, Rx> { 157pub struct I2S<'d, T: Instance, Tx, Rx> {
134 _peri: Spi<'d, T, Tx, Rx>, 158 _peri: Spi<'d, T, Tx, Rx>,
135 sd: Option<PeripheralRef<'d, AnyPin>>, 159 sd: Option<PeripheralRef<'d, AnyPin>>,
@@ -242,6 +266,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
242 } 266 }
243 } 267 }
244 268
269 /// Write audio data.
245 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> 270 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
246 where 271 where
247 Tx: TxDma<T>, 272 Tx: TxDma<T>,
@@ -249,6 +274,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
249 self._peri.write(data).await 274 self._peri.write(data).await
250 } 275 }
251 276
277 /// Read audio data.
252 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> 278 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
253 where 279 where
254 Tx: TxDma<T>, 280 Tx: TxDma<T>,
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 4006dee19..663a7f59d 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -1,3 +1,5 @@
1//! Inter-Process Communication Controller (IPCC)
2
1use core::future::poll_fn; 3use core::future::poll_fn;
2use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
3use core::task::Poll; 5use core::task::Poll;
@@ -41,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive
41 } 43 }
42} 44}
43 45
46/// TX interrupt handler.
44pub struct TransmitInterruptHandler {} 47pub struct TransmitInterruptHandler {}
45 48
46impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler { 49impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler {
@@ -72,6 +75,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for Transmi
72 } 75 }
73} 76}
74 77
78/// IPCC config.
75#[non_exhaustive] 79#[non_exhaustive]
76#[derive(Clone, Copy, Default)] 80#[derive(Clone, Copy, Default)]
77pub struct Config { 81pub struct Config {
@@ -79,6 +83,8 @@ pub struct Config {
79 // reserved for future use 83 // reserved for future use
80} 84}
81 85
86/// Channel.
87#[allow(missing_docs)]
82#[derive(Debug, Clone, Copy)] 88#[derive(Debug, Clone, Copy)]
83#[repr(C)] 89#[repr(C)]
84pub enum IpccChannel { 90pub enum IpccChannel {
@@ -90,9 +96,11 @@ pub enum IpccChannel {
90 Channel6 = 5, 96 Channel6 = 5,
91} 97}
92 98
99/// IPCC driver.
93pub struct Ipcc; 100pub struct Ipcc;
94 101
95impl Ipcc { 102impl Ipcc {
103 /// Enable IPCC.
96 pub fn enable(_config: Config) { 104 pub fn enable(_config: Config) {
97 IPCC::enable_and_reset(); 105 IPCC::enable_and_reset();
98 IPCC::set_cpu2(true); 106 IPCC::set_cpu2(true);
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 5d9b4e6a0..207f7ed8f 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -1,5 +1,6 @@
1#![cfg_attr(not(test), no_std)] 1#![cfg_attr(not(test), no_std)]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![warn(missing_docs)]
3 4
4//! ## Feature flags 5//! ## Feature flags
5#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] 6#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
@@ -79,6 +80,7 @@ pub(crate) mod _generated {
79 #![allow(dead_code)] 80 #![allow(dead_code)]
80 #![allow(unused_imports)] 81 #![allow(unused_imports)]
81 #![allow(non_snake_case)] 82 #![allow(non_snake_case)]
83 #![allow(missing_docs)]
82 84
83 include!(concat!(env!("OUT_DIR"), "/_generated.rs")); 85 include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
84} 86}
@@ -149,15 +151,33 @@ use crate::interrupt::Priority;
149pub use crate::pac::NVIC_PRIO_BITS; 151pub use crate::pac::NVIC_PRIO_BITS;
150use crate::rcc::sealed::RccPeripheral; 152use crate::rcc::sealed::RccPeripheral;
151 153
154/// `embassy-stm32` global configuration.
152#[non_exhaustive] 155#[non_exhaustive]
153pub struct Config { 156pub struct Config {
157 /// RCC config.
154 pub rcc: rcc::Config, 158 pub rcc: rcc::Config,
159
160 /// Enable debug during sleep.
161 ///
162 /// May incrase power consumption. Defaults to true.
155 #[cfg(dbgmcu)] 163 #[cfg(dbgmcu)]
156 pub enable_debug_during_sleep: bool, 164 pub enable_debug_during_sleep: bool,
165
166 /// BDMA interrupt priority.
167 ///
168 /// Defaults to P0 (highest).
157 #[cfg(bdma)] 169 #[cfg(bdma)]
158 pub bdma_interrupt_priority: Priority, 170 pub bdma_interrupt_priority: Priority,
171
172 /// DMA interrupt priority.
173 ///
174 /// Defaults to P0 (highest).
159 #[cfg(dma)] 175 #[cfg(dma)]
160 pub dma_interrupt_priority: Priority, 176 pub dma_interrupt_priority: Priority,
177
178 /// GPDMA interrupt priority.
179 ///
180 /// Defaults to P0 (highest).
161 #[cfg(gpdma)] 181 #[cfg(gpdma)]
162 pub gpdma_interrupt_priority: Priority, 182 pub gpdma_interrupt_priority: Priority,
163} 183}
@@ -178,7 +198,11 @@ impl Default for Config {
178 } 198 }
179} 199}
180 200
181/// Initialize embassy. 201/// Initialize the `embassy-stm32` HAL with the provided configuration.
202///
203/// This returns the peripheral singletons that can be used for creating drivers.
204///
205/// This should only be called once at startup, otherwise it panics.
182pub fn init(config: Config) -> Peripherals { 206pub fn init(config: Config) -> Peripherals {
183 critical_section::with(|cs| { 207 critical_section::with(|cs| {
184 let p = Peripherals::take_with_cs(cs); 208 let p = Peripherals::take_with_cs(cs);
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 20d8f9045..4fab8dae4 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -1,50 +1,54 @@
1/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating 1//! Low-power support.
2/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which 2//!
3/// can use knowledge of which peripherals are currently blocked upon to transparently and safely 3//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
4/// enter such low-power modes (currently, only `STOP2`) when idle. 4//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
5/// 5//! can use knowledge of which peripherals are currently blocked upon to transparently and safely
6/// The executor determines which peripherals are active by their RCC state; consequently, 6//! enter such low-power modes (currently, only `STOP2`) when idle.
7/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few 7//!
8/// exceptions to this rule: 8//! The executor determines which peripherals are active by their RCC state; consequently,
9/// 9//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few
10/// * `GPIO` 10//! exceptions to this rule:
11/// * `RCC` 11//!
12/// 12//! * `GPIO`
13/// Since entering and leaving low-power modes typically incurs a significant latency, the 13//! * `RCC`
14/// low-power executor will only attempt to enter when the next timer event is at least 14//!
15/// [`time_driver::MIN_STOP_PAUSE`] in the future. 15//! Since entering and leaving low-power modes typically incurs a significant latency, the
16/// 16//! low-power executor will only attempt to enter when the next timer event is at least
17/// Currently there is no macro analogous to `embassy_executor::main` for this executor; 17//! [`time_driver::MIN_STOP_PAUSE`] in the future.
18/// consequently one must define their entrypoint manually. Moveover, you must relinquish control 18//!
19/// of the `RTC` peripheral to the executor. This will typically look like 19//! Currently there is no macro analogous to `embassy_executor::main` for this executor;
20/// 20//! consequently one must define their entrypoint manually. Moveover, you must relinquish control
21/// ```rust,no_run 21//! of the `RTC` peripheral to the executor. This will typically look like
22/// use embassy_executor::Spawner; 22//!
23/// use embassy_stm32::low_power::Executor; 23//! ```rust,no_run
24/// use embassy_stm32::rtc::{Rtc, RtcConfig}; 24//! use embassy_executor::Spawner;
25/// use static_cell::make_static; 25//! use embassy_stm32::low_power::Executor;
26/// 26//! use embassy_stm32::rtc::{Rtc, RtcConfig};
27/// #[cortex_m_rt::entry] 27//! use static_cell::StaticCell;
28/// fn main() -> ! { 28//!
29/// Executor::take().run(|spawner| { 29//! #[cortex_m_rt::entry]
30/// unwrap!(spawner.spawn(async_main(spawner))); 30//! fn main() -> ! {
31/// }); 31//! Executor::take().run(|spawner| {
32/// } 32//! unwrap!(spawner.spawn(async_main(spawner)));
33/// 33//! });
34/// #[embassy_executor::task] 34//! }
35/// async fn async_main(spawner: Spawner) { 35//!
36/// // initialize the platform... 36//! #[embassy_executor::task]
37/// let mut config = embassy_stm32::Config::default(); 37//! async fn async_main(spawner: Spawner) {
38/// let p = embassy_stm32::init(config); 38//! // initialize the platform...
39/// 39//! let mut config = embassy_stm32::Config::default();
40/// // give the RTC to the executor... 40//! let p = embassy_stm32::init(config);
41/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 41//!
42/// let rtc = make_static!(rtc); 42//! // give the RTC to the executor...
43/// embassy_stm32::low_power::stop_with_rtc(rtc); 43//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
44/// 44//! static RTC: StaticCell<Rtc> = StaticCell::new();
45/// // your application here... 45//! let rtc = RTC.init(rtc);
46/// } 46//! embassy_stm32::low_power::stop_with_rtc(rtc);
47/// ``` 47//!
48//! // your application here...
49//! }
50//! ```
51
48use core::arch::asm; 52use core::arch::asm;
49use core::marker::PhantomData; 53use core::marker::PhantomData;
50use core::sync::atomic::{compiler_fence, Ordering}; 54use core::sync::atomic::{compiler_fence, Ordering};
@@ -64,6 +68,7 @@ static mut EXECUTOR: Option<Executor> = None;
64foreach_interrupt! { 68foreach_interrupt! {
65 (RTC, rtc, $block:ident, WKUP, $irq:ident) => { 69 (RTC, rtc, $block:ident, WKUP, $irq:ident) => {
66 #[interrupt] 70 #[interrupt]
71 #[allow(non_snake_case)]
67 unsafe fn $irq() { 72 unsafe fn $irq() {
68 EXECUTOR.as_mut().unwrap().on_wakeup_irq(); 73 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
69 } 74 }
@@ -75,10 +80,15 @@ pub(crate) unsafe fn on_wakeup_irq() {
75 EXECUTOR.as_mut().unwrap().on_wakeup_irq(); 80 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
76} 81}
77 82
83/// Configure STOP mode with RTC.
78pub fn stop_with_rtc(rtc: &'static Rtc) { 84pub fn stop_with_rtc(rtc: &'static Rtc) {
79 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) 85 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
80} 86}
81 87
88/// Get whether the core is ready to enter the given stop mode.
89///
90/// This will return false if some peripheral driver is in use that
91/// prevents entering the given stop mode.
82pub fn stop_ready(stop_mode: StopMode) -> bool { 92pub fn stop_ready(stop_mode: StopMode) -> bool {
83 match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() { 93 match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
84 Some(StopMode::Stop2) => true, 94 Some(StopMode::Stop2) => true,
@@ -87,10 +97,13 @@ pub fn stop_ready(stop_mode: StopMode) -> bool {
87 } 97 }
88} 98}
89 99
100/// Available stop modes.
90#[non_exhaustive] 101#[non_exhaustive]
91#[derive(PartialEq)] 102#[derive(PartialEq)]
92pub enum StopMode { 103pub enum StopMode {
104 /// STOP 1
93 Stop1, 105 Stop1,
106 /// STOP 2
94 Stop2, 107 Stop2,
95} 108}
96 109
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index e1eb031d1..df8a78bcc 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -1,9 +1,12 @@
1//! Operational Amplifier (OPAMP)
1#![macro_use] 2#![macro_use]
2 3
3use embassy_hal_internal::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
4 5
5use crate::Peripheral; 6use crate::Peripheral;
6 7
8/// Gain
9#[allow(missing_docs)]
7#[derive(Clone, Copy)] 10#[derive(Clone, Copy)]
8pub enum OpAmpGain { 11pub enum OpAmpGain {
9 Mul1, 12 Mul1,
@@ -13,6 +16,8 @@ pub enum OpAmpGain {
13 Mul16, 16 Mul16,
14} 17}
15 18
19/// Speed
20#[allow(missing_docs)]
16#[derive(Clone, Copy)] 21#[derive(Clone, Copy)]
17pub enum OpAmpSpeed { 22pub enum OpAmpSpeed {
18 Normal, 23 Normal,
@@ -180,6 +185,7 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
180 } 185 }
181} 186}
182 187
188/// Opamp instance trait.
183pub trait Instance: sealed::Instance + 'static {} 189pub trait Instance: sealed::Instance + 'static {}
184 190
185pub(crate) mod sealed { 191pub(crate) mod sealed {
@@ -198,8 +204,11 @@ pub(crate) mod sealed {
198 pub trait OutputPin<T: Instance> {} 204 pub trait OutputPin<T: Instance> {}
199} 205}
200 206
207/// Non-inverting pin trait.
201pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} 208pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
209/// Inverting pin trait.
202pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} 210pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
211/// Output pin trait.
203pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} 212pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {}
204 213
205macro_rules! impl_opamp_external_output { 214macro_rules! impl_opamp_external_output {
diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs
index 0412d991a..ecade9b1a 100644
--- a/embassy-stm32/src/qspi/enums.rs
+++ b/embassy-stm32/src/qspi/enums.rs
@@ -1,3 +1,5 @@
1//! Enums used in QSPI configuration.
2
1#[allow(dead_code)] 3#[allow(dead_code)]
2#[derive(Copy, Clone)] 4#[derive(Copy, Clone)]
3pub(crate) enum QspiMode { 5pub(crate) enum QspiMode {
@@ -18,12 +20,17 @@ impl Into<u8> for QspiMode {
18 } 20 }
19} 21}
20 22
23/// QSPI lane width
21#[allow(dead_code)] 24#[allow(dead_code)]
22#[derive(Copy, Clone)] 25#[derive(Copy, Clone)]
23pub enum QspiWidth { 26pub enum QspiWidth {
27 /// None
24 NONE, 28 NONE,
29 /// Single lane
25 SING, 30 SING,
31 /// Dual lanes
26 DUAL, 32 DUAL,
33 /// Quad lanes
27 QUAD, 34 QUAD,
28} 35}
29 36
@@ -38,10 +45,13 @@ impl Into<u8> for QspiWidth {
38 } 45 }
39} 46}
40 47
48/// Flash bank selection
41#[allow(dead_code)] 49#[allow(dead_code)]
42#[derive(Copy, Clone)] 50#[derive(Copy, Clone)]
43pub enum FlashSelection { 51pub enum FlashSelection {
52 /// Bank 1
44 Flash1, 53 Flash1,
54 /// Bank 2
45 Flash2, 55 Flash2,
46} 56}
47 57
@@ -54,6 +64,8 @@ impl Into<bool> for FlashSelection {
54 } 64 }
55} 65}
56 66
67/// QSPI memory size.
68#[allow(missing_docs)]
57#[derive(Copy, Clone)] 69#[derive(Copy, Clone)]
58pub enum MemorySize { 70pub enum MemorySize {
59 _1KiB, 71 _1KiB,
@@ -113,11 +125,16 @@ impl Into<u8> for MemorySize {
113 } 125 }
114} 126}
115 127
128/// QSPI Address size
116#[derive(Copy, Clone)] 129#[derive(Copy, Clone)]
117pub enum AddressSize { 130pub enum AddressSize {
131 /// 8-bit address
118 _8Bit, 132 _8Bit,
133 /// 16-bit address
119 _16Bit, 134 _16Bit,
135 /// 24-bit address
120 _24bit, 136 _24bit,
137 /// 32-bit address
121 _32bit, 138 _32bit,
122} 139}
123 140
@@ -132,8 +149,10 @@ impl Into<u8> for AddressSize {
132 } 149 }
133} 150}
134 151
152/// Time the Chip Select line stays high.
153#[allow(missing_docs)]
135#[derive(Copy, Clone)] 154#[derive(Copy, Clone)]
136pub enum ChipSelectHightTime { 155pub enum ChipSelectHighTime {
137 _1Cycle, 156 _1Cycle,
138 _2Cycle, 157 _2Cycle,
139 _3Cycle, 158 _3Cycle,
@@ -144,21 +163,23 @@ pub enum ChipSelectHightTime {
144 _8Cycle, 163 _8Cycle,
145} 164}
146 165
147impl Into<u8> for ChipSelectHightTime { 166impl Into<u8> for ChipSelectHighTime {
148 fn into(self) -> u8 { 167 fn into(self) -> u8 {
149 match self { 168 match self {
150 ChipSelectHightTime::_1Cycle => 0, 169 ChipSelectHighTime::_1Cycle => 0,
151 ChipSelectHightTime::_2Cycle => 1, 170 ChipSelectHighTime::_2Cycle => 1,
152 ChipSelectHightTime::_3Cycle => 2, 171 ChipSelectHighTime::_3Cycle => 2,
153 ChipSelectHightTime::_4Cycle => 3, 172 ChipSelectHighTime::_4Cycle => 3,
154 ChipSelectHightTime::_5Cycle => 4, 173 ChipSelectHighTime::_5Cycle => 4,
155 ChipSelectHightTime::_6Cycle => 5, 174 ChipSelectHighTime::_6Cycle => 5,
156 ChipSelectHightTime::_7Cycle => 6, 175 ChipSelectHighTime::_7Cycle => 6,
157 ChipSelectHightTime::_8Cycle => 7, 176 ChipSelectHighTime::_8Cycle => 7,
158 } 177 }
159 } 178 }
160} 179}
161 180
181/// FIFO threshold.
182#[allow(missing_docs)]
162#[derive(Copy, Clone)] 183#[derive(Copy, Clone)]
163pub enum FIFOThresholdLevel { 184pub enum FIFOThresholdLevel {
164 _1Bytes, 185 _1Bytes,
@@ -234,6 +255,8 @@ impl Into<u8> for FIFOThresholdLevel {
234 } 255 }
235} 256}
236 257
258/// Dummy cycle count
259#[allow(missing_docs)]
237#[derive(Copy, Clone)] 260#[derive(Copy, Clone)]
238pub enum DummyCycles { 261pub enum DummyCycles {
239 _0, 262 _0,
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 1153455c7..8a709a89e 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -1,3 +1,5 @@
1//! Quad Serial Peripheral Interface (QSPI)
2
1#![macro_use] 3#![macro_use]
2 4
3pub mod enums; 5pub mod enums;
@@ -12,6 +14,7 @@ use crate::pac::quadspi::Quadspi as Regs;
12use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
13use crate::{peripherals, Peripheral}; 15use crate::{peripherals, Peripheral};
14 16
17/// QSPI transfer configuration.
15pub struct TransferConfig { 18pub struct TransferConfig {
16 /// Instraction width (IMODE) 19 /// Instraction width (IMODE)
17 pub iwidth: QspiWidth, 20 pub iwidth: QspiWidth,
@@ -43,6 +46,7 @@ impl Default for TransferConfig {
43 } 46 }
44} 47}
45 48
49/// QSPI driver configuration.
46pub struct Config { 50pub struct Config {
47 /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. 51 /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
48 /// If you need other value the whose predefined use `Other` variant. 52 /// If you need other value the whose predefined use `Other` variant.
@@ -54,7 +58,7 @@ pub struct Config {
54 /// Number of bytes to trigger FIFO threshold flag. 58 /// Number of bytes to trigger FIFO threshold flag.
55 pub fifo_threshold: FIFOThresholdLevel, 59 pub fifo_threshold: FIFOThresholdLevel,
56 /// Minimum number of cycles that chip select must be high between issued commands 60 /// Minimum number of cycles that chip select must be high between issued commands
57 pub cs_high_time: ChipSelectHightTime, 61 pub cs_high_time: ChipSelectHighTime,
58} 62}
59 63
60impl Default for Config { 64impl Default for Config {
@@ -64,11 +68,12 @@ impl Default for Config {
64 address_size: AddressSize::_24bit, 68 address_size: AddressSize::_24bit,
65 prescaler: 128, 69 prescaler: 128,
66 fifo_threshold: FIFOThresholdLevel::_17Bytes, 70 fifo_threshold: FIFOThresholdLevel::_17Bytes,
67 cs_high_time: ChipSelectHightTime::_5Cycle, 71 cs_high_time: ChipSelectHighTime::_5Cycle,
68 } 72 }
69 } 73 }
70} 74}
71 75
76/// QSPI driver.
72#[allow(dead_code)] 77#[allow(dead_code)]
73pub struct Qspi<'d, T: Instance, Dma> { 78pub struct Qspi<'d, T: Instance, Dma> {
74 _peri: PeripheralRef<'d, T>, 79 _peri: PeripheralRef<'d, T>,
@@ -83,6 +88,7 @@ pub struct Qspi<'d, T: Instance, Dma> {
83} 88}
84 89
85impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { 90impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
91 /// Create a new QSPI driver for bank 1.
86 pub fn new_bk1( 92 pub fn new_bk1(
87 peri: impl Peripheral<P = T> + 'd, 93 peri: impl Peripheral<P = T> + 'd,
88 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd, 94 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
@@ -123,6 +129,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
123 ) 129 )
124 } 130 }
125 131
132 /// Create a new QSPI driver for bank 2.
126 pub fn new_bk2( 133 pub fn new_bk2(
127 peri: impl Peripheral<P = T> + 'd, 134 peri: impl Peripheral<P = T> + 'd,
128 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd, 135 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
@@ -221,6 +228,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
221 } 228 }
222 } 229 }
223 230
231 /// Do a QSPI command.
224 pub fn command(&mut self, transaction: TransferConfig) { 232 pub fn command(&mut self, transaction: TransferConfig) {
225 #[cfg(not(stm32h7))] 233 #[cfg(not(stm32h7))]
226 T::REGS.cr().modify(|v| v.set_dmaen(false)); 234 T::REGS.cr().modify(|v| v.set_dmaen(false));
@@ -230,6 +238,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
230 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 238 T::REGS.fcr().modify(|v| v.set_ctcf(true));
231 } 239 }
232 240
241 /// Blocking read data.
233 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { 242 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
234 #[cfg(not(stm32h7))] 243 #[cfg(not(stm32h7))]
235 T::REGS.cr().modify(|v| v.set_dmaen(false)); 244 T::REGS.cr().modify(|v| v.set_dmaen(false));
@@ -254,6 +263,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
254 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 263 T::REGS.fcr().modify(|v| v.set_ctcf(true));
255 } 264 }
256 265
266 /// Blocking write data.
257 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { 267 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
258 // STM32H7 does not have dmaen 268 // STM32H7 does not have dmaen
259 #[cfg(not(stm32h7))] 269 #[cfg(not(stm32h7))]
@@ -276,6 +286,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
276 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 286 T::REGS.fcr().modify(|v| v.set_ctcf(true));
277 } 287 }
278 288
289 /// Blocking read data, using DMA.
279 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) 290 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
280 where 291 where
281 Dma: QuadDma<T>, 292 Dma: QuadDma<T>,
@@ -308,6 +319,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
308 transfer.blocking_wait(); 319 transfer.blocking_wait();
309 } 320 }
310 321
322 /// Blocking write data, using DMA.
311 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) 323 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
312 where 324 where
313 Dma: QuadDma<T>, 325 Dma: QuadDma<T>,
@@ -377,6 +389,7 @@ pub(crate) mod sealed {
377 } 389 }
378} 390}
379 391
392/// QSPI instance trait.
380pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 393pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
381 394
382pin_trait!(SckPin, Instance); 395pin_trait!(SckPin, Instance);
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index dc829a9ad..04a51110c 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -1,4 +1,7 @@
1//! Reset and Clock Control (RCC)
2
1#![macro_use] 3#![macro_use]
4#![allow(missing_docs)] // TODO
2 5
3use core::mem::MaybeUninit; 6use core::mem::MaybeUninit;
4 7
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 5e6922e9b..ca641f352 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -1,3 +1,4 @@
1//! Random Number Generator (RNG)
1#![macro_use] 2#![macro_use]
2 3
3use core::future::poll_fn; 4use core::future::poll_fn;
@@ -13,13 +14,19 @@ use crate::{interrupt, pac, peripherals, Peripheral};
13 14
14static RNG_WAKER: AtomicWaker = AtomicWaker::new(); 15static RNG_WAKER: AtomicWaker = AtomicWaker::new();
15 16
17/// RNG error
16#[derive(Debug, PartialEq, Eq)] 18#[derive(Debug, PartialEq, Eq)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))] 19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub enum Error { 20pub enum Error {
21 /// Seed error.
19 SeedError, 22 SeedError,
23 /// Clock error. Double-check the RCC configuration,
24 /// see the Reference Manual for details on restrictions
25 /// on RNG clocks.
20 ClockError, 26 ClockError,
21} 27}
22 28
29/// RNG interrupt handler.
23pub struct InterruptHandler<T: Instance> { 30pub struct InterruptHandler<T: Instance> {
24 _phantom: PhantomData<T>, 31 _phantom: PhantomData<T>,
25} 32}
@@ -34,11 +41,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
34 } 41 }
35} 42}
36 43
44/// RNG driver.
37pub struct Rng<'d, T: Instance> { 45pub struct Rng<'d, T: Instance> {
38 _inner: PeripheralRef<'d, T>, 46 _inner: PeripheralRef<'d, T>,
39} 47}
40 48
41impl<'d, T: Instance> Rng<'d, T> { 49impl<'d, T: Instance> Rng<'d, T> {
50 /// Create a new RNG driver.
42 pub fn new( 51 pub fn new(
43 inner: impl Peripheral<P = T> + 'd, 52 inner: impl Peripheral<P = T> + 'd,
44 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 53 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -54,6 +63,7 @@ impl<'d, T: Instance> Rng<'d, T> {
54 random 63 random
55 } 64 }
56 65
66 /// Reset the RNG.
57 #[cfg(rng_v1)] 67 #[cfg(rng_v1)]
58 pub fn reset(&mut self) { 68 pub fn reset(&mut self) {
59 T::regs().cr().write(|reg| { 69 T::regs().cr().write(|reg| {
@@ -70,6 +80,7 @@ impl<'d, T: Instance> Rng<'d, T> {
70 let _ = self.next_u32(); 80 let _ = self.next_u32();
71 } 81 }
72 82
83 /// Reset the RNG.
73 #[cfg(not(rng_v1))] 84 #[cfg(not(rng_v1))]
74 pub fn reset(&mut self) { 85 pub fn reset(&mut self) {
75 T::regs().cr().write(|reg| { 86 T::regs().cr().write(|reg| {
@@ -106,7 +117,8 @@ impl<'d, T: Instance> Rng<'d, T> {
106 while T::regs().cr().read().condrst() {} 117 while T::regs().cr().read().condrst() {}
107 } 118 }
108 119
109 pub fn recover_seed_error(&mut self) -> () { 120 /// Try to recover from a seed error.
121 pub fn recover_seed_error(&mut self) {
110 self.reset(); 122 self.reset();
111 // reset should also clear the SEIS flag 123 // reset should also clear the SEIS flag
112 if T::regs().sr().read().seis() { 124 if T::regs().sr().read().seis() {
@@ -117,6 +129,7 @@ impl<'d, T: Instance> Rng<'d, T> {
117 while T::regs().sr().read().secs() {} 129 while T::regs().sr().read().secs() {}
118 } 130 }
119 131
132 /// Fill the given slice with random values.
120 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 133 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
121 for chunk in dest.chunks_mut(4) { 134 for chunk in dest.chunks_mut(4) {
122 let mut bits = T::regs().sr().read(); 135 let mut bits = T::regs().sr().read();
@@ -217,7 +230,9 @@ pub(crate) mod sealed {
217 } 230 }
218} 231}
219 232
233/// RNG instance trait.
220pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send { 234pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
235 /// Interrupt for this RNG instance.
221 type Interrupt: interrupt::typelevel::Interrupt; 236 type Interrupt: interrupt::typelevel::Interrupt;
222} 237}
223 238
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index f4e86dd87..ef92fa4bb 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -104,45 +104,51 @@ pub struct DateTime {
104} 104}
105 105
106impl DateTime { 106impl DateTime {
107 /// Get the year (0..=4095)
107 pub const fn year(&self) -> u16 { 108 pub const fn year(&self) -> u16 {
108 self.year 109 self.year
109 } 110 }
110 111
112 /// Get the month (1..=12, 1 is January)
111 pub const fn month(&self) -> u8 { 113 pub const fn month(&self) -> u8 {
112 self.month 114 self.month
113 } 115 }
114 116
117 /// Get the day (1..=31)
115 pub const fn day(&self) -> u8 { 118 pub const fn day(&self) -> u8 {
116 self.day 119 self.day
117 } 120 }
118 121
122 /// Get the day of week
119 pub const fn day_of_week(&self) -> DayOfWeek { 123 pub const fn day_of_week(&self) -> DayOfWeek {
120 self.day_of_week 124 self.day_of_week
121 } 125 }
122 126
127 /// Get the hour (0..=23)
123 pub const fn hour(&self) -> u8 { 128 pub const fn hour(&self) -> u8 {
124 self.hour 129 self.hour
125 } 130 }
126 131
132 /// Get the minute (0..=59)
127 pub const fn minute(&self) -> u8 { 133 pub const fn minute(&self) -> u8 {
128 self.minute 134 self.minute
129 } 135 }
130 136
137 /// Get the second (0..=59)
131 pub const fn second(&self) -> u8 { 138 pub const fn second(&self) -> u8 {
132 self.second 139 self.second
133 } 140 }
134 141
142 /// Create a new DateTime with the given information.
135 pub fn from( 143 pub fn from(
136 year: u16, 144 year: u16,
137 month: u8, 145 month: u8,
138 day: u8, 146 day: u8,
139 day_of_week: u8, 147 day_of_week: DayOfWeek,
140 hour: u8, 148 hour: u8,
141 minute: u8, 149 minute: u8,
142 second: u8, 150 second: u8,
143 ) -> Result<Self, Error> { 151 ) -> Result<Self, Error> {
144 let day_of_week = day_of_week_from_u8(day_of_week)?;
145
146 if year > 4095 { 152 if year > 4095 {
147 Err(Error::InvalidYear) 153 Err(Error::InvalidYear)
148 } else if month < 1 || month > 12 { 154 } else if month < 1 || month > 12 {
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index b4315f535..40cd752a2 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -1,4 +1,4 @@
1//! RTC peripheral abstraction 1//! Real Time Clock (RTC)
2mod datetime; 2mod datetime;
3 3
4#[cfg(feature = "low-power")] 4#[cfg(feature = "low-power")]
@@ -9,9 +9,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9#[cfg(feature = "low-power")] 9#[cfg(feature = "low-power")]
10use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11 11
12use self::datetime::day_of_week_to_u8;
13#[cfg(not(rtc_v2f2))] 12#[cfg(not(rtc_v2f2))]
14use self::datetime::RtcInstant; 13use self::datetime::RtcInstant;
14use self::datetime::{day_of_week_from_u8, day_of_week_to_u8};
15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
16use crate::pac::rtc::regs::{Dr, Tr}; 16use crate::pac::rtc::regs::{Dr, Tr};
17use crate::time::Hertz; 17use crate::time::Hertz;
@@ -102,7 +102,7 @@ pub enum RtcError {
102 NotRunning, 102 NotRunning,
103} 103}
104 104
105pub struct RtcTimeProvider { 105pub(crate) struct RtcTimeProvider {
106 _private: (), 106 _private: (),
107} 107}
108 108
@@ -127,10 +127,10 @@ impl RtcTimeProvider {
127 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 127 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
128 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 128 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
129 129
130 let weekday = dr.wdu(); 130 let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?;
131 let day = bcd2_to_byte((dr.dt(), dr.du())); 131 let day = bcd2_to_byte((dr.dt(), dr.du()));
132 let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); 132 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
133 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; 133 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
134 134
135 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) 135 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
136 }) 136 })
@@ -163,7 +163,7 @@ impl RtcTimeProvider {
163 } 163 }
164} 164}
165 165
166/// RTC Abstraction 166/// RTC driver.
167pub struct Rtc { 167pub struct Rtc {
168 #[cfg(feature = "low-power")] 168 #[cfg(feature = "low-power")]
169 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, 169 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
@@ -171,6 +171,7 @@ pub struct Rtc {
171 _private: (), 171 _private: (),
172} 172}
173 173
174/// RTC configuration.
174#[non_exhaustive] 175#[non_exhaustive]
175#[derive(Copy, Clone, PartialEq)] 176#[derive(Copy, Clone, PartialEq)]
176pub struct RtcConfig { 177pub struct RtcConfig {
@@ -188,6 +189,7 @@ impl Default for RtcConfig {
188 } 189 }
189} 190}
190 191
192/// Calibration cycle period.
191#[derive(Copy, Clone, Debug, PartialEq)] 193#[derive(Copy, Clone, Debug, PartialEq)]
192#[repr(u8)] 194#[repr(u8)]
193pub enum RtcCalibrationCyclePeriod { 195pub enum RtcCalibrationCyclePeriod {
@@ -206,6 +208,7 @@ impl Default for RtcCalibrationCyclePeriod {
206} 208}
207 209
208impl Rtc { 210impl Rtc {
211 /// Create a new RTC instance.
209 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 212 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
210 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 213 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
211 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); 214 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
@@ -240,7 +243,7 @@ impl Rtc {
240 } 243 }
241 244
242 /// Acquire a [`RtcTimeProvider`] instance. 245 /// Acquire a [`RtcTimeProvider`] instance.
243 pub const fn time_provider(&self) -> RtcTimeProvider { 246 pub(crate) const fn time_provider(&self) -> RtcTimeProvider {
244 RtcTimeProvider { _private: () } 247 RtcTimeProvider { _private: () }
245 } 248 }
246 249
@@ -258,7 +261,7 @@ impl Rtc {
258 let (dt, du) = byte_to_bcd2(t.day() as u8); 261 let (dt, du) = byte_to_bcd2(t.day() as u8);
259 let (mt, mu) = byte_to_bcd2(t.month() as u8); 262 let (mt, mu) = byte_to_bcd2(t.month() as u8);
260 let yr = t.year() as u16; 263 let yr = t.year() as u16;
261 let yr_offset = (yr - 1970_u16) as u8; 264 let yr_offset = (yr - 2000_u16) as u8;
262 let (yt, yu) = byte_to_bcd2(yr_offset); 265 let (yt, yu) = byte_to_bcd2(yr_offset);
263 266
264 use crate::pac::rtc::vals::Ampm; 267 use crate::pac::rtc::vals::Ampm;
@@ -315,6 +318,7 @@ impl Rtc {
315 }) 318 })
316 } 319 }
317 320
321 /// Number of backup registers of this instance.
318 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; 322 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
319 323
320 /// Read content of the backup register. 324 /// Read content of the backup register.
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index a16d38af1..ef8802184 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -1,8 +1,11 @@
1//! Serial Audio Interface (SAI)
1#![macro_use] 2#![macro_use]
2 3
3use embassy_embedded_hal::SetConfig; 4use core::marker::PhantomData;
5
4use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
5 7
8use self::sealed::WhichSubBlock;
6pub use crate::dma::word; 9pub use crate::dma::word;
7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 10use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
8use crate::gpio::sealed::{AFType, Pin as _}; 11use crate::gpio::sealed::{AFType, Pin as _};
@@ -11,48 +14,32 @@ use crate::pac::sai::{vals, Sai as Regs};
11use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
12use crate::{peripherals, Peripheral}; 15use crate::{peripherals, Peripheral};
13 16
17/// SAI error
14#[derive(Debug, PartialEq, Eq)] 18#[derive(Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))] 19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error { 20pub enum Error {
21 /// `write` called on a SAI in receive mode.
17 NotATransmitter, 22 NotATransmitter,
23 /// `read` called on a SAI in transmit mode.
18 NotAReceiver, 24 NotAReceiver,
19 OverrunError, 25 /// Overrun
26 Overrun,
20} 27}
21 28
22impl From<ringbuffer::OverrunError> for Error { 29impl From<ringbuffer::OverrunError> for Error {
23 fn from(_: ringbuffer::OverrunError) -> Self { 30 fn from(_: ringbuffer::OverrunError) -> Self {
24 Self::OverrunError 31 Self::Overrun
25 } 32 }
26} 33}
27 34
35/// Master/slave mode.
28#[derive(Copy, Clone)] 36#[derive(Copy, Clone)]
29pub enum SyncBlock { 37#[allow(missing_docs)]
30 None,
31 Sai1BlockA,
32 Sai1BlockB,
33 Sai2BlockA,
34 Sai2BlockB,
35}
36
37#[derive(Copy, Clone)]
38pub enum SyncIn {
39 None,
40 ChannelZero,
41 ChannelOne,
42}
43
44#[derive(Copy, Clone)]
45pub enum Mode { 38pub enum Mode {
46 Master, 39 Master,
47 Slave, 40 Slave,
48} 41}
49 42
50#[derive(Copy, Clone)]
51pub enum TxRx {
52 Transmitter,
53 Receiver,
54}
55
56impl Mode { 43impl Mode {
57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 44 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode { 45 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
@@ -69,7 +56,17 @@ impl Mode {
69 } 56 }
70} 57}
71 58
59/// Direction: transmit or receive
72#[derive(Copy, Clone)] 60#[derive(Copy, Clone)]
61#[allow(missing_docs)]
62pub enum TxRx {
63 Transmitter,
64 Receiver,
65}
66
67/// Data slot size.
68#[derive(Copy, Clone)]
69#[allow(missing_docs)]
73pub enum SlotSize { 70pub enum SlotSize {
74 DataSize, 71 DataSize,
75 /// 16 bit data length on 16 bit wide channel 72 /// 16 bit data length on 16 bit wide channel
@@ -80,7 +77,7 @@ pub enum SlotSize {
80 77
81impl SlotSize { 78impl SlotSize {
82 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 79 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
83 pub const fn slotsz(&self) -> vals::Slotsz { 80 const fn slotsz(&self) -> vals::Slotsz {
84 match self { 81 match self {
85 SlotSize::DataSize => vals::Slotsz::DATASIZE, 82 SlotSize::DataSize => vals::Slotsz::DATASIZE,
86 SlotSize::Channel16 => vals::Slotsz::BIT16, 83 SlotSize::Channel16 => vals::Slotsz::BIT16,
@@ -89,7 +86,9 @@ impl SlotSize {
89 } 86 }
90} 87}
91 88
89/// Data size.
92#[derive(Copy, Clone)] 90#[derive(Copy, Clone)]
91#[allow(missing_docs)]
93pub enum DataSize { 92pub enum DataSize {
94 Data8, 93 Data8,
95 Data10, 94 Data10,
@@ -101,7 +100,7 @@ pub enum DataSize {
101 100
102impl DataSize { 101impl DataSize {
103 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 102 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
104 pub const fn ds(&self) -> vals::Ds { 103 const fn ds(&self) -> vals::Ds {
105 match self { 104 match self {
106 DataSize::Data8 => vals::Ds::BIT8, 105 DataSize::Data8 => vals::Ds::BIT8,
107 DataSize::Data10 => vals::Ds::BIT10, 106 DataSize::Data10 => vals::Ds::BIT10,
@@ -113,7 +112,9 @@ impl DataSize {
113 } 112 }
114} 113}
115 114
115/// FIFO threshold level.
116#[derive(Copy, Clone)] 116#[derive(Copy, Clone)]
117#[allow(missing_docs)]
117pub enum FifoThreshold { 118pub enum FifoThreshold {
118 Empty, 119 Empty,
119 Quarter, 120 Quarter,
@@ -124,7 +125,7 @@ pub enum FifoThreshold {
124 125
125impl FifoThreshold { 126impl FifoThreshold {
126 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 127 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
127 pub const fn fth(&self) -> vals::Fth { 128 const fn fth(&self) -> vals::Fth {
128 match self { 129 match self {
129 FifoThreshold::Empty => vals::Fth::EMPTY, 130 FifoThreshold::Empty => vals::Fth::EMPTY,
130 FifoThreshold::Quarter => vals::Fth::QUARTER1, 131 FifoThreshold::Quarter => vals::Fth::QUARTER1,
@@ -135,38 +136,9 @@ impl FifoThreshold {
135 } 136 }
136} 137}
137 138
139/// Output value on mute.
138#[derive(Copy, Clone)] 140#[derive(Copy, Clone)]
139pub enum FifoLevel { 141#[allow(missing_docs)]
140 Empty,
141 FirstQuarter,
142 SecondQuarter,
143 ThirdQuarter,
144 FourthQuarter,
145 Full,
146}
147
148#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
149impl From<vals::Flvl> for FifoLevel {
150 fn from(flvl: vals::Flvl) -> Self {
151 match flvl {
152 vals::Flvl::EMPTY => FifoLevel::Empty,
153 vals::Flvl::QUARTER1 => FifoLevel::FirstQuarter,
154 vals::Flvl::QUARTER2 => FifoLevel::SecondQuarter,
155 vals::Flvl::QUARTER3 => FifoLevel::ThirdQuarter,
156 vals::Flvl::QUARTER4 => FifoLevel::FourthQuarter,
157 vals::Flvl::FULL => FifoLevel::Full,
158 _ => FifoLevel::Empty,
159 }
160 }
161}
162
163#[derive(Copy, Clone)]
164pub enum MuteDetection {
165 NoMute,
166 Mute,
167}
168
169#[derive(Copy, Clone)]
170pub enum MuteValue { 142pub enum MuteValue {
171 Zero, 143 Zero,
172 LastValue, 144 LastValue,
@@ -174,7 +146,7 @@ pub enum MuteValue {
174 146
175impl MuteValue { 147impl MuteValue {
176 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 148 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
177 pub const fn muteval(&self) -> vals::Muteval { 149 const fn muteval(&self) -> vals::Muteval {
178 match self { 150 match self {
179 MuteValue::Zero => vals::Muteval::SENDZERO, 151 MuteValue::Zero => vals::Muteval::SENDZERO,
180 MuteValue::LastValue => vals::Muteval::SENDLAST, 152 MuteValue::LastValue => vals::Muteval::SENDLAST,
@@ -182,13 +154,9 @@ impl MuteValue {
182 } 154 }
183} 155}
184 156
157/// Protocol variant to use.
185#[derive(Copy, Clone)] 158#[derive(Copy, Clone)]
186pub enum OverUnderStatus { 159#[allow(missing_docs)]
187 NoError,
188 OverUnderRunDetected,
189}
190
191#[derive(Copy, Clone)]
192pub enum Protocol { 160pub enum Protocol {
193 Free, 161 Free,
194 Spdif, 162 Spdif,
@@ -197,7 +165,7 @@ pub enum Protocol {
197 165
198impl Protocol { 166impl Protocol {
199 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 167 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
200 pub const fn prtcfg(&self) -> vals::Prtcfg { 168 const fn prtcfg(&self) -> vals::Prtcfg {
201 match self { 169 match self {
202 Protocol::Free => vals::Prtcfg::FREE, 170 Protocol::Free => vals::Prtcfg::FREE,
203 Protocol::Spdif => vals::Prtcfg::SPDIF, 171 Protocol::Spdif => vals::Prtcfg::SPDIF,
@@ -206,7 +174,9 @@ impl Protocol {
206 } 174 }
207} 175}
208 176
177/// Sync input between SAI units/blocks.
209#[derive(Copy, Clone, PartialEq)] 178#[derive(Copy, Clone, PartialEq)]
179#[allow(missing_docs)]
210pub enum SyncInput { 180pub enum SyncInput {
211 /// Not synced to any other SAI unit. 181 /// Not synced to any other SAI unit.
212 None, 182 None,
@@ -218,7 +188,7 @@ pub enum SyncInput {
218} 188}
219 189
220impl SyncInput { 190impl SyncInput {
221 pub const fn syncen(&self) -> vals::Syncen { 191 const fn syncen(&self) -> vals::Syncen {
222 match self { 192 match self {
223 SyncInput::None => vals::Syncen::ASYNCHRONOUS, 193 SyncInput::None => vals::Syncen::ASYNCHRONOUS,
224 SyncInput::Internal => vals::Syncen::INTERNAL, 194 SyncInput::Internal => vals::Syncen::INTERNAL,
@@ -228,8 +198,10 @@ impl SyncInput {
228 } 198 }
229} 199}
230 200
201/// SAI instance to sync from.
231#[cfg(sai_v4)] 202#[cfg(sai_v4)]
232#[derive(Copy, Clone, PartialEq)] 203#[derive(Copy, Clone, PartialEq)]
204#[allow(missing_docs)]
233pub enum SyncInputInstance { 205pub enum SyncInputInstance {
234 #[cfg(peri_sai1)] 206 #[cfg(peri_sai1)]
235 Sai1 = 0, 207 Sai1 = 0,
@@ -241,7 +213,9 @@ pub enum SyncInputInstance {
241 Sai4 = 3, 213 Sai4 = 3,
242} 214}
243 215
216/// Channels (stereo or mono).
244#[derive(Copy, Clone, PartialEq)] 217#[derive(Copy, Clone, PartialEq)]
218#[allow(missing_docs)]
245pub enum StereoMono { 219pub enum StereoMono {
246 Stereo, 220 Stereo,
247 Mono, 221 Mono,
@@ -249,7 +223,7 @@ pub enum StereoMono {
249 223
250impl StereoMono { 224impl StereoMono {
251 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 225 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
252 pub const fn mono(&self) -> vals::Mono { 226 const fn mono(&self) -> vals::Mono {
253 match self { 227 match self {
254 StereoMono::Stereo => vals::Mono::STEREO, 228 StereoMono::Stereo => vals::Mono::STEREO,
255 StereoMono::Mono => vals::Mono::MONO, 229 StereoMono::Mono => vals::Mono::MONO,
@@ -257,15 +231,18 @@ impl StereoMono {
257 } 231 }
258} 232}
259 233
234/// Bit order
260#[derive(Copy, Clone)] 235#[derive(Copy, Clone)]
261pub enum BitOrder { 236pub enum BitOrder {
237 /// Least significant bit first.
262 LsbFirst, 238 LsbFirst,
239 /// Most significant bit first.
263 MsbFirst, 240 MsbFirst,
264} 241}
265 242
266impl BitOrder { 243impl BitOrder {
267 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 244 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
268 pub const fn lsbfirst(&self) -> vals::Lsbfirst { 245 const fn lsbfirst(&self) -> vals::Lsbfirst {
269 match self { 246 match self {
270 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, 247 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST,
271 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, 248 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
@@ -273,6 +250,7 @@ impl BitOrder {
273 } 250 }
274} 251}
275 252
253/// Frame sync offset.
276#[derive(Copy, Clone)] 254#[derive(Copy, Clone)]
277pub enum FrameSyncOffset { 255pub enum FrameSyncOffset {
278 /// This is used in modes other than standard I2S phillips mode 256 /// This is used in modes other than standard I2S phillips mode
@@ -283,7 +261,7 @@ pub enum FrameSyncOffset {
283 261
284impl FrameSyncOffset { 262impl FrameSyncOffset {
285 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 263 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
286 pub const fn fsoff(&self) -> vals::Fsoff { 264 const fn fsoff(&self) -> vals::Fsoff {
287 match self { 265 match self {
288 FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST, 266 FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST,
289 FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST, 267 FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST,
@@ -291,15 +269,18 @@ impl FrameSyncOffset {
291 } 269 }
292} 270}
293 271
272/// Frame sync polarity
294#[derive(Copy, Clone)] 273#[derive(Copy, Clone)]
295pub enum FrameSyncPolarity { 274pub enum FrameSyncPolarity {
275 /// Sync signal is active low.
296 ActiveLow, 276 ActiveLow,
277 /// Sync signal is active high
297 ActiveHigh, 278 ActiveHigh,
298} 279}
299 280
300impl FrameSyncPolarity { 281impl FrameSyncPolarity {
301 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 282 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
302 pub const fn fspol(&self) -> vals::Fspol { 283 const fn fspol(&self) -> vals::Fspol {
303 match self { 284 match self {
304 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE, 285 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE,
305 FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE, 286 FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE,
@@ -307,7 +288,9 @@ impl FrameSyncPolarity {
307 } 288 }
308} 289}
309 290
291/// Sync definition.
310#[derive(Copy, Clone)] 292#[derive(Copy, Clone)]
293#[allow(missing_docs)]
311pub enum FrameSyncDefinition { 294pub enum FrameSyncDefinition {
312 StartOfFrame, 295 StartOfFrame,
313 ChannelIdentification, 296 ChannelIdentification,
@@ -315,7 +298,7 @@ pub enum FrameSyncDefinition {
315 298
316impl FrameSyncDefinition { 299impl FrameSyncDefinition {
317 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 300 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
318 pub const fn fsdef(&self) -> bool { 301 const fn fsdef(&self) -> bool {
319 match self { 302 match self {
320 FrameSyncDefinition::StartOfFrame => false, 303 FrameSyncDefinition::StartOfFrame => false,
321 FrameSyncDefinition::ChannelIdentification => true, 304 FrameSyncDefinition::ChannelIdentification => true,
@@ -323,7 +306,9 @@ impl FrameSyncDefinition {
323 } 306 }
324} 307}
325 308
309/// Clock strobe.
326#[derive(Copy, Clone)] 310#[derive(Copy, Clone)]
311#[allow(missing_docs)]
327pub enum ClockStrobe { 312pub enum ClockStrobe {
328 Falling, 313 Falling,
329 Rising, 314 Rising,
@@ -331,7 +316,7 @@ pub enum ClockStrobe {
331 316
332impl ClockStrobe { 317impl ClockStrobe {
333 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 318 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
334 pub const fn ckstr(&self) -> vals::Ckstr { 319 const fn ckstr(&self) -> vals::Ckstr {
335 match self { 320 match self {
336 ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE, 321 ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE,
337 ClockStrobe::Rising => vals::Ckstr::RISINGEDGE, 322 ClockStrobe::Rising => vals::Ckstr::RISINGEDGE,
@@ -339,7 +324,9 @@ impl ClockStrobe {
339 } 324 }
340} 325}
341 326
327/// Complements format for negative samples.
342#[derive(Copy, Clone)] 328#[derive(Copy, Clone)]
329#[allow(missing_docs)]
343pub enum ComplementFormat { 330pub enum ComplementFormat {
344 OnesComplement, 331 OnesComplement,
345 TwosComplement, 332 TwosComplement,
@@ -347,7 +334,7 @@ pub enum ComplementFormat {
347 334
348impl ComplementFormat { 335impl ComplementFormat {
349 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 336 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
350 pub const fn cpl(&self) -> vals::Cpl { 337 const fn cpl(&self) -> vals::Cpl {
351 match self { 338 match self {
352 ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT, 339 ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT,
353 ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT, 340 ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT,
@@ -355,7 +342,9 @@ impl ComplementFormat {
355 } 342 }
356} 343}
357 344
345/// Companding setting.
358#[derive(Copy, Clone)] 346#[derive(Copy, Clone)]
347#[allow(missing_docs)]
359pub enum Companding { 348pub enum Companding {
360 None, 349 None,
361 MuLaw, 350 MuLaw,
@@ -364,7 +353,7 @@ pub enum Companding {
364 353
365impl Companding { 354impl Companding {
366 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 355 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
367 pub const fn comp(&self) -> vals::Comp { 356 const fn comp(&self) -> vals::Comp {
368 match self { 357 match self {
369 Companding::None => vals::Comp::NOCOMPANDING, 358 Companding::None => vals::Comp::NOCOMPANDING,
370 Companding::MuLaw => vals::Comp::MULAW, 359 Companding::MuLaw => vals::Comp::MULAW,
@@ -373,7 +362,9 @@ impl Companding {
373 } 362 }
374} 363}
375 364
365/// Output drive
376#[derive(Copy, Clone)] 366#[derive(Copy, Clone)]
367#[allow(missing_docs)]
377pub enum OutputDrive { 368pub enum OutputDrive {
378 OnStart, 369 OnStart,
379 Immediately, 370 Immediately,
@@ -381,7 +372,7 @@ pub enum OutputDrive {
381 372
382impl OutputDrive { 373impl OutputDrive {
383 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 374 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
384 pub const fn outdriv(&self) -> vals::Outdriv { 375 const fn outdriv(&self) -> vals::Outdriv {
385 match self { 376 match self {
386 OutputDrive::OnStart => vals::Outdriv::ONSTART, 377 OutputDrive::OnStart => vals::Outdriv::ONSTART,
387 OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY, 378 OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY,
@@ -389,7 +380,9 @@ impl OutputDrive {
389 } 380 }
390} 381}
391 382
383/// Master clock divider.
392#[derive(Copy, Clone, PartialEq)] 384#[derive(Copy, Clone, PartialEq)]
385#[allow(missing_docs)]
393pub enum MasterClockDivider { 386pub enum MasterClockDivider {
394 MasterClockDisabled, 387 MasterClockDisabled,
395 Div1, 388 Div1,
@@ -412,7 +405,7 @@ pub enum MasterClockDivider {
412 405
413impl MasterClockDivider { 406impl MasterClockDivider {
414 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 407 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
415 pub const fn mckdiv(&self) -> u8 { 408 const fn mckdiv(&self) -> u8 {
416 match self { 409 match self {
417 MasterClockDivider::MasterClockDisabled => 0, 410 MasterClockDivider::MasterClockDisabled => 0,
418 MasterClockDivider::Div1 => 0, 411 MasterClockDivider::Div1 => 0,
@@ -436,6 +429,7 @@ impl MasterClockDivider {
436} 429}
437 430
438/// [`SAI`] configuration. 431/// [`SAI`] configuration.
432#[allow(missing_docs)]
439#[non_exhaustive] 433#[non_exhaustive]
440#[derive(Copy, Clone)] 434#[derive(Copy, Clone)]
441pub struct Config { 435pub struct Config {
@@ -459,7 +453,7 @@ pub struct Config {
459 pub clock_strobe: ClockStrobe, 453 pub clock_strobe: ClockStrobe,
460 pub output_drive: OutputDrive, 454 pub output_drive: OutputDrive,
461 pub master_clock_divider: MasterClockDivider, 455 pub master_clock_divider: MasterClockDivider,
462 pub is_high_impedenane_on_inactive_slot: bool, 456 pub is_high_impedance_on_inactive_slot: bool,
463 pub fifo_threshold: FifoThreshold, 457 pub fifo_threshold: FifoThreshold,
464 pub companding: Companding, 458 pub companding: Companding,
465 pub complement_format: ComplementFormat, 459 pub complement_format: ComplementFormat,
@@ -490,7 +484,7 @@ impl Default for Config {
490 master_clock_divider: MasterClockDivider::MasterClockDisabled, 484 master_clock_divider: MasterClockDivider::MasterClockDisabled,
491 clock_strobe: ClockStrobe::Rising, 485 clock_strobe: ClockStrobe::Rising,
492 output_drive: OutputDrive::Immediately, 486 output_drive: OutputDrive::Immediately,
493 is_high_impedenane_on_inactive_slot: false, 487 is_high_impedance_on_inactive_slot: false,
494 fifo_threshold: FifoThreshold::ThreeQuarters, 488 fifo_threshold: FifoThreshold::ThreeQuarters,
495 companding: Companding::None, 489 companding: Companding::None,
496 complement_format: ComplementFormat::TwosComplement, 490 complement_format: ComplementFormat::TwosComplement,
@@ -501,23 +495,10 @@ impl Default for Config {
501} 495}
502 496
503impl Config { 497impl Config {
504 pub fn new_i2s() -> Self { 498 /// Create a new config with all default values.
499 pub fn new() -> Self {
505 return Default::default(); 500 return Default::default();
506 } 501 }
507
508 pub fn new_msb_first() -> Self {
509 Self {
510 bit_order: BitOrder::MsbFirst,
511 frame_sync_offset: FrameSyncOffset::OnFirstBit,
512 ..Default::default()
513 }
514 }
515}
516
517#[derive(Copy, Clone)]
518enum WhichSubBlock {
519 A = 0,
520 B = 1,
521} 502}
522 503
523enum RingBuffer<'d, C: Channel, W: word::Word> { 504enum RingBuffer<'d, C: Channel, W: word::Word> {
@@ -531,28 +512,6 @@ fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut
531 ch.dr().as_ptr() as _ 512 ch.dr().as_ptr() as _
532} 513}
533 514
534pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> {
535 _peri: PeripheralRef<'d, T>,
536 sd: Option<PeripheralRef<'d, AnyPin>>,
537 fs: Option<PeripheralRef<'d, AnyPin>>,
538 sck: Option<PeripheralRef<'d, AnyPin>>,
539 mclk: Option<PeripheralRef<'d, AnyPin>>,
540 ring_buffer: RingBuffer<'d, C, W>,
541 sub_block: WhichSubBlock,
542}
543
544pub struct SubBlockA {}
545pub struct SubBlockB {}
546
547pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>);
548pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>);
549
550pub struct Sai<'d, T: Instance> {
551 _peri: PeripheralRef<'d, T>,
552 sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>,
553 sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>,
554}
555
556// return the type for (sd, sck) 515// return the type for (sd, sck)
557fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { 516fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
558 ( 517 (
@@ -583,42 +542,14 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>(
583 }; 542 };
584 match tx_rx { 543 match tx_rx {
585 TxRx::Transmitter => RingBuffer::Writable(unsafe { 544 TxRx::Transmitter => RingBuffer::Writable(unsafe {
586 WritableRingBuffer::new_write(dma, request, dr(T::REGS, sub_block), dma_buf, opts) 545 WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
587 }), 546 }),
588 TxRx::Receiver => RingBuffer::Readable(unsafe { 547 TxRx::Receiver => RingBuffer::Readable(unsafe {
589 ReadableRingBuffer::new_read(dma, request, dr(T::REGS, sub_block), dma_buf, opts) 548 ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
590 }), 549 }),
591 } 550 }
592} 551}
593 552
594impl<'d, T: Instance> Sai<'d, T> {
595 pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self {
596 T::enable_and_reset();
597
598 Self {
599 _peri: unsafe { peri.clone_unchecked().into_ref() },
600 sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })),
601 sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())),
602 }
603 }
604
605 pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> {
606 if self.sub_block_a_peri.is_some() {
607 self.sub_block_a_peri.take()
608 } else {
609 None
610 }
611 }
612
613 pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> {
614 if self.sub_block_b_peri.is_some() {
615 self.sub_block_b_peri.take()
616 } else {
617 None
618 }
619 }
620}
621
622fn update_synchronous_config(config: &mut Config) { 553fn update_synchronous_config(config: &mut Config) {
623 config.mode = Mode::Slave; 554 config.mode = Mode::Slave;
624 config.sync_output = false; 555 config.sync_output = false;
@@ -636,122 +567,58 @@ fn update_synchronous_config(config: &mut Config) {
636 } 567 }
637} 568}
638 569
639impl SubBlockA { 570/// SAI subblock instance.
640 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 571pub struct SubBlock<'d, T, S: SubBlockInstance> {
641 peri: SubBlockAPeripheral<'d, T>, 572 peri: PeripheralRef<'d, T>,
642 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 573 _phantom: PhantomData<S>,
643 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 574}
644 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
645 mclk: impl Peripheral<P = impl MclkAPin<T>> + 'd,
646 dma: impl Peripheral<P = C> + 'd,
647 dma_buf: &'d mut [W],
648 mut config: Config,
649 ) -> SubBlock<'d, T, C, W>
650 where
651 C: Channel + DmaA<T>,
652 {
653 into_ref!(mclk);
654
655 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
656
657 mclk.set_as_af(mclk.af_num(), ck_af_type);
658 mclk.set_speed(crate::gpio::Speed::VeryHigh);
659
660 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
661 config.master_clock_divider = MasterClockDivider::Div1;
662 }
663
664 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
665 }
666
667 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
668 peri: SubBlockAPeripheral<'d, T>,
669 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
670 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
671 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
672 dma: impl Peripheral<P = C> + 'd,
673 dma_buf: &'d mut [W],
674 config: Config,
675 ) -> SubBlock<'d, T, C, W>
676 where
677 C: Channel + DmaA<T>,
678 {
679 let peri = peri.0;
680 into_ref!(peri, dma, sck, sd, fs);
681
682 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
683 sd.set_as_af(sd.af_num(), sd_af_type);
684 sd.set_speed(crate::gpio::Speed::VeryHigh);
685
686 sck.set_as_af(sck.af_num(), ck_af_type);
687 sck.set_speed(crate::gpio::Speed::VeryHigh);
688 fs.set_as_af(fs.af_num(), ck_af_type);
689 fs.set_speed(crate::gpio::Speed::VeryHigh);
690 575
691 let sub_block = WhichSubBlock::A; 576/// Split the main SAIx peripheral into the two subblocks.
692 let request = dma.request(); 577///
578/// You can then create a [`Sai`] driver for each each half.
579pub fn split_subblocks<'d, T: Instance>(peri: impl Peripheral<P = T> + 'd) -> (SubBlock<'d, T, A>, SubBlock<'d, T, B>) {
580 into_ref!(peri);
581 T::enable_and_reset();
693 582
694 SubBlock::new_inner( 583 (
584 SubBlock {
585 peri: unsafe { peri.clone_unchecked() },
586 _phantom: PhantomData,
587 },
588 SubBlock {
695 peri, 589 peri,
696 sub_block, 590 _phantom: PhantomData,
697 Some(sck.map_into()), 591 },
698 None, 592 )
699 Some(sd.map_into()), 593}
700 Some(fs.map_into()),
701 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
702 config,
703 )
704 }
705
706 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
707 peri: SubBlockAPeripheral<'d, T>,
708 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
709 dma: impl Peripheral<P = C> + 'd,
710 dma_buf: &'d mut [W],
711 mut config: Config,
712 ) -> SubBlock<'d, T, C, W>
713 where
714 C: Channel + DmaA<T>,
715 {
716 update_synchronous_config(&mut config);
717
718 let peri = peri.0;
719 into_ref!(dma, peri, sd);
720
721 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
722
723 sd.set_as_af(sd.af_num(), sd_af_type);
724 sd.set_speed(crate::gpio::Speed::VeryHigh);
725
726 let sub_block = WhichSubBlock::A;
727 let request = dma.request();
728 594
729 SubBlock::new_inner( 595/// SAI sub-block driver.
730 peri, 596pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> {
731 sub_block, 597 _peri: PeripheralRef<'d, T>,
732 None, 598 sd: Option<PeripheralRef<'d, AnyPin>>,
733 None, 599 fs: Option<PeripheralRef<'d, AnyPin>>,
734 Some(sd.map_into()), 600 sck: Option<PeripheralRef<'d, AnyPin>>,
735 None, 601 mclk: Option<PeripheralRef<'d, AnyPin>>,
736 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), 602 ring_buffer: RingBuffer<'d, C, W>,
737 config, 603 sub_block: WhichSubBlock,
738 )
739 }
740} 604}
741 605
742impl SubBlockB { 606impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
743 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 607 /// Create a new SAI driver in asynchronous mode with MCLK.
744 peri: SubBlockBPeripheral<'d, T>, 608 ///
745 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 609 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
746 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 610 pub fn new_asynchronous_with_mclk<S: SubBlockInstance>(
747 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 611 peri: SubBlock<'d, T, S>,
748 mclk: impl Peripheral<P = impl MclkBPin<T>> + 'd, 612 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
613 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
614 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
615 mclk: impl Peripheral<P = impl MclkPin<T, S>> + 'd,
749 dma: impl Peripheral<P = C> + 'd, 616 dma: impl Peripheral<P = C> + 'd,
750 dma_buf: &'d mut [W], 617 dma_buf: &'d mut [W],
751 mut config: Config, 618 mut config: Config,
752 ) -> SubBlock<'d, T, C, W> 619 ) -> Self
753 where 620 where
754 C: Channel + DmaB<T>, 621 C: Channel + Dma<T, S>,
755 { 622 {
756 into_ref!(mclk); 623 into_ref!(mclk);
757 624
@@ -767,23 +634,25 @@ impl SubBlockB {
767 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) 634 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
768 } 635 }
769 636
770 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( 637 /// Create a new SAI driver in asynchronous mode without MCLK.
771 peri: SubBlockBPeripheral<'d, T>, 638 ///
772 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 639 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
773 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 640 pub fn new_asynchronous<S: SubBlockInstance>(
774 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 641 peri: SubBlock<'d, T, S>,
642 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
643 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
644 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
775 dma: impl Peripheral<P = C> + 'd, 645 dma: impl Peripheral<P = C> + 'd,
776 dma_buf: &'d mut [W], 646 dma_buf: &'d mut [W],
777 config: Config, 647 config: Config,
778 ) -> SubBlock<'d, T, C, W> 648 ) -> Self
779 where 649 where
780 C: Channel + DmaB<T>, 650 C: Channel + Dma<T, S>,
781 { 651 {
782 let peri = peri.0; 652 let peri = peri.peri;
783 into_ref!(dma, peri, sck, sd, fs); 653 into_ref!(peri, dma, sck, sd, fs);
784 654
785 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); 655 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
786
787 sd.set_as_af(sd.af_num(), sd_af_type); 656 sd.set_as_af(sd.af_num(), sd_af_type);
788 sd.set_speed(crate::gpio::Speed::VeryHigh); 657 sd.set_speed(crate::gpio::Speed::VeryHigh);
789 658
@@ -792,10 +661,10 @@ impl SubBlockB {
792 fs.set_as_af(fs.af_num(), ck_af_type); 661 fs.set_as_af(fs.af_num(), ck_af_type);
793 fs.set_speed(crate::gpio::Speed::VeryHigh); 662 fs.set_speed(crate::gpio::Speed::VeryHigh);
794 663
795 let sub_block = WhichSubBlock::B; 664 let sub_block = S::WHICH;
796 let request = dma.request(); 665 let request = dma.request();
797 666
798 SubBlock::new_inner( 667 Self::new_inner(
799 peri, 668 peri,
800 sub_block, 669 sub_block,
801 Some(sck.map_into()), 670 Some(sck.map_into()),
@@ -807,18 +676,22 @@ impl SubBlockB {
807 ) 676 )
808 } 677 }
809 678
810 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( 679 /// Create a new SAI driver in synchronous mode.
811 peri: SubBlockBPeripheral<'d, T>, 680 ///
812 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 681 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
682 pub fn new_synchronous<S: SubBlockInstance>(
683 peri: SubBlock<'d, T, S>,
684 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
813 dma: impl Peripheral<P = C> + 'd, 685 dma: impl Peripheral<P = C> + 'd,
814 dma_buf: &'d mut [W], 686 dma_buf: &'d mut [W],
815 mut config: Config, 687 mut config: Config,
816 ) -> SubBlock<'d, T, C, W> 688 ) -> Self
817 where 689 where
818 C: Channel + DmaB<T>, 690 C: Channel + Dma<T, S>,
819 { 691 {
820 update_synchronous_config(&mut config); 692 update_synchronous_config(&mut config);
821 let peri = peri.0; 693
694 let peri = peri.peri;
822 into_ref!(dma, peri, sd); 695 into_ref!(dma, peri, sd);
823 696
824 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); 697 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
@@ -826,10 +699,10 @@ impl SubBlockB {
826 sd.set_as_af(sd.af_num(), sd_af_type); 699 sd.set_as_af(sd.af_num(), sd_af_type);
827 sd.set_speed(crate::gpio::Speed::VeryHigh); 700 sd.set_speed(crate::gpio::Speed::VeryHigh);
828 701
829 let sub_block = WhichSubBlock::B; 702 let sub_block = S::WHICH;
830 let request = dma.request(); 703 let request = dma.request();
831 704
832 SubBlock::new_inner( 705 Self::new_inner(
833 peri, 706 peri,
834 sub_block, 707 sub_block,
835 None, 708 None,
@@ -840,26 +713,6 @@ impl SubBlockB {
840 config, 713 config,
841 ) 714 )
842 } 715 }
843}
844
845impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
846 pub fn start(self: &mut Self) {
847 match self.ring_buffer {
848 RingBuffer::Writable(ref mut rb) => {
849 rb.start();
850 }
851 RingBuffer::Readable(ref mut rb) => {
852 rb.start();
853 }
854 }
855 }
856
857 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
858 match ring_buffer {
859 RingBuffer::Writable(_) => true,
860 _ => false,
861 }
862 }
863 716
864 fn new_inner( 717 fn new_inner(
865 peri: impl Peripheral<P = T> + 'd, 718 peri: impl Peripheral<P = T> + 'd,
@@ -929,7 +782,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
929 w.set_cpl(config.complement_format.cpl()); 782 w.set_cpl(config.complement_format.cpl());
930 w.set_muteval(config.mute_value.muteval()); 783 w.set_muteval(config.mute_value.muteval());
931 w.set_mutecnt(config.mute_detection_counter.0 as u8); 784 w.set_mutecnt(config.mute_detection_counter.0 as u8);
932 w.set_tris(config.is_high_impedenane_on_inactive_slot); 785 w.set_tris(config.is_high_impedance_on_inactive_slot);
933 }); 786 });
934 787
935 ch.frcr().modify(|w| { 788 ch.frcr().modify(|w| {
@@ -965,10 +818,31 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
965 } 818 }
966 } 819 }
967 820
821 /// Start the SAI driver.
822 pub fn start(&mut self) {
823 match self.ring_buffer {
824 RingBuffer::Writable(ref mut rb) => {
825 rb.start();
826 }
827 RingBuffer::Readable(ref mut rb) => {
828 rb.start();
829 }
830 }
831 }
832
833 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
834 match ring_buffer {
835 RingBuffer::Writable(_) => true,
836 _ => false,
837 }
838 }
839
840 /// Reset SAI operation.
968 pub fn reset() { 841 pub fn reset() {
969 T::enable_and_reset(); 842 T::enable_and_reset();
970 } 843 }
971 844
845 /// Flush.
972 pub fn flush(&mut self) { 846 pub fn flush(&mut self) {
973 let ch = T::REGS.ch(self.sub_block as usize); 847 let ch = T::REGS.ch(self.sub_block as usize);
974 ch.cr1().modify(|w| w.set_saien(false)); 848 ch.cr1().modify(|w| w.set_saien(false));
@@ -983,19 +857,18 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
983 ch.cr1().modify(|w| w.set_saien(true)); 857 ch.cr1().modify(|w| w.set_saien(true));
984 } 858 }
985 859
860 /// Enable or disable mute.
986 pub fn set_mute(&mut self, value: bool) { 861 pub fn set_mute(&mut self, value: bool) {
987 let ch = T::REGS.ch(self.sub_block as usize); 862 let ch = T::REGS.ch(self.sub_block as usize);
988 ch.cr2().modify(|w| w.set_mute(value)); 863 ch.cr2().modify(|w| w.set_mute(value));
989 } 864 }
990 865
991 #[allow(dead_code)] 866 /// Write data to the SAI ringbuffer.
992 /// Reconfigures it with the supplied config. 867 ///
993 fn reconfigure(&mut self, _config: Config) {} 868 /// This appends the data to the buffer and returns immediately. The
994 869 /// data will be transmitted in the background.
995 pub fn get_current_config(&self) -> Config { 870 ///
996 Config::default() 871 /// If there's no space in the buffer, this waits until there is.
997 }
998
999 pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { 872 pub async fn write(&mut self, data: &[W]) -> Result<(), Error> {
1000 match &mut self.ring_buffer { 873 match &mut self.ring_buffer {
1001 RingBuffer::Writable(buffer) => { 874 RingBuffer::Writable(buffer) => {
@@ -1006,6 +879,12 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
1006 } 879 }
1007 } 880 }
1008 881
882 /// Read data from the SAI ringbuffer.
883 ///
884 /// SAI is always receiving data in the background. This function pops already-received
885 /// data from the buffer.
886 ///
887 /// If there's less than `data.len()` data in the buffer, this waits until there is.
1009 pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { 888 pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> {
1010 match &mut self.ring_buffer { 889 match &mut self.ring_buffer {
1011 RingBuffer::Readable(buffer) => { 890 RingBuffer::Readable(buffer) => {
@@ -1017,7 +896,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
1017 } 896 }
1018} 897}
1019 898
1020impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> { 899impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> {
1021 fn drop(&mut self) { 900 fn drop(&mut self) {
1022 let ch = T::REGS.ch(self.sub_block as usize); 901 let ch = T::REGS.ch(self.sub_block as usize);
1023 ch.cr1().modify(|w| w.set_saien(false)); 902 ch.cr1().modify(|w| w.set_saien(false));
@@ -1034,22 +913,43 @@ pub(crate) mod sealed {
1034 pub trait Instance { 913 pub trait Instance {
1035 const REGS: Regs; 914 const REGS: Regs;
1036 } 915 }
916
917 #[derive(Copy, Clone)]
918 pub enum WhichSubBlock {
919 A = 0,
920 B = 1,
921 }
922
923 pub trait SubBlock {
924 const WHICH: WhichSubBlock;
925 }
1037} 926}
1038 927
1039pub trait Word: word::Word {} 928/// Sub-block instance trait.
929pub trait SubBlockInstance: sealed::SubBlock {}
1040 930
931/// Sub-block A.
932pub enum A {}
933impl sealed::SubBlock for A {
934 const WHICH: WhichSubBlock = WhichSubBlock::A;
935}
936impl SubBlockInstance for A {}
937
938/// Sub-block B.
939pub enum B {}
940impl sealed::SubBlock for B {
941 const WHICH: WhichSubBlock = WhichSubBlock::B;
942}
943impl SubBlockInstance for B {}
944
945/// SAI instance trait.
1041pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 946pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
1042pin_trait!(SckAPin, Instance); 947pin_trait!(SckPin, Instance, SubBlockInstance);
1043pin_trait!(SckBPin, Instance); 948pin_trait!(FsPin, Instance, SubBlockInstance);
1044pin_trait!(FsAPin, Instance); 949pin_trait!(SdPin, Instance, SubBlockInstance);
1045pin_trait!(FsBPin, Instance); 950pin_trait!(MclkPin, Instance, SubBlockInstance);
1046pin_trait!(SdAPin, Instance); 951
1047pin_trait!(SdBPin, Instance); 952dma_trait!(Dma, Instance, SubBlockInstance);
1048pin_trait!(MclkAPin, Instance);
1049pin_trait!(MclkBPin, Instance);
1050
1051dma_trait!(DmaA, Instance);
1052dma_trait!(DmaB, Instance);
1053 953
1054foreach_peripheral!( 954foreach_peripheral!(
1055 (sai, $inst:ident) => { 955 (sai, $inst:ident) => {
@@ -1060,13 +960,3 @@ foreach_peripheral!(
1060 impl Instance for peripherals::$inst {} 960 impl Instance for peripherals::$inst {}
1061 }; 961 };
1062); 962);
1063
1064impl<'d, T: Instance> SetConfig for Sai<'d, T> {
1065 type Config = Config;
1066 type ConfigError = ();
1067 fn set_config(&mut self, _config: &Self::Config) -> Result<(), ()> {
1068 // self.reconfigure(*config);
1069
1070 Ok(())
1071 }
1072}
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 27a12062c..debe26c88 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -1,3 +1,4 @@
1//! Secure Digital / MultiMedia Card (SDMMC)
1#![macro_use] 2#![macro_use]
2 3
3use core::default::Default; 4use core::default::Default;
@@ -53,6 +54,7 @@ const SD_INIT_FREQ: Hertz = Hertz(400_000);
53 54
54/// The signalling scheme used on the SDMMC bus 55/// The signalling scheme used on the SDMMC bus
55#[non_exhaustive] 56#[non_exhaustive]
57#[allow(missing_docs)]
56#[derive(Debug, Copy, Clone, PartialEq, Eq)] 58#[derive(Debug, Copy, Clone, PartialEq, Eq)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))] 59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58pub enum Signalling { 60pub enum Signalling {
@@ -69,6 +71,9 @@ impl Default for Signalling {
69 } 71 }
70} 72}
71 73
74/// Aligned data block for SDMMC transfers.
75///
76/// This is a 512-byte array, aligned to 4 bytes to satisfy DMA requirements.
72#[repr(align(4))] 77#[repr(align(4))]
73#[derive(Debug, Clone, PartialEq, Eq)] 78#[derive(Debug, Clone, PartialEq, Eq)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))] 79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -93,17 +98,23 @@ impl DerefMut for DataBlock {
93#[derive(Debug, Copy, Clone, PartialEq, Eq)] 98#[derive(Debug, Copy, Clone, PartialEq, Eq)]
94#[cfg_attr(feature = "defmt", derive(defmt::Format))] 99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
95pub enum Error { 100pub enum Error {
101 /// Timeout reported by the hardware
96 Timeout, 102 Timeout,
103 /// Timeout reported by the software driver.
97 SoftwareTimeout, 104 SoftwareTimeout,
105 /// Unsupported card version.
98 UnsupportedCardVersion, 106 UnsupportedCardVersion,
107 /// Unsupported card type.
99 UnsupportedCardType, 108 UnsupportedCardType,
109 /// CRC error.
100 Crc, 110 Crc,
101 DataCrcFail, 111 /// No card inserted.
102 RxOverFlow,
103 NoCard, 112 NoCard,
113 /// Bad clock supplied to the SDMMC peripheral.
104 BadClock, 114 BadClock,
115 /// Signaling switch failed.
105 SignalingSwitchFailed, 116 SignalingSwitchFailed,
106 PeripheralBusy, 117 /// ST bit error.
107 #[cfg(sdmmc_v1)] 118 #[cfg(sdmmc_v1)]
108 StBitErr, 119 StBitErr,
109} 120}
@@ -282,6 +293,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
282 293
283#[cfg(sdmmc_v1)] 294#[cfg(sdmmc_v1)]
284impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { 295impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
296 /// Create a new SDMMC driver, with 1 data lane.
285 pub fn new_1bit( 297 pub fn new_1bit(
286 sdmmc: impl Peripheral<P = T> + 'd, 298 sdmmc: impl Peripheral<P = T> + 'd,
287 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 299 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -316,6 +328,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
316 ) 328 )
317 } 329 }
318 330
331 /// Create a new SDMMC driver, with 4 data lanes.
319 pub fn new_4bit( 332 pub fn new_4bit(
320 sdmmc: impl Peripheral<P = T> + 'd, 333 sdmmc: impl Peripheral<P = T> + 'd,
321 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 334 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -362,6 +375,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
362 375
363#[cfg(sdmmc_v2)] 376#[cfg(sdmmc_v2)]
364impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { 377impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
378 /// Create a new SDMMC driver, with 1 data lane.
365 pub fn new_1bit( 379 pub fn new_1bit(
366 sdmmc: impl Peripheral<P = T> + 'd, 380 sdmmc: impl Peripheral<P = T> + 'd,
367 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 381 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -395,6 +409,7 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> {
395 ) 409 )
396 } 410 }
397 411
412 /// Create a new SDMMC driver, with 4 data lanes.
398 pub fn new_4bit( 413 pub fn new_4bit(
399 sdmmc: impl Peripheral<P = T> + 'd, 414 sdmmc: impl Peripheral<P = T> + 'd,
400 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 415 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -496,7 +511,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
496 } 511 }
497 512
498 /// Data transfer is in progress 513 /// Data transfer is in progress
499 #[inline(always)] 514 #[inline]
500 fn data_active() -> bool { 515 fn data_active() -> bool {
501 let regs = T::regs(); 516 let regs = T::regs();
502 517
@@ -508,7 +523,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
508 } 523 }
509 524
510 /// Coammand transfer is in progress 525 /// Coammand transfer is in progress
511 #[inline(always)] 526 #[inline]
512 fn cmd_active() -> bool { 527 fn cmd_active() -> bool {
513 let regs = T::regs(); 528 let regs = T::regs();
514 529
@@ -520,7 +535,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
520 } 535 }
521 536
522 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) 537 /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2)
523 #[inline(always)] 538 #[inline]
524 fn wait_idle() { 539 fn wait_idle() {
525 while Self::data_active() || Self::cmd_active() {} 540 while Self::data_active() || Self::cmd_active() {}
526 } 541 }
@@ -836,7 +851,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
836 } 851 }
837 852
838 /// Clear flags in interrupt clear register 853 /// Clear flags in interrupt clear register
839 #[inline(always)] 854 #[inline]
840 fn clear_interrupt_flags() { 855 fn clear_interrupt_flags() {
841 let regs = T::regs(); 856 let regs = T::regs();
842 regs.icr().write(|w| { 857 regs.icr().write(|w| {
@@ -1151,7 +1166,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1151 Ok(()) 1166 Ok(())
1152 } 1167 }
1153 1168
1154 #[inline(always)] 1169 /// Read a data block.
1170 #[inline]
1155 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 1171 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> {
1156 let card_capacity = self.card()?.card_type; 1172 let card_capacity = self.card()?.card_type;
1157 1173
@@ -1203,6 +1219,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1203 res 1219 res
1204 } 1220 }
1205 1221
1222 /// Write a data block.
1206 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { 1223 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> {
1207 let card = self.card.as_mut().ok_or(Error::NoCard)?; 1224 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1208 1225
@@ -1282,7 +1299,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1282 /// 1299 ///
1283 /// Returns Error::NoCard if [`init_card`](#method.init_card) 1300 /// Returns Error::NoCard if [`init_card`](#method.init_card)
1284 /// has not previously succeeded 1301 /// has not previously succeeded
1285 #[inline(always)] 1302 #[inline]
1286 pub fn card(&self) -> Result<&Card, Error> { 1303 pub fn card(&self) -> Result<&Card, Error> {
1287 self.card.as_ref().ok_or(Error::NoCard) 1304 self.card.as_ref().ok_or(Error::NoCard)
1288 } 1305 }
@@ -1418,7 +1435,9 @@ pub(crate) mod sealed {
1418 pub trait Pins<T: Instance> {} 1435 pub trait Pins<T: Instance> {}
1419} 1436}
1420 1437
1438/// SDMMC instance trait.
1421pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 1439pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
1440
1422pin_trait!(CkPin, Instance); 1441pin_trait!(CkPin, Instance);
1423pin_trait!(CmdPin, Instance); 1442pin_trait!(CmdPin, Instance);
1424pin_trait!(D0Pin, Instance); 1443pin_trait!(D0Pin, Instance);
@@ -1433,7 +1452,10 @@ pin_trait!(D7Pin, Instance);
1433#[cfg(sdmmc_v1)] 1452#[cfg(sdmmc_v1)]
1434dma_trait!(SdmmcDma, Instance); 1453dma_trait!(SdmmcDma, Instance);
1435 1454
1436// SDMMCv2 uses internal DMA 1455/// DMA instance trait.
1456///
1457/// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of
1458/// using ST's system-wide DMA peripheral.
1437#[cfg(sdmmc_v2)] 1459#[cfg(sdmmc_v2)]
1438pub trait SdmmcDma<T: Instance> {} 1460pub trait SdmmcDma<T: Instance> {}
1439#[cfg(sdmmc_v2)] 1461#[cfg(sdmmc_v2)]
@@ -1516,53 +1538,3 @@ foreach_peripheral!(
1516 impl Instance for peripherals::$inst {} 1538 impl Instance for peripherals::$inst {}
1517 }; 1539 };
1518); 1540);
1519
1520#[cfg(feature = "embedded-sdmmc")]
1521mod sdmmc_rs {
1522 use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx};
1523
1524 use super::*;
1525
1526 impl<'d, T: Instance, Dma: SdmmcDma<T>> BlockDevice for Sdmmc<'d, T, Dma> {
1527 type Error = Error;
1528
1529 async fn read(
1530 &mut self,
1531 blocks: &mut [Block],
1532 start_block_idx: BlockIdx,
1533 _reason: &str,
1534 ) -> Result<(), Self::Error> {
1535 let mut address = start_block_idx.0;
1536
1537 for block in blocks.iter_mut() {
1538 let block: &mut [u8; 512] = &mut block.contents;
1539
1540 // NOTE(unsafe) Block uses align(4)
1541 let block = unsafe { &mut *(block as *mut _ as *mut DataBlock) };
1542 self.read_block(address, block).await?;
1543 address += 1;
1544 }
1545 Ok(())
1546 }
1547
1548 async fn write(&mut self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
1549 let mut address = start_block_idx.0;
1550
1551 for block in blocks.iter() {
1552 let block: &[u8; 512] = &block.contents;
1553
1554 // NOTE(unsafe) DataBlock uses align 4
1555 let block = unsafe { &*(block as *const _ as *const DataBlock) };
1556 self.write_block(address, block).await?;
1557 address += 1;
1558 }
1559 Ok(())
1560 }
1561
1562 fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
1563 let card = self.card()?;
1564 let count = card.csd.block_count();
1565 Ok(BlockCount(count))
1566 }
1567 }
1568}
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 92599c75e..674a5d316 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,3 +1,4 @@
1//! Serial Peripheral Interface (SPI)
1#![macro_use] 2#![macro_use]
2 3
3use core::ptr; 4use core::ptr;
@@ -15,27 +16,38 @@ use crate::rcc::RccPeripheral;
15use crate::time::Hertz; 16use crate::time::Hertz;
16use crate::{peripherals, Peripheral}; 17use crate::{peripherals, Peripheral};
17 18
19/// SPI error.
18#[derive(Debug, PartialEq, Eq)] 20#[derive(Debug, PartialEq, Eq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum Error { 22pub enum Error {
23 /// Invalid framing.
21 Framing, 24 Framing,
25 /// CRC error (only if hardware CRC checking is enabled).
22 Crc, 26 Crc,
27 /// Mode fault
23 ModeFault, 28 ModeFault,
29 /// Overrun.
24 Overrun, 30 Overrun,
25} 31}
26 32
27// TODO move upwards in the tree 33/// SPI bit order
28#[derive(Copy, Clone)] 34#[derive(Copy, Clone)]
29pub enum BitOrder { 35pub enum BitOrder {
36 /// Least significant bit first.
30 LsbFirst, 37 LsbFirst,
38 /// Most significant bit first.
31 MsbFirst, 39 MsbFirst,
32} 40}
33 41
42/// SPI configuration.
34#[non_exhaustive] 43#[non_exhaustive]
35#[derive(Copy, Clone)] 44#[derive(Copy, Clone)]
36pub struct Config { 45pub struct Config {
46 /// SPI mode.
37 pub mode: Mode, 47 pub mode: Mode,
48 /// Bit order.
38 pub bit_order: BitOrder, 49 pub bit_order: BitOrder,
50 /// Clock frequency.
39 pub frequency: Hertz, 51 pub frequency: Hertz,
40} 52}
41 53
@@ -72,6 +84,7 @@ impl Config {
72 } 84 }
73} 85}
74 86
87/// SPI driver.
75pub struct Spi<'d, T: Instance, Tx, Rx> { 88pub struct Spi<'d, T: Instance, Tx, Rx> {
76 _peri: PeripheralRef<'d, T>, 89 _peri: PeripheralRef<'d, T>,
77 sck: Option<PeripheralRef<'d, AnyPin>>, 90 sck: Option<PeripheralRef<'d, AnyPin>>,
@@ -83,6 +96,7 @@ pub struct Spi<'d, T: Instance, Tx, Rx> {
83} 96}
84 97
85impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 98impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
99 /// Create a new SPI driver.
86 pub fn new( 100 pub fn new(
87 peri: impl Peripheral<P = T> + 'd, 101 peri: impl Peripheral<P = T> + 'd,
88 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 102 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
@@ -117,6 +131,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
117 ) 131 )
118 } 132 }
119 133
134 /// Create a new SPI driver, in RX-only mode (only MISO pin, no MOSI).
120 pub fn new_rxonly( 135 pub fn new_rxonly(
121 peri: impl Peripheral<P = T> + 'd, 136 peri: impl Peripheral<P = T> + 'd,
122 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 137 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
@@ -142,6 +157,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
142 ) 157 )
143 } 158 }
144 159
160 /// Create a new SPI driver, in TX-only mode (only MOSI pin, no MISO).
145 pub fn new_txonly( 161 pub fn new_txonly(
146 peri: impl Peripheral<P = T> + 'd, 162 peri: impl Peripheral<P = T> + 'd,
147 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 163 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
@@ -167,6 +183,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
167 ) 183 )
168 } 184 }
169 185
186 /// Create a new SPI driver, in TX-only mode, without SCK pin.
187 ///
188 /// This can be useful for bit-banging non-SPI protocols.
170 pub fn new_txonly_nosck( 189 pub fn new_txonly_nosck(
171 peri: impl Peripheral<P = T> + 'd, 190 peri: impl Peripheral<P = T> + 'd,
172 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd, 191 mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
@@ -354,6 +373,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
354 Ok(()) 373 Ok(())
355 } 374 }
356 375
376 /// Get current SPI configuration.
357 pub fn get_current_config(&self) -> Config { 377 pub fn get_current_config(&self) -> Config {
358 #[cfg(any(spi_v1, spi_f1, spi_v2))] 378 #[cfg(any(spi_v1, spi_f1, spi_v2))]
359 let cfg = T::REGS.cr1().read(); 379 let cfg = T::REGS.cr1().read();
@@ -443,6 +463,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
443 self.current_word_size = word_size; 463 self.current_word_size = word_size;
444 } 464 }
445 465
466 /// SPI write, using DMA.
446 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> 467 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error>
447 where 468 where
448 Tx: TxDma<T>, 469 Tx: TxDma<T>,
@@ -476,6 +497,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
476 Ok(()) 497 Ok(())
477 } 498 }
478 499
500 /// SPI read, using DMA.
479 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> 501 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
480 where 502 where
481 Tx: TxDma<T>, 503 Tx: TxDma<T>,
@@ -579,6 +601,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
579 Ok(()) 601 Ok(())
580 } 602 }
581 603
604 /// Bidirectional transfer, using DMA.
605 ///
606 /// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
607 ///
608 /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
609 /// If `write` is shorter it is padded with zero bytes.
582 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> 610 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error>
583 where 611 where
584 Tx: TxDma<T>, 612 Tx: TxDma<T>,
@@ -587,6 +615,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
587 self.transfer_inner(read, write).await 615 self.transfer_inner(read, write).await
588 } 616 }
589 617
618 /// In-place bidirectional transfer, using DMA.
619 ///
620 /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
590 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> 621 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
591 where 622 where
592 Tx: TxDma<T>, 623 Tx: TxDma<T>,
@@ -595,6 +626,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
595 self.transfer_inner(data, data).await 626 self.transfer_inner(data, data).await
596 } 627 }
597 628
629 /// Blocking write.
598 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { 630 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
599 T::REGS.cr1().modify(|w| w.set_spe(true)); 631 T::REGS.cr1().modify(|w| w.set_spe(true));
600 flush_rx_fifo(T::REGS); 632 flush_rx_fifo(T::REGS);
@@ -605,6 +637,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
605 Ok(()) 637 Ok(())
606 } 638 }
607 639
640 /// Blocking read.
608 pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { 641 pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
609 T::REGS.cr1().modify(|w| w.set_spe(true)); 642 T::REGS.cr1().modify(|w| w.set_spe(true));
610 flush_rx_fifo(T::REGS); 643 flush_rx_fifo(T::REGS);
@@ -615,6 +648,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
615 Ok(()) 648 Ok(())
616 } 649 }
617 650
651 /// Blocking in-place bidirectional transfer.
652 ///
653 /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time.
618 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { 654 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
619 T::REGS.cr1().modify(|w| w.set_spe(true)); 655 T::REGS.cr1().modify(|w| w.set_spe(true));
620 flush_rx_fifo(T::REGS); 656 flush_rx_fifo(T::REGS);
@@ -625,6 +661,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
625 Ok(()) 661 Ok(())
626 } 662 }
627 663
664 /// Blocking bidirectional transfer.
665 ///
666 /// This transfers both buffers at the same time, so it is NOT equivalent to `write` followed by `read`.
667 ///
668 /// The transfer runs for `max(read.len(), write.len())` bytes. If `read` is shorter extra bytes are ignored.
669 /// If `write` is shorter it is padded with zero bytes.
628 pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { 670 pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
629 T::REGS.cr1().modify(|w| w.set_spe(true)); 671 T::REGS.cr1().modify(|w| w.set_spe(true));
630 flush_rx_fifo(T::REGS); 672 flush_rx_fifo(T::REGS);
@@ -945,6 +987,7 @@ pub(crate) mod sealed {
945 } 987 }
946} 988}
947 989
990/// Word sizes usable for SPI.
948pub trait Word: word::Word + sealed::Word {} 991pub trait Word: word::Word + sealed::Word {}
949 992
950macro_rules! impl_word { 993macro_rules! impl_word {
@@ -1024,7 +1067,9 @@ mod word_impl {
1024 impl_word!(u32, 32 - 1); 1067 impl_word!(u32, 32 - 1);
1025} 1068}
1026 1069
1070/// SPI instance trait.
1027pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 1071pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
1072
1028pin_trait!(SckPin, Instance); 1073pin_trait!(SckPin, Instance);
1029pin_trait!(MosiPin, Instance); 1074pin_trait!(MosiPin, Instance);
1030pin_trait!(MisoPin, Instance); 1075pin_trait!(MisoPin, Instance);
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index a0bc33944..17690aefc 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -8,14 +8,17 @@ use core::ops::{Div, Mul};
8pub struct Hertz(pub u32); 8pub struct Hertz(pub u32);
9 9
10impl Hertz { 10impl Hertz {
11 /// Create a `Hertz` from the given hertz.
11 pub const fn hz(hertz: u32) -> Self { 12 pub const fn hz(hertz: u32) -> Self {
12 Self(hertz) 13 Self(hertz)
13 } 14 }
14 15
16 /// Create a `Hertz` from the given kilohertz.
15 pub const fn khz(kilohertz: u32) -> Self { 17 pub const fn khz(kilohertz: u32) -> Self {
16 Self(kilohertz * 1_000) 18 Self(kilohertz * 1_000)
17 } 19 }
18 20
21 /// Create a `Hertz` from the given megahertz.
19 pub const fn mhz(megahertz: u32) -> Self { 22 pub const fn mhz(megahertz: u32) -> Self {
20 Self(megahertz * 1_000_000) 23 Self(megahertz * 1_000_000)
21 } 24 }
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index ea9c22d87..9981800b2 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -474,16 +474,29 @@ impl Driver for RtcDriver {
474 return false; 474 return false;
475 } 475 }
476 476
477 let safe_timestamp = timestamp.max(t + 3);
478
479 // Write the CCR value regardless of whether we're going to enable it now or not. 477 // Write the CCR value regardless of whether we're going to enable it now or not.
480 // This way, when we enable it later, the right value is already set. 478 // This way, when we enable it later, the right value is already set.
481 r.ccr(n + 1).write(|w| w.set_ccr(safe_timestamp as u16)); 479 r.ccr(n + 1).write(|w| w.set_ccr(timestamp as u16));
482 480
483 // Enable it if it'll happen soon. Otherwise, `next_period` will enable it. 481 // Enable it if it'll happen soon. Otherwise, `next_period` will enable it.
484 let diff = timestamp - t; 482 let diff = timestamp - t;
485 r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)); 483 r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000));
486 484
485 // Reevaluate if the alarm timestamp is still in the future
486 let t = self.now();
487 if timestamp <= t {
488 // If alarm timestamp has passed since we set it, we have a race condition and
489 // the alarm may or may not have fired.
490 // Disarm the alarm and return `false` to indicate that.
491 // It is the caller's responsibility to handle this ambiguity.
492 r.dier().modify(|w| w.set_ccie(n + 1, false));
493
494 alarm.timestamp.set(u64::MAX);
495
496 return false;
497 }
498
499 // We're confident the alarm will ring in the future.
487 true 500 true
488 }) 501 })
489 } 502 }
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 6654366cd..71d7110b5 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -1,3 +1,5 @@
1//! PWM driver with complementary output support.
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
@@ -11,15 +13,19 @@ use crate::gpio::{AnyPin, OutputType};
11use crate::time::Hertz; 13use crate::time::Hertz;
12use crate::Peripheral; 14use crate::Peripheral;
13 15
14pub struct ComplementaryPwmPin<'d, Perip, Channel> { 16/// Complementary PWM pin wrapper.
17///
18/// This wraps a pin to make it usable with PWM.
19pub struct ComplementaryPwmPin<'d, T, C> {
15 _pin: PeripheralRef<'d, AnyPin>, 20 _pin: PeripheralRef<'d, AnyPin>,
16 phantom: PhantomData<(Perip, Channel)>, 21 phantom: PhantomData<(T, C)>,
17} 22}
18 23
19macro_rules! complementary_channel_impl { 24macro_rules! complementary_channel_impl {
20 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 25 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
21 impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { 26 impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> {
22 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self { 27 #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
28 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
23 into_ref!(pin); 29 into_ref!(pin);
24 critical_section::with(|_| { 30 critical_section::with(|_| {
25 pin.set_low(); 31 pin.set_low();
@@ -41,11 +47,13 @@ complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
41complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); 47complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
42complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); 48complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
43 49
50/// PWM driver with support for standard and complementary outputs.
44pub struct ComplementaryPwm<'d, T> { 51pub struct ComplementaryPwm<'d, T> {
45 inner: PeripheralRef<'d, T>, 52 inner: PeripheralRef<'d, T>,
46} 53}
47 54
48impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { 55impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
56 /// Create a new complementary PWM driver.
49 pub fn new( 57 pub fn new(
50 tim: impl Peripheral<P = T> + 'd, 58 tim: impl Peripheral<P = T> + 'd,
51 _ch1: Option<PwmPin<'d, T, Ch1>>, 59 _ch1: Option<PwmPin<'d, T, Ch1>>,
@@ -70,7 +78,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
70 let mut this = Self { inner: tim }; 78 let mut this = Self { inner: tim };
71 79
72 this.inner.set_counting_mode(counting_mode); 80 this.inner.set_counting_mode(counting_mode);
73 this.set_freq(freq); 81 this.set_frequency(freq);
74 this.inner.start(); 82 this.inner.start();
75 83
76 this.inner.enable_outputs(); 84 this.inner.enable_outputs();
@@ -86,17 +94,23 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
86 this 94 this
87 } 95 }
88 96
97 /// Enable the given channel.
89 pub fn enable(&mut self, channel: Channel) { 98 pub fn enable(&mut self, channel: Channel) {
90 self.inner.enable_channel(channel, true); 99 self.inner.enable_channel(channel, true);
91 self.inner.enable_complementary_channel(channel, true); 100 self.inner.enable_complementary_channel(channel, true);
92 } 101 }
93 102
103 /// Disable the given channel.
94 pub fn disable(&mut self, channel: Channel) { 104 pub fn disable(&mut self, channel: Channel) {
95 self.inner.enable_complementary_channel(channel, false); 105 self.inner.enable_complementary_channel(channel, false);
96 self.inner.enable_channel(channel, false); 106 self.inner.enable_channel(channel, false);
97 } 107 }
98 108
99 pub fn set_freq(&mut self, freq: Hertz) { 109 /// Set PWM frequency.
110 ///
111 /// Note: when you call this, the max duty value changes, so you will have to
112 /// call `set_duty` on all channels with the duty calculated based on the new max duty.
113 pub fn set_frequency(&mut self, freq: Hertz) {
100 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 114 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
101 2u8 115 2u8
102 } else { 116 } else {
@@ -105,15 +119,22 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
105 self.inner.set_frequency(freq * multiplier); 119 self.inner.set_frequency(freq * multiplier);
106 } 120 }
107 121
122 /// Get max duty value.
123 ///
124 /// This value depends on the configured frequency and the timer's clock rate from RCC.
108 pub fn get_max_duty(&self) -> u16 { 125 pub fn get_max_duty(&self) -> u16 {
109 self.inner.get_max_compare_value() + 1 126 self.inner.get_max_compare_value() + 1
110 } 127 }
111 128
129 /// Set the duty for a given channel.
130 ///
131 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
112 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 132 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
113 assert!(duty <= self.get_max_duty()); 133 assert!(duty <= self.get_max_duty());
114 self.inner.set_compare_value(channel, duty) 134 self.inner.set_compare_value(channel, duty)
115 } 135 }
116 136
137 /// Set the output polarity for a given channel.
117 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 138 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
118 self.inner.set_output_polarity(channel, polarity); 139 self.inner.set_output_polarity(channel, polarity);
119 self.inner.set_complementary_output_polarity(channel, polarity); 140 self.inner.set_complementary_output_polarity(channel, polarity);
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 9f93c6425..74120adad 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,3 +1,5 @@
1//! Timers, PWM, quadrature decoder.
2
1pub mod complementary_pwm; 3pub mod complementary_pwm;
2pub mod qei; 4pub mod qei;
3pub mod simple_pwm; 5pub mod simple_pwm;
@@ -8,23 +10,34 @@ use crate::interrupt;
8use crate::rcc::RccPeripheral; 10use crate::rcc::RccPeripheral;
9use crate::time::Hertz; 11use crate::time::Hertz;
10 12
13/// Low-level timer access.
11#[cfg(feature = "unstable-pac")] 14#[cfg(feature = "unstable-pac")]
12pub mod low_level { 15pub mod low_level {
13 pub use super::sealed::*; 16 pub use super::sealed::*;
14} 17}
15 18
16pub(crate) mod sealed { 19pub(crate) mod sealed {
17
18 use super::*; 20 use super::*;
21
22 /// Basic 16-bit timer instance.
19 pub trait Basic16bitInstance: RccPeripheral { 23 pub trait Basic16bitInstance: RccPeripheral {
24 /// Interrupt for this timer.
20 type Interrupt: interrupt::typelevel::Interrupt; 25 type Interrupt: interrupt::typelevel::Interrupt;
21 26
27 /// Get access to the basic 16bit timer registers.
28 ///
29 /// Note: This works even if the timer is more capable, because registers
30 /// for the less capable timers are a subset. This allows writing a driver
31 /// for a given set of capabilities, and having it transparently work with
32 /// more capable timers.
22 fn regs() -> crate::pac::timer::TimBasic; 33 fn regs() -> crate::pac::timer::TimBasic;
23 34
35 /// Start the timer.
24 fn start(&mut self) { 36 fn start(&mut self) {
25 Self::regs().cr1().modify(|r| r.set_cen(true)); 37 Self::regs().cr1().modify(|r| r.set_cen(true));
26 } 38 }
27 39
40 /// Stop the timer.
28 fn stop(&mut self) { 41 fn stop(&mut self) {
29 Self::regs().cr1().modify(|r| r.set_cen(false)); 42 Self::regs().cr1().modify(|r| r.set_cen(false));
30 } 43 }
@@ -60,6 +73,9 @@ pub(crate) mod sealed {
60 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 73 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
61 } 74 }
62 75
76 /// Clear update interrupt.
77 ///
78 /// Returns whether the update interrupt flag was set.
63 fn clear_update_interrupt(&mut self) -> bool { 79 fn clear_update_interrupt(&mut self) -> bool {
64 let regs = Self::regs(); 80 let regs = Self::regs();
65 let sr = regs.sr().read(); 81 let sr = regs.sr().read();
@@ -73,14 +89,17 @@ pub(crate) mod sealed {
73 } 89 }
74 } 90 }
75 91
92 /// Enable/disable the update interrupt.
76 fn enable_update_interrupt(&mut self, enable: bool) { 93 fn enable_update_interrupt(&mut self, enable: bool) {
77 Self::regs().dier().write(|r| r.set_uie(enable)); 94 Self::regs().dier().write(|r| r.set_uie(enable));
78 } 95 }
79 96
97 /// Enable/disable autoreload preload.
80 fn set_autoreload_preload(&mut self, enable: bool) { 98 fn set_autoreload_preload(&mut self, enable: bool) {
81 Self::regs().cr1().modify(|r| r.set_arpe(enable)); 99 Self::regs().cr1().modify(|r| r.set_arpe(enable));
82 } 100 }
83 101
102 /// Get the timer frequency.
84 fn get_frequency(&self) -> Hertz { 103 fn get_frequency(&self) -> Hertz {
85 let timer_f = Self::frequency(); 104 let timer_f = Self::frequency();
86 105
@@ -92,9 +111,17 @@ pub(crate) mod sealed {
92 } 111 }
93 } 112 }
94 113
114 /// Gneral-purpose 16-bit timer instance.
95 pub trait GeneralPurpose16bitInstance: Basic16bitInstance { 115 pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
116 /// Get access to the general purpose 16bit timer registers.
117 ///
118 /// Note: This works even if the timer is more capable, because registers
119 /// for the less capable timers are a subset. This allows writing a driver
120 /// for a given set of capabilities, and having it transparently work with
121 /// more capable timers.
96 fn regs_gp16() -> crate::pac::timer::TimGp16; 122 fn regs_gp16() -> crate::pac::timer::TimGp16;
97 123
124 /// Set counting mode.
98 fn set_counting_mode(&mut self, mode: CountingMode) { 125 fn set_counting_mode(&mut self, mode: CountingMode) {
99 let (cms, dir) = mode.into(); 126 let (cms, dir) = mode.into();
100 127
@@ -107,19 +134,29 @@ pub(crate) mod sealed {
107 Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) 134 Self::regs_gp16().cr1().modify(|r| r.set_cms(cms))
108 } 135 }
109 136
137 /// Get counting mode.
110 fn get_counting_mode(&self) -> CountingMode { 138 fn get_counting_mode(&self) -> CountingMode {
111 let cr1 = Self::regs_gp16().cr1().read(); 139 let cr1 = Self::regs_gp16().cr1().read();
112 (cr1.cms(), cr1.dir()).into() 140 (cr1.cms(), cr1.dir()).into()
113 } 141 }
114 142
143 /// Set clock divider.
115 fn set_clock_division(&mut self, ckd: vals::Ckd) { 144 fn set_clock_division(&mut self, ckd: vals::Ckd) {
116 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); 145 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
117 } 146 }
118 } 147 }
119 148
149 /// Gneral-purpose 32-bit timer instance.
120 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { 150 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
151 /// Get access to the general purpose 32bit timer registers.
152 ///
153 /// Note: This works even if the timer is more capable, because registers
154 /// for the less capable timers are a subset. This allows writing a driver
155 /// for a given set of capabilities, and having it transparently work with
156 /// more capable timers.
121 fn regs_gp32() -> crate::pac::timer::TimGp32; 157 fn regs_gp32() -> crate::pac::timer::TimGp32;
122 158
159 /// Set timer frequency.
123 fn set_frequency(&mut self, frequency: Hertz) { 160 fn set_frequency(&mut self, frequency: Hertz) {
124 let f = frequency.0; 161 let f = frequency.0;
125 assert!(f > 0); 162 assert!(f > 0);
@@ -137,6 +174,7 @@ pub(crate) mod sealed {
137 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 174 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
138 } 175 }
139 176
177 /// Get timer frequency.
140 fn get_frequency(&self) -> Hertz { 178 fn get_frequency(&self) -> Hertz {
141 let timer_f = Self::frequency(); 179 let timer_f = Self::frequency();
142 180
@@ -148,141 +186,177 @@ pub(crate) mod sealed {
148 } 186 }
149 } 187 }
150 188
189 /// Advanced control timer instance.
151 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { 190 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
191 /// Get access to the advanced timer registers.
152 fn regs_advanced() -> crate::pac::timer::TimAdv; 192 fn regs_advanced() -> crate::pac::timer::TimAdv;
153 } 193 }
154 194
195 /// Capture/Compare 16-bit timer instance.
155 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { 196 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
197 /// Set input capture filter.
156 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { 198 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
157 let raw_channel = channel.raw(); 199 let raw_channel = channel.index();
158 Self::regs_gp16() 200 Self::regs_gp16()
159 .ccmr_input(raw_channel / 2) 201 .ccmr_input(raw_channel / 2)
160 .modify(|r| r.set_icf(raw_channel % 2, icf)); 202 .modify(|r| r.set_icf(raw_channel % 2, icf));
161 } 203 }
162 204
205 /// Clear input interrupt.
163 fn clear_input_interrupt(&mut self, channel: Channel) { 206 fn clear_input_interrupt(&mut self, channel: Channel) {
164 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.raw(), false)); 207 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
165 } 208 }
166 209
210 /// Enable input interrupt.
167 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { 211 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
168 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.raw(), enable)); 212 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
169 } 213 }
214
215 /// Set input capture prescaler.
170 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { 216 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
171 let raw_channel = channel.raw(); 217 let raw_channel = channel.index();
172 Self::regs_gp16() 218 Self::regs_gp16()
173 .ccmr_input(raw_channel / 2) 219 .ccmr_input(raw_channel / 2)
174 .modify(|r| r.set_icpsc(raw_channel % 2, factor)); 220 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
175 } 221 }
176 222
223 /// Set input TI selection.
177 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { 224 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
178 let raw_channel = channel.raw(); 225 let raw_channel = channel.index();
179 Self::regs_gp16() 226 Self::regs_gp16()
180 .ccmr_input(raw_channel / 2) 227 .ccmr_input(raw_channel / 2)
181 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); 228 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
182 } 229 }
230
231 /// Set input capture mode.
183 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { 232 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
184 Self::regs_gp16().ccer().modify(|r| match mode { 233 Self::regs_gp16().ccer().modify(|r| match mode {
185 InputCaptureMode::Rising => { 234 InputCaptureMode::Rising => {
186 r.set_ccnp(channel.raw(), false); 235 r.set_ccnp(channel.index(), false);
187 r.set_ccp(channel.raw(), false); 236 r.set_ccp(channel.index(), false);
188 } 237 }
189 InputCaptureMode::Falling => { 238 InputCaptureMode::Falling => {
190 r.set_ccnp(channel.raw(), false); 239 r.set_ccnp(channel.index(), false);
191 r.set_ccp(channel.raw(), true); 240 r.set_ccp(channel.index(), true);
192 } 241 }
193 InputCaptureMode::BothEdges => { 242 InputCaptureMode::BothEdges => {
194 r.set_ccnp(channel.raw(), true); 243 r.set_ccnp(channel.index(), true);
195 r.set_ccp(channel.raw(), true); 244 r.set_ccp(channel.index(), true);
196 } 245 }
197 }); 246 });
198 } 247 }
248
249 /// Enable timer outputs.
199 fn enable_outputs(&mut self); 250 fn enable_outputs(&mut self);
200 251
252 /// Set output compare mode.
201 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { 253 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
202 let r = Self::regs_gp16(); 254 let r = Self::regs_gp16();
203 let raw_channel: usize = channel.raw(); 255 let raw_channel: usize = channel.index();
204 r.ccmr_output(raw_channel / 2) 256 r.ccmr_output(raw_channel / 2)
205 .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); 257 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
206 } 258 }
207 259
260 /// Set output polarity.
208 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 261 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
209 Self::regs_gp16() 262 Self::regs_gp16()
210 .ccer() 263 .ccer()
211 .modify(|w| w.set_ccp(channel.raw(), polarity.into())); 264 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
212 } 265 }
213 266
267 /// Enable/disable a channel.
214 fn enable_channel(&mut self, channel: Channel, enable: bool) { 268 fn enable_channel(&mut self, channel: Channel, enable: bool) {
215 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.raw(), enable)); 269 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
216 } 270 }
217 271
272 /// Set compare value for a channel.
218 fn set_compare_value(&mut self, channel: Channel, value: u16) { 273 fn set_compare_value(&mut self, channel: Channel, value: u16) {
219 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 274 Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
220 } 275 }
221 276
277 /// Get capture value for a channel.
222 fn get_capture_value(&mut self, channel: Channel) -> u16 { 278 fn get_capture_value(&mut self, channel: Channel) -> u16 {
223 Self::regs_gp16().ccr(channel.raw()).read().ccr() 279 Self::regs_gp16().ccr(channel.index()).read().ccr()
224 } 280 }
225 281
282 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
226 fn get_max_compare_value(&self) -> u16 { 283 fn get_max_compare_value(&self) -> u16 {
227 Self::regs_gp16().arr().read().arr() 284 Self::regs_gp16().arr().read().arr()
228 } 285 }
229 286
287 /// Get compare value for a channel.
230 fn get_compare_value(&self, channel: Channel) -> u16 { 288 fn get_compare_value(&self, channel: Channel) -> u16 {
231 Self::regs_gp16().ccr(channel.raw()).read().ccr() 289 Self::regs_gp16().ccr(channel.index()).read().ccr()
232 } 290 }
233 } 291 }
234 292
293 /// Capture/Compare 16-bit timer instance with complementary pin support.
235 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { 294 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
295 /// Set complementary output polarity.
236 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 296 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
237 Self::regs_advanced() 297 Self::regs_advanced()
238 .ccer() 298 .ccer()
239 .modify(|w| w.set_ccnp(channel.raw(), polarity.into())); 299 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
240 } 300 }
241 301
302 /// Set clock divider for the dead time.
242 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { 303 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
243 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); 304 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
244 } 305 }
245 306
307 /// Set dead time, as a fraction of the max duty value.
246 fn set_dead_time_value(&mut self, value: u8) { 308 fn set_dead_time_value(&mut self, value: u8) {
247 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); 309 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
248 } 310 }
249 311
312 /// Enable/disable a complementary channel.
250 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { 313 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
251 Self::regs_advanced() 314 Self::regs_advanced()
252 .ccer() 315 .ccer()
253 .modify(|w| w.set_ccne(channel.raw(), enable)); 316 .modify(|w| w.set_ccne(channel.index(), enable));
254 } 317 }
255 } 318 }
256 319
320 /// Capture/Compare 32-bit timer instance.
257 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance { 321 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
322 /// Set comapre value for a channel.
258 fn set_compare_value(&mut self, channel: Channel, value: u32) { 323 fn set_compare_value(&mut self, channel: Channel, value: u32) {
259 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 324 Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value));
260 } 325 }
261 326
327 /// Get capture value for a channel.
262 fn get_capture_value(&mut self, channel: Channel) -> u32 { 328 fn get_capture_value(&mut self, channel: Channel) -> u32 {
263 Self::regs_gp32().ccr(channel.raw()).read().ccr() 329 Self::regs_gp32().ccr(channel.index()).read().ccr()
264 } 330 }
265 331
332 /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC.
266 fn get_max_compare_value(&self) -> u32 { 333 fn get_max_compare_value(&self) -> u32 {
267 Self::regs_gp32().arr().read().arr() 334 Self::regs_gp32().arr().read().arr()
268 } 335 }
269 336
337 /// Get compare value for a channel.
270 fn get_compare_value(&self, channel: Channel) -> u32 { 338 fn get_compare_value(&self, channel: Channel) -> u32 {
271 Self::regs_gp32().ccr(channel.raw()).read().ccr() 339 Self::regs_gp32().ccr(channel.index()).read().ccr()
272 } 340 }
273 } 341 }
274} 342}
275 343
344/// Timer channel.
276#[derive(Clone, Copy)] 345#[derive(Clone, Copy)]
277pub enum Channel { 346pub enum Channel {
347 /// Channel 1.
278 Ch1, 348 Ch1,
349 /// Channel 2.
279 Ch2, 350 Ch2,
351 /// Channel 3.
280 Ch3, 352 Ch3,
353 /// Channel 4.
281 Ch4, 354 Ch4,
282} 355}
283 356
284impl Channel { 357impl Channel {
285 pub fn raw(&self) -> usize { 358 /// Get the channel index (0..3)
359 pub fn index(&self) -> usize {
286 match self { 360 match self {
287 Channel::Ch1 => 0, 361 Channel::Ch1 => 0,
288 Channel::Ch2 => 1, 362 Channel::Ch2 => 1,
@@ -292,17 +366,25 @@ impl Channel {
292 } 366 }
293} 367}
294 368
369/// Input capture mode.
295#[derive(Clone, Copy)] 370#[derive(Clone, Copy)]
296pub enum InputCaptureMode { 371pub enum InputCaptureMode {
372 /// Rising edge only.
297 Rising, 373 Rising,
374 /// Falling edge only.
298 Falling, 375 Falling,
376 /// Both rising or falling edges.
299 BothEdges, 377 BothEdges,
300} 378}
301 379
380/// Input TI selection.
302#[derive(Clone, Copy)] 381#[derive(Clone, Copy)]
303pub enum InputTISelection { 382pub enum InputTISelection {
383 /// Normal
304 Normal, 384 Normal,
385 /// Alternate
305 Alternate, 386 Alternate,
387 /// TRC
306 TRC, 388 TRC,
307} 389}
308 390
@@ -316,6 +398,7 @@ impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
316 } 398 }
317} 399}
318 400
401/// Timer counting mode.
319#[repr(u8)] 402#[repr(u8)]
320#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] 403#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
321pub enum CountingMode { 404pub enum CountingMode {
@@ -342,6 +425,7 @@ pub enum CountingMode {
342} 425}
343 426
344impl CountingMode { 427impl CountingMode {
428 /// Return whether this mode is edge-aligned (up or down).
345 pub fn is_edge_aligned(&self) -> bool { 429 pub fn is_edge_aligned(&self) -> bool {
346 match self { 430 match self {
347 CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown => true, 431 CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown => true,
@@ -349,6 +433,7 @@ impl CountingMode {
349 } 433 }
350 } 434 }
351 435
436 /// Return whether this mode is center-aligned.
352 pub fn is_center_aligned(&self) -> bool { 437 pub fn is_center_aligned(&self) -> bool {
353 match self { 438 match self {
354 CountingMode::CenterAlignedDownInterrupts 439 CountingMode::CenterAlignedDownInterrupts
@@ -383,16 +468,34 @@ impl From<(vals::Cms, vals::Dir)> for CountingMode {
383 } 468 }
384} 469}
385 470
471/// Output compare mode.
386#[derive(Clone, Copy)] 472#[derive(Clone, Copy)]
387pub enum OutputCompareMode { 473pub enum OutputCompareMode {
474 /// The comparison between the output compare register TIMx_CCRx and
475 /// the counter TIMx_CNT has no effect on the outputs.
476 /// (this mode is used to generate a timing base).
388 Frozen, 477 Frozen,
478 /// Set channel to active level on match. OCxREF signal is forced high when the
479 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
389 ActiveOnMatch, 480 ActiveOnMatch,
481 /// Set channel to inactive level on match. OCxREF signal is forced low when the
482 /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx).
390 InactiveOnMatch, 483 InactiveOnMatch,
484 /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx.
391 Toggle, 485 Toggle,
486 /// Force inactive level - OCxREF is forced low.
392 ForceInactive, 487 ForceInactive,
488 /// Force active level - OCxREF is forced high.
393 ForceActive, 489 ForceActive,
490 /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNT<TIMx_CCRx
491 /// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as
492 /// TIMx_CNT>TIMx_CCRx else active (OCxREF=1).
394 PwmMode1, 493 PwmMode1,
494 /// PWM mode 2 - In upcounting, channel is inactive as long as
495 /// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
496 /// TIMx_CNT>TIMx_CCRx else inactive.
395 PwmMode2, 497 PwmMode2,
498 // TODO: there's more modes here depending on the chip family.
396} 499}
397 500
398impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { 501impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
@@ -410,9 +513,12 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm {
410 } 513 }
411} 514}
412 515
516/// Timer output pin polarity.
413#[derive(Clone, Copy)] 517#[derive(Clone, Copy)]
414pub enum OutputPolarity { 518pub enum OutputPolarity {
519 /// Active high (higher duty value makes the pin spend more time high).
415 ActiveHigh, 520 ActiveHigh,
521 /// Active low (higher duty value makes the pin spend more time low).
416 ActiveLow, 522 ActiveLow,
417} 523}
418 524
@@ -425,24 +531,31 @@ impl From<OutputPolarity> for bool {
425 } 531 }
426} 532}
427 533
534/// Basic 16-bit timer instance.
428pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} 535pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
429 536
537/// Gneral-purpose 16-bit timer instance.
430pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {} 538pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {}
431 539
540/// Gneral-purpose 32-bit timer instance.
432pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {} 541pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {}
433 542
543/// Advanced control timer instance.
434pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {} 544pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {}
435 545
546/// Capture/Compare 16-bit timer instance.
436pub trait CaptureCompare16bitInstance: 547pub trait CaptureCompare16bitInstance:
437 sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static 548 sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
438{ 549{
439} 550}
440 551
552/// Capture/Compare 16-bit timer instance with complementary pin support.
441pub trait ComplementaryCaptureCompare16bitInstance: 553pub trait ComplementaryCaptureCompare16bitInstance:
442 sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static 554 sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static
443{ 555{
444} 556}
445 557
558/// Capture/Compare 32-bit timer instance.
446pub trait CaptureCompare32bitInstance: 559pub trait CaptureCompare32bitInstance:
447 sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static 560 sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
448{ 561{
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 01d028bf9..59efb72ba 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -1,3 +1,5 @@
1//! Quadrature decoder using a timer.
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
@@ -7,23 +9,30 @@ use crate::gpio::sealed::AFType;
7use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
8use crate::Peripheral; 10use crate::Peripheral;
9 11
12/// Counting direction
10pub enum Direction { 13pub enum Direction {
14 /// Counting up.
11 Upcounting, 15 Upcounting,
16 /// Counting down.
12 Downcounting, 17 Downcounting,
13} 18}
14 19
15pub struct Ch1; 20/// Channel 1 marker type.
16pub struct Ch2; 21pub enum Ch1 {}
22/// Channel 2 marker type.
23pub enum Ch2 {}
17 24
18pub struct QeiPin<'d, Perip, Channel> { 25/// Wrapper for using a pin with QEI.
26pub struct QeiPin<'d, T, Channel> {
19 _pin: PeripheralRef<'d, AnyPin>, 27 _pin: PeripheralRef<'d, AnyPin>,
20 phantom: PhantomData<(Perip, Channel)>, 28 phantom: PhantomData<(T, Channel)>,
21} 29}
22 30
23macro_rules! channel_impl { 31macro_rules! channel_impl {
24 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 32 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
25 impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> { 33 impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
26 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self { 34 #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
35 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
27 into_ref!(pin); 36 into_ref!(pin);
28 critical_section::with(|_| { 37 critical_section::with(|_| {
29 pin.set_low(); 38 pin.set_low();
@@ -43,11 +52,13 @@ macro_rules! channel_impl {
43channel_impl!(new_ch1, Ch1, Channel1Pin); 52channel_impl!(new_ch1, Ch1, Channel1Pin);
44channel_impl!(new_ch2, Ch2, Channel2Pin); 53channel_impl!(new_ch2, Ch2, Channel2Pin);
45 54
55/// Quadrature decoder driver.
46pub struct Qei<'d, T> { 56pub struct Qei<'d, T> {
47 _inner: PeripheralRef<'d, T>, 57 _inner: PeripheralRef<'d, T>,
48} 58}
49 59
50impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { 60impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
61 /// Create a new quadrature decoder driver.
51 pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { 62 pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
52 Self::new_inner(tim) 63 Self::new_inner(tim)
53 } 64 }
@@ -82,6 +93,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
82 Self { _inner: tim } 93 Self { _inner: tim }
83 } 94 }
84 95
96 /// Get direction.
85 pub fn read_direction(&self) -> Direction { 97 pub fn read_direction(&self) -> Direction {
86 match T::regs_gp16().cr1().read().dir() { 98 match T::regs_gp16().cr1().read().dir() {
87 vals::Dir::DOWN => Direction::Downcounting, 99 vals::Dir::DOWN => Direction::Downcounting,
@@ -89,6 +101,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
89 } 101 }
90 } 102 }
91 103
104 /// Get count.
92 pub fn count(&self) -> u16 { 105 pub fn count(&self) -> u16 {
93 T::regs_gp16().cnt().read().cnt() 106 T::regs_gp16().cnt().read().cnt()
94 } 107 }
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 1cf0ad728..e6072aa15 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -1,3 +1,5 @@
1//! Simple PWM driver.
2
1use core::marker::PhantomData; 3use core::marker::PhantomData;
2 4
3use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
@@ -9,20 +11,28 @@ use crate::gpio::{AnyPin, OutputType};
9use crate::time::Hertz; 11use crate::time::Hertz;
10use crate::Peripheral; 12use crate::Peripheral;
11 13
12pub struct Ch1; 14/// Channel 1 marker type.
13pub struct Ch2; 15pub enum Ch1 {}
14pub struct Ch3; 16/// Channel 2 marker type.
15pub struct Ch4; 17pub enum Ch2 {}
16 18/// Channel 3 marker type.
17pub struct PwmPin<'d, Perip, Channel> { 19pub enum Ch3 {}
20/// Channel 4 marker type.
21pub enum Ch4 {}
22
23/// PWM pin wrapper.
24///
25/// This wraps a pin to make it usable with PWM.
26pub struct PwmPin<'d, T, C> {
18 _pin: PeripheralRef<'d, AnyPin>, 27 _pin: PeripheralRef<'d, AnyPin>,
19 phantom: PhantomData<(Perip, Channel)>, 28 phantom: PhantomData<(T, C)>,
20} 29}
21 30
22macro_rules! channel_impl { 31macro_rules! channel_impl {
23 ($new_chx:ident, $channel:ident, $pin_trait:ident) => { 32 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
24 impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { 33 impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
25 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd, output_type: OutputType) -> Self { 34 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
35 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
26 into_ref!(pin); 36 into_ref!(pin);
27 critical_section::with(|_| { 37 critical_section::with(|_| {
28 pin.set_low(); 38 pin.set_low();
@@ -44,11 +54,13 @@ channel_impl!(new_ch2, Ch2, Channel2Pin);
44channel_impl!(new_ch3, Ch3, Channel3Pin); 54channel_impl!(new_ch3, Ch3, Channel3Pin);
45channel_impl!(new_ch4, Ch4, Channel4Pin); 55channel_impl!(new_ch4, Ch4, Channel4Pin);
46 56
57/// Simple PWM driver.
47pub struct SimplePwm<'d, T> { 58pub struct SimplePwm<'d, T> {
48 inner: PeripheralRef<'d, T>, 59 inner: PeripheralRef<'d, T>,
49} 60}
50 61
51impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { 62impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
63 /// Create a new simple PWM driver.
52 pub fn new( 64 pub fn new(
53 tim: impl Peripheral<P = T> + 'd, 65 tim: impl Peripheral<P = T> + 'd,
54 _ch1: Option<PwmPin<'d, T, Ch1>>, 66 _ch1: Option<PwmPin<'d, T, Ch1>>,
@@ -69,7 +81,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
69 let mut this = Self { inner: tim }; 81 let mut this = Self { inner: tim };
70 82
71 this.inner.set_counting_mode(counting_mode); 83 this.inner.set_counting_mode(counting_mode);
72 this.set_freq(freq); 84 this.set_frequency(freq);
73 this.inner.start(); 85 this.inner.start();
74 86
75 this.inner.enable_outputs(); 87 this.inner.enable_outputs();
@@ -85,15 +97,21 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
85 this 97 this
86 } 98 }
87 99
100 /// Enable the given channel.
88 pub fn enable(&mut self, channel: Channel) { 101 pub fn enable(&mut self, channel: Channel) {
89 self.inner.enable_channel(channel, true); 102 self.inner.enable_channel(channel, true);
90 } 103 }
91 104
105 /// Disable the given channel.
92 pub fn disable(&mut self, channel: Channel) { 106 pub fn disable(&mut self, channel: Channel) {
93 self.inner.enable_channel(channel, false); 107 self.inner.enable_channel(channel, false);
94 } 108 }
95 109
96 pub fn set_freq(&mut self, freq: Hertz) { 110 /// Set PWM frequency.
111 ///
112 /// Note: when you call this, the max duty value changes, so you will have to
113 /// call `set_duty` on all channels with the duty calculated based on the new max duty.
114 pub fn set_frequency(&mut self, freq: Hertz) {
97 let multiplier = if self.inner.get_counting_mode().is_center_aligned() { 115 let multiplier = if self.inner.get_counting_mode().is_center_aligned() {
98 2u8 116 2u8
99 } else { 117 } else {
@@ -102,15 +120,22 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
102 self.inner.set_frequency(freq * multiplier); 120 self.inner.set_frequency(freq * multiplier);
103 } 121 }
104 122
123 /// Get max duty value.
124 ///
125 /// This value depends on the configured frequency and the timer's clock rate from RCC.
105 pub fn get_max_duty(&self) -> u16 { 126 pub fn get_max_duty(&self) -> u16 {
106 self.inner.get_max_compare_value() + 1 127 self.inner.get_max_compare_value() + 1
107 } 128 }
108 129
130 /// Set the duty for a given channel.
131 ///
132 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
109 pub fn set_duty(&mut self, channel: Channel, duty: u16) { 133 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
110 assert!(duty <= self.get_max_duty()); 134 assert!(duty <= self.get_max_duty());
111 self.inner.set_compare_value(channel, duty) 135 self.inner.set_compare_value(channel, duty)
112 } 136 }
113 137
138 /// Set the output polarity for a given channel.
114 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { 139 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
115 self.inner.set_output_polarity(channel, polarity); 140 self.inner.set_output_polarity(channel, polarity);
116 } 141 }
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs
index ffce7bd42..13f695821 100644
--- a/embassy-stm32/src/traits.rs
+++ b/embassy-stm32/src/traits.rs
@@ -1,16 +1,18 @@
1#![macro_use] 1#![macro_use]
2 2
3macro_rules! pin_trait { 3macro_rules! pin_trait {
4 ($signal:ident, $instance:path) => { 4 ($signal:ident, $instance:path $(, $mode:path)?) => {
5 pub trait $signal<T: $instance>: crate::gpio::Pin { 5 #[doc = concat!(stringify!($signal), " pin trait")]
6 pub trait $signal<T: $instance $(, M: $mode)?>: crate::gpio::Pin {
7 #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))]
6 fn af_num(&self) -> u8; 8 fn af_num(&self) -> u8;
7 } 9 }
8 }; 10 };
9} 11}
10 12
11macro_rules! pin_trait_impl { 13macro_rules! pin_trait_impl {
12 (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, $af:expr) => { 14 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr) => {
13 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$pin { 15 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$pin {
14 fn af_num(&self) -> u8 { 16 fn af_num(&self) -> u8 {
15 $af 17 $af
16 } 18 }
@@ -21,8 +23,12 @@ macro_rules! pin_trait_impl {
21// ==================== 23// ====================
22 24
23macro_rules! dma_trait { 25macro_rules! dma_trait {
24 ($signal:ident, $instance:path) => { 26 ($signal:ident, $instance:path$(, $mode:path)?) => {
25 pub trait $signal<T: $instance>: crate::dma::Channel { 27 #[doc = concat!(stringify!($signal), " DMA request trait")]
28 pub trait $signal<T: $instance $(, M: $mode)?>: crate::dma::Channel {
29 #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))]
30 /// Note: in some chips, ST calls this the "channel", and calls channels "streams".
31 /// `embassy-stm32` always uses the "channel" and "request number" names.
26 fn request(&self) -> crate::dma::Request; 32 fn request(&self) -> crate::dma::Request;
27 } 33 }
28 }; 34 };
@@ -31,8 +37,8 @@ macro_rules! dma_trait {
31#[allow(unused)] 37#[allow(unused)]
32macro_rules! dma_trait_impl { 38macro_rules! dma_trait_impl {
33 // DMAMUX 39 // DMAMUX
34 (crate::$mod:ident::$trait:ident, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => { 40 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => {
35 impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T 41 impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T
36 where 42 where
37 T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>, 43 T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>,
38 { 44 {
@@ -43,8 +49,8 @@ macro_rules! dma_trait_impl {
43 }; 49 };
44 50
45 // DMAMUX 51 // DMAMUX
46 (crate::$mod:ident::$trait:ident, $instance:ident, {dma: $dma:ident}, $request:expr) => { 52 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dma: $dma:ident}, $request:expr) => {
47 impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T 53 impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T
48 where 54 where
49 T: crate::dma::Channel, 55 T: crate::dma::Channel,
50 { 56 {
@@ -55,8 +61,8 @@ macro_rules! dma_trait_impl {
55 }; 61 };
56 62
57 // DMA/GPDMA, without DMAMUX 63 // DMA/GPDMA, without DMAMUX
58 (crate::$mod:ident::$trait:ident, $instance:ident, {channel: $channel:ident}, $request:expr) => { 64 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {channel: $channel:ident}, $request:expr) => {
59 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$channel { 65 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel {
60 fn request(&self) -> crate::dma::Request { 66 fn request(&self) -> crate::dma::Request {
61 $request 67 $request
62 } 68 }
diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs
index 6dcfcb96e..aa13586f8 100644
--- a/embassy-stm32/src/uid.rs
+++ b/embassy-stm32/src/uid.rs
@@ -1,3 +1,5 @@
1//! Unique ID (UID)
2
1/// Get this device's unique 96-bit ID. 3/// Get this device's unique 96-bit ID.
2pub fn uid() -> &'static [u8; 12] { 4pub fn uid() -> &'static [u8; 12] {
3 unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() } 5 unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() }
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index a2e4ceaae..962547bd7 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -82,6 +82,7 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
82 } 82 }
83} 83}
84 84
85/// Buffered UART State
85pub struct State { 86pub struct State {
86 rx_waker: AtomicWaker, 87 rx_waker: AtomicWaker,
87 rx_buf: RingBuffer, 88 rx_buf: RingBuffer,
@@ -91,6 +92,7 @@ pub struct State {
91} 92}
92 93
93impl State { 94impl State {
95 /// Create new state
94 pub const fn new() -> Self { 96 pub const fn new() -> Self {
95 Self { 97 Self {
96 rx_buf: RingBuffer::new(), 98 rx_buf: RingBuffer::new(),
@@ -101,15 +103,18 @@ impl State {
101 } 103 }
102} 104}
103 105
106/// Bidirectional buffered UART
104pub struct BufferedUart<'d, T: BasicInstance> { 107pub struct BufferedUart<'d, T: BasicInstance> {
105 rx: BufferedUartRx<'d, T>, 108 rx: BufferedUartRx<'d, T>,
106 tx: BufferedUartTx<'d, T>, 109 tx: BufferedUartTx<'d, T>,
107} 110}
108 111
112/// Tx-only buffered UART
109pub struct BufferedUartTx<'d, T: BasicInstance> { 113pub struct BufferedUartTx<'d, T: BasicInstance> {
110 phantom: PhantomData<&'d mut T>, 114 phantom: PhantomData<&'d mut T>,
111} 115}
112 116
117/// Rx-only buffered UART
113pub struct BufferedUartRx<'d, T: BasicInstance> { 118pub struct BufferedUartRx<'d, T: BasicInstance> {
114 phantom: PhantomData<&'d mut T>, 119 phantom: PhantomData<&'d mut T>,
115} 120}
@@ -142,6 +147,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
142} 147}
143 148
144impl<'d, T: BasicInstance> BufferedUart<'d, T> { 149impl<'d, T: BasicInstance> BufferedUart<'d, T> {
150 /// Create a new bidirectional buffered UART driver
145 pub fn new( 151 pub fn new(
146 peri: impl Peripheral<P = T> + 'd, 152 peri: impl Peripheral<P = T> + 'd,
147 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 153 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -158,6 +164,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
158 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 164 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
159 } 165 }
160 166
167 /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
161 pub fn new_with_rtscts( 168 pub fn new_with_rtscts(
162 peri: impl Peripheral<P = T> + 'd, 169 peri: impl Peripheral<P = T> + 'd,
163 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 170 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -185,6 +192,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
185 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 192 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
186 } 193 }
187 194
195 /// Create a new bidirectional buffered UART driver with a driver-enable pin
188 #[cfg(not(any(usart_v1, usart_v2)))] 196 #[cfg(not(any(usart_v1, usart_v2)))]
189 pub fn new_with_de( 197 pub fn new_with_de(
190 peri: impl Peripheral<P = T> + 'd, 198 peri: impl Peripheral<P = T> + 'd,
@@ -246,10 +254,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
246 }) 254 })
247 } 255 }
248 256
257 /// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
249 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { 258 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
250 (self.tx, self.rx) 259 (self.tx, self.rx)
251 } 260 }
252 261
262 /// Reconfigure the driver
253 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 263 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
254 reconfigure::<T>(config)?; 264 reconfigure::<T>(config)?;
255 265
@@ -337,6 +347,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
337 } 347 }
338 } 348 }
339 349
350 /// Reconfigure the driver
340 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 351 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
341 reconfigure::<T>(config)?; 352 reconfigure::<T>(config)?;
342 353
@@ -418,6 +429,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
418 } 429 }
419 } 430 }
420 431
432 /// Reconfigure the driver
421 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 433 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
422 reconfigure::<T>(config)?; 434 reconfigure::<T>(config)?;
423 435
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index dfa1f3a6a..8a0c85d2c 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,4 +1,6 @@
1//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
1#![macro_use] 2#![macro_use]
3#![warn(missing_docs)]
2 4
3use core::future::poll_fn; 5use core::future::poll_fn;
4use core::marker::PhantomData; 6use core::marker::PhantomData;
@@ -76,21 +78,29 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
76 78
77#[derive(Clone, Copy, PartialEq, Eq, Debug)] 79#[derive(Clone, Copy, PartialEq, Eq, Debug)]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))] 80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81/// Number of data bits
79pub enum DataBits { 82pub enum DataBits {
83 /// 8 Data Bits
80 DataBits8, 84 DataBits8,
85 /// 9 Data Bits
81 DataBits9, 86 DataBits9,
82} 87}
83 88
84#[derive(Clone, Copy, PartialEq, Eq, Debug)] 89#[derive(Clone, Copy, PartialEq, Eq, Debug)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))] 90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91/// Parity
86pub enum Parity { 92pub enum Parity {
93 /// No parity
87 ParityNone, 94 ParityNone,
95 /// Even Parity
88 ParityEven, 96 ParityEven,
97 /// Odd Parity
89 ParityOdd, 98 ParityOdd,
90} 99}
91 100
92#[derive(Clone, Copy, PartialEq, Eq, Debug)] 101#[derive(Clone, Copy, PartialEq, Eq, Debug)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))] 102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103/// Number of stop bits
94pub enum StopBits { 104pub enum StopBits {
95 #[doc = "1 stop bit"] 105 #[doc = "1 stop bit"]
96 STOP1, 106 STOP1,
@@ -105,26 +115,37 @@ pub enum StopBits {
105#[non_exhaustive] 115#[non_exhaustive]
106#[derive(Clone, Copy, PartialEq, Eq, Debug)] 116#[derive(Clone, Copy, PartialEq, Eq, Debug)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))] 117#[cfg_attr(feature = "defmt", derive(defmt::Format))]
118/// Config Error
108pub enum ConfigError { 119pub enum ConfigError {
120 /// Baudrate too low
109 BaudrateTooLow, 121 BaudrateTooLow,
122 /// Baudrate too high
110 BaudrateTooHigh, 123 BaudrateTooHigh,
124 /// Rx or Tx not enabled
111 RxOrTxNotEnabled, 125 RxOrTxNotEnabled,
112} 126}
113 127
114#[non_exhaustive] 128#[non_exhaustive]
115#[derive(Clone, Copy, PartialEq, Eq, Debug)] 129#[derive(Clone, Copy, PartialEq, Eq, Debug)]
130/// Config
116pub struct Config { 131pub struct Config {
132 /// Baud rate
117 pub baudrate: u32, 133 pub baudrate: u32,
134 /// Number of data bits
118 pub data_bits: DataBits, 135 pub data_bits: DataBits,
136 /// Number of stop bits
119 pub stop_bits: StopBits, 137 pub stop_bits: StopBits,
138 /// Parity type
120 pub parity: Parity, 139 pub parity: Parity,
121 /// if true, on read-like method, if there is a latent error pending, 140
122 /// read will abort, the error reported and cleared 141 /// If true: on a read-like method, if there is a latent error pending,
123 /// if false, the error is ignored and cleared 142 /// the read will abort and the error will be reported and cleared
143 ///
144 /// If false: the error is ignored and cleared
124 pub detect_previous_overrun: bool, 145 pub detect_previous_overrun: bool,
125 146
126 /// Set this to true if the line is considered noise free. 147 /// Set this to true if the line is considered noise free.
127 /// This will increase the receivers tolerance to clock deviations, 148 /// This will increase the receiver’s tolerance to clock deviations,
128 /// but will effectively disable noise detection. 149 /// but will effectively disable noise detection.
129 #[cfg(not(usart_v1))] 150 #[cfg(not(usart_v1))]
130 pub assume_noise_free: bool, 151 pub assume_noise_free: bool,
@@ -187,6 +208,7 @@ enum ReadCompletionEvent {
187 Idle(usize), 208 Idle(usize),
188} 209}
189 210
211/// Bidirectional UART Driver
190pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { 212pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
191 tx: UartTx<'d, T, TxDma>, 213 tx: UartTx<'d, T, TxDma>,
192 rx: UartRx<'d, T, RxDma>, 214 rx: UartRx<'d, T, RxDma>,
@@ -202,6 +224,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma>
202 } 224 }
203} 225}
204 226
227/// Tx-only UART Driver
205pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { 228pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
206 phantom: PhantomData<&'d mut T>, 229 phantom: PhantomData<&'d mut T>,
207 tx_dma: PeripheralRef<'d, TxDma>, 230 tx_dma: PeripheralRef<'d, TxDma>,
@@ -216,6 +239,7 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
216 } 239 }
217} 240}
218 241
242/// Rx-only UART Driver
219pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 243pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
220 _peri: PeripheralRef<'d, T>, 244 _peri: PeripheralRef<'d, T>,
221 rx_dma: PeripheralRef<'d, RxDma>, 245 rx_dma: PeripheralRef<'d, RxDma>,
@@ -246,6 +270,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
246 Self::new_inner(peri, tx, tx_dma, config) 270 Self::new_inner(peri, tx, tx_dma, config)
247 } 271 }
248 272
273 /// Create a new tx-only UART with a clear-to-send pin
249 pub fn new_with_cts( 274 pub fn new_with_cts(
250 peri: impl Peripheral<P = T> + 'd, 275 peri: impl Peripheral<P = T> + 'd,
251 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 276 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@@ -287,10 +312,12 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
287 }) 312 })
288 } 313 }
289 314
315 /// Reconfigure the driver
290 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 316 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
291 reconfigure::<T>(config) 317 reconfigure::<T>(config)
292 } 318 }
293 319
320 /// Initiate an asynchronous UART write
294 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 321 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
295 where 322 where
296 TxDma: crate::usart::TxDma<T>, 323 TxDma: crate::usart::TxDma<T>,
@@ -307,6 +334,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
307 Ok(()) 334 Ok(())
308 } 335 }
309 336
337 /// Perform a blocking UART write
310 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 338 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
311 let r = T::regs(); 339 let r = T::regs();
312 for &b in buffer { 340 for &b in buffer {
@@ -316,6 +344,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
316 Ok(()) 344 Ok(())
317 } 345 }
318 346
347 /// Block until transmission complete
319 pub fn blocking_flush(&mut self) -> Result<(), Error> { 348 pub fn blocking_flush(&mut self) -> Result<(), Error> {
320 let r = T::regs(); 349 let r = T::regs();
321 while !sr(r).read().tc() {} 350 while !sr(r).read().tc() {}
@@ -337,6 +366,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
337 Self::new_inner(peri, rx, rx_dma, config) 366 Self::new_inner(peri, rx, rx_dma, config)
338 } 367 }
339 368
369 /// Create a new rx-only UART with a request-to-send pin
340 pub fn new_with_rts( 370 pub fn new_with_rts(
341 peri: impl Peripheral<P = T> + 'd, 371 peri: impl Peripheral<P = T> + 'd,
342 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 372 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -386,6 +416,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
386 }) 416 })
387 } 417 }
388 418
419 /// Reconfigure the driver
389 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 420 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
390 reconfigure::<T>(config) 421 reconfigure::<T>(config)
391 } 422 }
@@ -443,6 +474,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
443 Ok(sr.rxne()) 474 Ok(sr.rxne())
444 } 475 }
445 476
477 /// Initiate an asynchronous UART read
446 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 478 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
447 where 479 where
448 RxDma: crate::usart::RxDma<T>, 480 RxDma: crate::usart::RxDma<T>,
@@ -452,6 +484,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
452 Ok(()) 484 Ok(())
453 } 485 }
454 486
487 /// Read a single u8 if there is one available, otherwise return WouldBlock
455 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 488 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
456 let r = T::regs(); 489 let r = T::regs();
457 if self.check_rx_flags()? { 490 if self.check_rx_flags()? {
@@ -461,6 +494,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
461 } 494 }
462 } 495 }
463 496
497 /// Perform a blocking read into `buffer`
464 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 498 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
465 let r = T::regs(); 499 let r = T::regs();
466 for b in buffer { 500 for b in buffer {
@@ -470,6 +504,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
470 Ok(()) 504 Ok(())
471 } 505 }
472 506
507 /// Initiate an asynchronous read with idle line detection enabled
473 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> 508 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
474 where 509 where
475 RxDma: crate::usart::RxDma<T>, 510 RxDma: crate::usart::RxDma<T>,
@@ -694,6 +729,7 @@ impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
694} 729}
695 730
696impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 731impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
732 /// Create a new bidirectional UART
697 pub fn new( 733 pub fn new(
698 peri: impl Peripheral<P = T> + 'd, 734 peri: impl Peripheral<P = T> + 'd,
699 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 735 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -710,6 +746,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
710 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) 746 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
711 } 747 }
712 748
749 /// Create a new bidirectional UART with request-to-send and clear-to-send pins
713 pub fn new_with_rtscts( 750 pub fn new_with_rtscts(
714 peri: impl Peripheral<P = T> + 'd, 751 peri: impl Peripheral<P = T> + 'd,
715 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 752 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -737,6 +774,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
737 } 774 }
738 775
739 #[cfg(not(any(usart_v1, usart_v2)))] 776 #[cfg(not(any(usart_v1, usart_v2)))]
777 /// Create a new bidirectional UART with a driver-enable pin
740 pub fn new_with_de( 778 pub fn new_with_de(
741 peri: impl Peripheral<P = T> + 'd, 779 peri: impl Peripheral<P = T> + 'd,
742 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 780 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -812,6 +850,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
812 }) 850 })
813 } 851 }
814 852
853 /// Initiate an asynchronous write
815 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 854 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
816 where 855 where
817 TxDma: crate::usart::TxDma<T>, 856 TxDma: crate::usart::TxDma<T>,
@@ -819,14 +858,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
819 self.tx.write(buffer).await 858 self.tx.write(buffer).await
820 } 859 }
821 860
861 /// Perform a blocking write
822 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 862 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
823 self.tx.blocking_write(buffer) 863 self.tx.blocking_write(buffer)
824 } 864 }
825 865
866 /// Block until transmission complete
826 pub fn blocking_flush(&mut self) -> Result<(), Error> { 867 pub fn blocking_flush(&mut self) -> Result<(), Error> {
827 self.tx.blocking_flush() 868 self.tx.blocking_flush()
828 } 869 }
829 870
871 /// Initiate an asynchronous read into `buffer`
830 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 872 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
831 where 873 where
832 RxDma: crate::usart::RxDma<T>, 874 RxDma: crate::usart::RxDma<T>,
@@ -834,14 +876,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
834 self.rx.read(buffer).await 876 self.rx.read(buffer).await
835 } 877 }
836 878
879 /// Read a single `u8` or return `WouldBlock`
837 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 880 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
838 self.rx.nb_read() 881 self.rx.nb_read()
839 } 882 }
840 883
884 /// Perform a blocking read into `buffer`
841 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 885 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
842 self.rx.blocking_read(buffer) 886 self.rx.blocking_read(buffer)
843 } 887 }
844 888
889 /// Initiate an an asynchronous read with idle line detection enabled
845 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> 890 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
846 where 891 where
847 RxDma: crate::usart::RxDma<T>, 892 RxDma: crate::usart::RxDma<T>,
@@ -1291,8 +1336,10 @@ pub(crate) mod sealed {
1291 } 1336 }
1292} 1337}
1293 1338
1339/// Basic UART driver instance
1294pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} 1340pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
1295 1341
1342/// Full UART driver instance
1296pub trait FullInstance: sealed::FullInstance {} 1343pub trait FullInstance: sealed::FullInstance {}
1297 1344
1298pin_trait!(RxPin, BasicInstance); 1345pin_trait!(RxPin, BasicInstance);
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index b8d17e4e4..4391bfef7 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -11,6 +11,7 @@ use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config,
11use crate::dma::ReadableRingBuffer; 11use crate::dma::ReadableRingBuffer;
12use crate::usart::{Regs, Sr}; 12use crate::usart::{Regs, Sr};
13 13
14/// Rx-only Ring-buffered UART Driver
14pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> { 15pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
15 _peri: PeripheralRef<'d, T>, 16 _peri: PeripheralRef<'d, T>,
16 ring_buf: ReadableRingBuffer<'d, RxDma, u8>, 17 ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
@@ -27,8 +28,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUar
27 28
28impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { 29impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
29 /// Turn the `UartRx` into a buffered uart which can continously receive in the background 30 /// Turn the `UartRx` into a buffered uart which can continously receive in the background
30 /// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the 31 /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
31 /// DMA controller, and must be sufficiently large, such that it will not overflow. 32 /// DMA controller, and must be large enough to prevent overflows.
32 pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> { 33 pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
33 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 34 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
34 35
@@ -39,7 +40,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
39 let rx_dma = unsafe { self.rx_dma.clone_unchecked() }; 40 let rx_dma = unsafe { self.rx_dma.clone_unchecked() };
40 let _peri = unsafe { self._peri.clone_unchecked() }; 41 let _peri = unsafe { self._peri.clone_unchecked() };
41 42
42 let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; 43 let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
43 44
44 // Don't disable the clock 45 // Don't disable the clock
45 mem::forget(self); 46 mem::forget(self);
@@ -49,6 +50,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
49} 50}
50 51
51impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> { 52impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
53 /// Clear the ring buffer and start receiving in the background
52 pub fn start(&mut self) -> Result<(), Error> { 54 pub fn start(&mut self) -> Result<(), Error> {
53 // Clear the ring buffer so that it is ready to receive data 55 // Clear the ring buffer so that it is ready to receive data
54 self.ring_buf.clear(); 56 self.ring_buf.clear();
@@ -64,6 +66,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
64 Err(err) 66 Err(err)
65 } 67 }
66 68
69 /// Cleanly stop and reconfigure the driver
67 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 70 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
68 self.teardown_uart(); 71 self.teardown_uart();
69 reconfigure::<T>(config) 72 reconfigure::<T>(config)
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs
index d0b289462..4debd4e54 100644
--- a/embassy-stm32/src/usb/mod.rs
+++ b/embassy-stm32/src/usb/mod.rs
@@ -1,3 +1,5 @@
1//! Universal Serial Bus (USB)
2
1use crate::interrupt; 3use crate::interrupt;
2use crate::rcc::RccPeripheral; 4use crate::rcc::RccPeripheral;
3 5
@@ -10,7 +12,9 @@ pub(crate) mod sealed {
10 } 12 }
11} 13}
12 14
15/// USB instance trait.
13pub trait Instance: sealed::Instance + RccPeripheral + 'static { 16pub trait Instance: sealed::Instance + RccPeripheral + 'static {
17 /// Interrupt for this USB instance.
14 type Interrupt: interrupt::typelevel::Interrupt; 18 type Interrupt: interrupt::typelevel::Interrupt;
15} 19}
16 20
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 295dc9198..a8aebfe1f 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -244,6 +244,7 @@ struct EndpointData {
244 used_out: bool, 244 used_out: bool,
245} 245}
246 246
247/// USB driver.
247pub struct Driver<'d, T: Instance> { 248pub struct Driver<'d, T: Instance> {
248 phantom: PhantomData<&'d mut T>, 249 phantom: PhantomData<&'d mut T>,
249 alloc: [EndpointData; EP_COUNT], 250 alloc: [EndpointData; EP_COUNT],
@@ -251,6 +252,7 @@ pub struct Driver<'d, T: Instance> {
251} 252}
252 253
253impl<'d, T: Instance> Driver<'d, T> { 254impl<'d, T: Instance> Driver<'d, T> {
255 /// Create a new USB driver.
254 pub fn new( 256 pub fn new(
255 _usb: impl Peripheral<P = T> + 'd, 257 _usb: impl Peripheral<P = T> + 'd,
256 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 258 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -465,6 +467,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
465 } 467 }
466} 468}
467 469
470/// USB bus.
468pub struct Bus<'d, T: Instance> { 471pub struct Bus<'d, T: Instance> {
469 phantom: PhantomData<&'d mut T>, 472 phantom: PhantomData<&'d mut T>,
470 ep_types: [EpType; EP_COUNT - 1], 473 ep_types: [EpType; EP_COUNT - 1],
@@ -640,6 +643,7 @@ trait Dir {
640 fn waker(i: usize) -> &'static AtomicWaker; 643 fn waker(i: usize) -> &'static AtomicWaker;
641} 644}
642 645
646/// Marker type for the "IN" direction.
643pub enum In {} 647pub enum In {}
644impl Dir for In { 648impl Dir for In {
645 fn dir() -> Direction { 649 fn dir() -> Direction {
@@ -652,6 +656,7 @@ impl Dir for In {
652 } 656 }
653} 657}
654 658
659/// Marker type for the "OUT" direction.
655pub enum Out {} 660pub enum Out {}
656impl Dir for Out { 661impl Dir for Out {
657 fn dir() -> Direction { 662 fn dir() -> Direction {
@@ -664,6 +669,7 @@ impl Dir for Out {
664 } 669 }
665} 670}
666 671
672/// USB endpoint.
667pub struct Endpoint<'d, T: Instance, D> { 673pub struct Endpoint<'d, T: Instance, D> {
668 _phantom: PhantomData<(&'d mut T, D)>, 674 _phantom: PhantomData<(&'d mut T, D)>,
669 info: EndpointInfo, 675 info: EndpointInfo,
@@ -813,6 +819,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
813 } 819 }
814} 820}
815 821
822/// USB control pipe.
816pub struct ControlPipe<'d, T: Instance> { 823pub struct ControlPipe<'d, T: Instance> {
817 _phantom: PhantomData<&'d mut T>, 824 _phantom: PhantomData<&'d mut T>,
818 max_packet_size: u16, 825 max_packet_size: u16,
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs
index be54a3d10..0649e684b 100644
--- a/embassy-stm32/src/usb_otg/mod.rs
+++ b/embassy-stm32/src/usb_otg/mod.rs
@@ -1,3 +1,5 @@
1//! USB On The Go (OTG)
2
1use crate::rcc::RccPeripheral; 3use crate::rcc::RccPeripheral;
2use crate::{interrupt, peripherals}; 4use crate::{interrupt, peripherals};
3 5
@@ -18,7 +20,9 @@ pub(crate) mod sealed {
18 } 20 }
19} 21}
20 22
23/// USB OTG instance.
21pub trait Instance: sealed::Instance + RccPeripheral { 24pub trait Instance: sealed::Instance + RccPeripheral {
25 /// Interrupt for this USB OTG instance.
22 type Interrupt: interrupt::typelevel::Interrupt; 26 type Interrupt: interrupt::typelevel::Interrupt;
23} 27}
24 28
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index ba77bfb16..190fb274f 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -204,6 +204,7 @@ pub enum PhyType {
204} 204}
205 205
206impl PhyType { 206impl PhyType {
207 /// Get whether this PHY is any of the internal types.
207 pub fn internal(&self) -> bool { 208 pub fn internal(&self) -> bool {
208 match self { 209 match self {
209 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true, 210 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
@@ -211,6 +212,7 @@ impl PhyType {
211 } 212 }
212 } 213 }
213 214
215 /// Get whether this PHY is any of the high-speed types.
214 pub fn high_speed(&self) -> bool { 216 pub fn high_speed(&self) -> bool {
215 match self { 217 match self {
216 PhyType::InternalFullSpeed => false, 218 PhyType::InternalFullSpeed => false,
@@ -218,7 +220,7 @@ impl PhyType {
218 } 220 }
219 } 221 }
220 222
221 pub fn to_dspd(&self) -> vals::Dspd { 223 fn to_dspd(&self) -> vals::Dspd {
222 match self { 224 match self {
223 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL, 225 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
224 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED, 226 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
@@ -230,6 +232,7 @@ impl PhyType {
230/// Indicates that [State::ep_out_buffers] is empty. 232/// Indicates that [State::ep_out_buffers] is empty.
231const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; 233const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
232 234
235/// USB OTG driver state.
233pub struct State<const EP_COUNT: usize> { 236pub struct State<const EP_COUNT: usize> {
234 /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. 237 /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
235 ep0_setup_data: UnsafeCell<[u8; 8]>, 238 ep0_setup_data: UnsafeCell<[u8; 8]>,
@@ -247,6 +250,7 @@ unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
247unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {} 250unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
248 251
249impl<const EP_COUNT: usize> State<EP_COUNT> { 252impl<const EP_COUNT: usize> State<EP_COUNT> {
253 /// Create a new State.
250 pub const fn new() -> Self { 254 pub const fn new() -> Self {
251 const NEW_AW: AtomicWaker = AtomicWaker::new(); 255 const NEW_AW: AtomicWaker = AtomicWaker::new();
252 const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); 256 const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
@@ -271,6 +275,7 @@ struct EndpointData {
271 fifo_size_words: u16, 275 fifo_size_words: u16,
272} 276}
273 277
278/// USB driver config.
274#[non_exhaustive] 279#[non_exhaustive]
275#[derive(Clone, Copy, PartialEq, Eq, Debug)] 280#[derive(Clone, Copy, PartialEq, Eq, Debug)]
276pub struct Config { 281pub struct Config {
@@ -297,6 +302,7 @@ impl Default for Config {
297 } 302 }
298} 303}
299 304
305/// USB driver.
300pub struct Driver<'d, T: Instance> { 306pub struct Driver<'d, T: Instance> {
301 config: Config, 307 config: Config,
302 phantom: PhantomData<&'d mut T>, 308 phantom: PhantomData<&'d mut T>,
@@ -527,6 +533,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
527 } 533 }
528} 534}
529 535
536/// USB bus.
530pub struct Bus<'d, T: Instance> { 537pub struct Bus<'d, T: Instance> {
531 config: Config, 538 config: Config,
532 phantom: PhantomData<&'d mut T>, 539 phantom: PhantomData<&'d mut T>,
@@ -1092,6 +1099,7 @@ trait Dir {
1092 fn dir() -> Direction; 1099 fn dir() -> Direction;
1093} 1100}
1094 1101
1102/// Marker type for the "IN" direction.
1095pub enum In {} 1103pub enum In {}
1096impl Dir for In { 1104impl Dir for In {
1097 fn dir() -> Direction { 1105 fn dir() -> Direction {
@@ -1099,6 +1107,7 @@ impl Dir for In {
1099 } 1107 }
1100} 1108}
1101 1109
1110/// Marker type for the "OUT" direction.
1102pub enum Out {} 1111pub enum Out {}
1103impl Dir for Out { 1112impl Dir for Out {
1104 fn dir() -> Direction { 1113 fn dir() -> Direction {
@@ -1106,6 +1115,7 @@ impl Dir for Out {
1106 } 1115 }
1107} 1116}
1108 1117
1118/// USB endpoint.
1109pub struct Endpoint<'d, T: Instance, D> { 1119pub struct Endpoint<'d, T: Instance, D> {
1110 _phantom: PhantomData<(&'d mut T, D)>, 1120 _phantom: PhantomData<(&'d mut T, D)>,
1111 info: EndpointInfo, 1121 info: EndpointInfo,
@@ -1299,6 +1309,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1299 } 1309 }
1300} 1310}
1301 1311
1312/// USB control pipe.
1302pub struct ControlPipe<'d, T: Instance> { 1313pub struct ControlPipe<'d, T: Instance> {
1303 _phantom: PhantomData<&'d mut T>, 1314 _phantom: PhantomData<&'d mut T>,
1304 max_packet_size: u16, 1315 max_packet_size: u16,
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index c7c2694e0..dc701ef64 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -1,3 +1,4 @@
1//! Watchdog Timer (IWDG, WWDG)
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_hal_internal::{into_ref, Peripheral}; 4use embassy_hal_internal::{into_ref, Peripheral};
@@ -5,6 +6,7 @@ use stm32_metapac::iwdg::vals::{Key, Pr};
5 6
6use crate::rcc::LSI_FREQ; 7use crate::rcc::LSI_FREQ;
7 8
9/// Independent watchdog (IWDG) driver.
8pub struct IndependentWatchdog<'d, T: Instance> { 10pub struct IndependentWatchdog<'d, T: Instance> {
9 wdg: PhantomData<&'d mut T>, 11 wdg: PhantomData<&'d mut T>,
10} 12}
@@ -63,10 +65,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
63 IndependentWatchdog { wdg: PhantomData } 65 IndependentWatchdog { wdg: PhantomData }
64 } 66 }
65 67
68 /// Unleash (start) the watchdog.
66 pub fn unleash(&mut self) { 69 pub fn unleash(&mut self) {
67 T::regs().kr().write(|w| w.set_key(Key::START)); 70 T::regs().kr().write(|w| w.set_key(Key::START));
68 } 71 }
69 72
73 /// Pet (reload, refresh) the watchdog.
70 pub fn pet(&mut self) { 74 pub fn pet(&mut self) {
71 T::regs().kr().write(|w| w.set_key(Key::RESET)); 75 T::regs().kr().write(|w| w.set_key(Key::RESET));
72 } 76 }
@@ -78,6 +82,7 @@ mod sealed {
78 } 82 }
79} 83}
80 84
85/// IWDG instance trait.
81pub trait Instance: sealed::Instance {} 86pub trait Instance: sealed::Instance {}
82 87
83foreach_peripheral!( 88foreach_peripheral!(
diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs
index bea67d8be..d75750ce7 100644
--- a/embassy-sync/src/signal.rs
+++ b/embassy-sync/src/signal.rs
@@ -111,6 +111,20 @@ where
111 poll_fn(move |cx| self.poll_wait(cx)) 111 poll_fn(move |cx| self.poll_wait(cx))
112 } 112 }
113 113
114 /// non-blocking method to try and take the signal value.
115 pub fn try_take(&self) -> Option<T> {
116 self.state.lock(|cell| {
117 let state = cell.replace(State::None);
118 match state {
119 State::Signaled(res) => Some(res),
120 state => {
121 cell.set(state);
122 None
123 }
124 }
125 })
126 }
127
114 /// non-blocking method to check whether this signal has been signaled. 128 /// non-blocking method to check whether this signal has been signaled.
115 pub fn signaled(&self) -> bool { 129 pub fn signaled(&self) -> bool {
116 self.state.lock(|cell| { 130 self.state.lock(|cell| {
diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs
index 5fe7becaf..81ee1b0f5 100644
--- a/embassy-time/src/driver.rs
+++ b/embassy-time/src/driver.rs
@@ -108,6 +108,10 @@ pub trait Driver: Send + Sync + 'static {
108 /// The `Driver` implementation should guarantee that the alarm callback is never called synchronously from `set_alarm`. 108 /// The `Driver` implementation should guarantee that the alarm callback is never called synchronously from `set_alarm`.
109 /// Rather - if `timestamp` is already in the past - `false` should be returned and alarm should not be set, 109 /// Rather - if `timestamp` is already in the past - `false` should be returned and alarm should not be set,
110 /// or alternatively, the driver should return `true` and arrange to call the alarm callback as soon as possible, but not synchronously. 110 /// or alternatively, the driver should return `true` and arrange to call the alarm callback as soon as possible, but not synchronously.
111 /// There is a rare third possibility that the alarm was barely in the future, and by the time it was enabled, it had slipped into the
112 /// past. This is can be detected by double-checking that the alarm is still in the future after enabling it; if it isn't, `false`
113 /// should also be returned to indicate that the callback may have been called already by the alarm, but it is not guaranteed, so the
114 /// caller should also call the callback, just like in the more common `false` case. (Note: This requires idempotency of the callback.)
111 /// 115 ///
112 /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. 116 /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp.
113 /// 117 ///
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs
index 574d715da..2705ba03f 100644
--- a/embassy-time/src/timer.rs
+++ b/embassy-time/src/timer.rs
@@ -47,9 +47,6 @@ impl Timer {
47 /// 47 ///
48 /// Example: 48 /// Example:
49 /// ``` no_run 49 /// ``` no_run
50 /// # #![feature(type_alias_impl_trait)]
51 /// #
52 /// # fn foo() {}
53 /// use embassy_time::{Duration, Timer}; 50 /// use embassy_time::{Duration, Timer};
54 /// 51 ///
55 /// #[embassy_executor::task] 52 /// #[embassy_executor::task]
@@ -132,8 +129,6 @@ impl Future for Timer {
132/// 129///
133/// For instance, consider the following code fragment. 130/// For instance, consider the following code fragment.
134/// ``` no_run 131/// ``` no_run
135/// # #![feature(type_alias_impl_trait)]
136/// #
137/// use embassy_time::{Duration, Timer}; 132/// use embassy_time::{Duration, Timer};
138/// # fn foo() {} 133/// # fn foo() {}
139/// 134///
@@ -152,8 +147,6 @@ impl Future for Timer {
152/// Example using ticker, which will consistently call `foo` once a second. 147/// Example using ticker, which will consistently call `foo` once a second.
153/// 148///
154/// ``` no_run 149/// ``` no_run
155/// # #![feature(type_alias_impl_trait)]
156/// #
157/// use embassy_time::{Duration, Ticker}; 150/// use embassy_time::{Duration, Ticker};
158/// # fn foo(){} 151/// # fn foo(){}
159/// 152///
diff --git a/embassy-usb-dfu/README.md b/embassy-usb-dfu/README.md
new file mode 100644
index 000000000..d8bc19bfd
--- /dev/null
+++ b/embassy-usb-dfu/README.md
@@ -0,0 +1,20 @@
1# embassy-usb-dfu
2
3An implementation of the USB DFU 1.1 protocol using embassy-boot. It has 2 components depending on which feature is enabled by the user.
4
5* DFU protocol mode, enabled by the `dfu` feature. This mode corresponds to the transfer phase DFU protocol described by the USB IF. It supports DFU_DNLOAD requests if marked by the user, and will automatically reset the chip once a DFU transaction has been completed. It also responds to DFU_GETSTATUS, DFU_GETSTATE, DFU_ABORT, and DFU_CLRSTATUS with no user intervention.
6* DFU runtime mode, enabled by the `application feature`. This mode allows users to expose a DFU interface on their USB device, informing the host of the capability to DFU over USB, and allowing the host to reset the device into its bootloader to complete a DFU operation. Supports DFU_GETSTATUS and DFU_DETACH. When detach/reset is seen by the device as described by the standard, will write a new DFU magic number into the bootloader state in flash, and reset the system.
7
8## Minimum supported Rust version (MSRV)
9
10Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
11
12## License
13
14This work is licensed under either of
15
16- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
17 <http://www.apache.org/licenses/LICENSE-2.0>)
18- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
19
20at your option.
diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs
index 75689db26..f0d7626f6 100644
--- a/embassy-usb-dfu/src/application.rs
+++ b/embassy-usb-dfu/src/application.rs
@@ -24,6 +24,7 @@ pub struct Control<'d, STATE: NorFlash, RST: Reset> {
24} 24}
25 25
26impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> { 26impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> {
27 /// Create a new DFU instance to expose a DFU interface.
27 pub fn new(firmware_state: BlockingFirmwareState<'d, STATE>, attrs: DfuAttributes) -> Self { 28 pub fn new(firmware_state: BlockingFirmwareState<'d, STATE>, attrs: DfuAttributes) -> Self {
28 Control { 29 Control {
29 firmware_state, 30 firmware_state,
diff --git a/embassy-usb-dfu/src/consts.rs b/embassy-usb-dfu/src/consts.rs
index b359a107e..f8a056e5c 100644
--- a/embassy-usb-dfu/src/consts.rs
+++ b/embassy-usb-dfu/src/consts.rs
@@ -1,3 +1,4 @@
1//! USB DFU constants.
1pub(crate) const USB_CLASS_APPN_SPEC: u8 = 0xFE; 2pub(crate) const USB_CLASS_APPN_SPEC: u8 = 0xFE;
2pub(crate) const APPN_SPEC_SUBCLASS_DFU: u8 = 0x01; 3pub(crate) const APPN_SPEC_SUBCLASS_DFU: u8 = 0x01;
3#[allow(unused)] 4#[allow(unused)]
@@ -18,10 +19,15 @@ defmt::bitflags! {
18 19
19#[cfg(not(feature = "defmt"))] 20#[cfg(not(feature = "defmt"))]
20bitflags::bitflags! { 21bitflags::bitflags! {
22 /// Attributes supported by the DFU controller.
21 pub struct DfuAttributes: u8 { 23 pub struct DfuAttributes: u8 {
24 /// Generate WillDetache sequence on bus.
22 const WILL_DETACH = 0b0000_1000; 25 const WILL_DETACH = 0b0000_1000;
26 /// Device can communicate during manifestation phase.
23 const MANIFESTATION_TOLERANT = 0b0000_0100; 27 const MANIFESTATION_TOLERANT = 0b0000_0100;
28 /// Capable of upload.
24 const CAN_UPLOAD = 0b0000_0010; 29 const CAN_UPLOAD = 0b0000_0010;
30 /// Capable of download.
25 const CAN_DOWNLOAD = 0b0000_0001; 31 const CAN_DOWNLOAD = 0b0000_0001;
26 } 32 }
27} 33}
@@ -29,7 +35,7 @@ bitflags::bitflags! {
29#[derive(Copy, Clone, PartialEq, Eq)] 35#[derive(Copy, Clone, PartialEq, Eq)]
30#[repr(u8)] 36#[repr(u8)]
31#[allow(unused)] 37#[allow(unused)]
32pub enum State { 38pub(crate) enum State {
33 AppIdle = 0, 39 AppIdle = 0,
34 AppDetach = 1, 40 AppDetach = 1,
35 DfuIdle = 2, 41 DfuIdle = 2,
@@ -46,7 +52,7 @@ pub enum State {
46#[derive(Copy, Clone, PartialEq, Eq)] 52#[derive(Copy, Clone, PartialEq, Eq)]
47#[repr(u8)] 53#[repr(u8)]
48#[allow(unused)] 54#[allow(unused)]
49pub enum Status { 55pub(crate) enum Status {
50 Ok = 0x00, 56 Ok = 0x00,
51 ErrTarget = 0x01, 57 ErrTarget = 0x01,
52 ErrFile = 0x02, 58 ErrFile = 0x02,
@@ -67,7 +73,7 @@ pub enum Status {
67 73
68#[derive(Copy, Clone, PartialEq, Eq)] 74#[derive(Copy, Clone, PartialEq, Eq)]
69#[repr(u8)] 75#[repr(u8)]
70pub enum Request { 76pub(crate) enum Request {
71 Detach = 0, 77 Detach = 0,
72 Dnload = 1, 78 Dnload = 1,
73 Upload = 2, 79 Upload = 2,
diff --git a/embassy-usb-dfu/src/bootloader.rs b/embassy-usb-dfu/src/dfu.rs
index d41e6280d..e99aa70c3 100644
--- a/embassy-usb-dfu/src/bootloader.rs
+++ b/embassy-usb-dfu/src/dfu.rs
@@ -23,6 +23,7 @@ pub struct Control<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_S
23} 23}
24 24
25impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Control<'d, DFU, STATE, RST, BLOCK_SIZE> { 25impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Control<'d, DFU, STATE, RST, BLOCK_SIZE> {
26 /// Create a new DFU instance to handle DFU transfers.
26 pub fn new(updater: BlockingFirmwareUpdater<'d, DFU, STATE>, attrs: DfuAttributes) -> Self { 27 pub fn new(updater: BlockingFirmwareUpdater<'d, DFU, STATE>, attrs: DfuAttributes) -> Self {
27 Self { 28 Self {
28 updater, 29 updater,
diff --git a/embassy-usb-dfu/src/lib.rs b/embassy-usb-dfu/src/lib.rs
index 389bb33f2..eaa4b6e33 100644
--- a/embassy-usb-dfu/src/lib.rs
+++ b/embassy-usb-dfu/src/lib.rs
@@ -1,12 +1,14 @@
1#![no_std] 1#![no_std]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
2mod fmt; 4mod fmt;
3 5
4pub mod consts; 6pub mod consts;
5 7
6#[cfg(feature = "dfu")] 8#[cfg(feature = "dfu")]
7mod bootloader; 9mod dfu;
8#[cfg(feature = "dfu")] 10#[cfg(feature = "dfu")]
9pub use self::bootloader::*; 11pub use self::dfu::*;
10 12
11#[cfg(feature = "application")] 13#[cfg(feature = "application")]
12mod application; 14mod application;
@@ -17,7 +19,7 @@ pub use self::application::*;
17 all(feature = "dfu", feature = "application"), 19 all(feature = "dfu", feature = "application"),
18 not(any(feature = "dfu", feature = "application")) 20 not(any(feature = "dfu", feature = "application"))
19))] 21))]
20compile_error!("usb-dfu must be compiled with exactly one of `bootloader`, or `application` features"); 22compile_error!("usb-dfu must be compiled with exactly one of `dfu`, or `application` features");
21 23
22/// Provides a platform-agnostic interface for initiating a system reset. 24/// Provides a platform-agnostic interface for initiating a system reset.
23/// 25///
@@ -26,9 +28,11 @@ compile_error!("usb-dfu must be compiled with exactly one of `bootloader`, or `a
26/// 28///
27/// If alternate behaviour is desired, a custom implementation of Reset can be provided as a type argument to the usb_dfu function. 29/// If alternate behaviour is desired, a custom implementation of Reset can be provided as a type argument to the usb_dfu function.
28pub trait Reset { 30pub trait Reset {
31 /// Reset the device.
29 fn sys_reset() -> !; 32 fn sys_reset() -> !;
30} 33}
31 34
35/// Reset immediately.
32#[cfg(feature = "esp32c3-hal")] 36#[cfg(feature = "esp32c3-hal")]
33pub struct ResetImmediate; 37pub struct ResetImmediate;
34 38
@@ -40,6 +44,7 @@ impl Reset for ResetImmediate {
40 } 44 }
41} 45}
42 46
47/// Reset immediately.
43#[cfg(feature = "cortex-m")] 48#[cfg(feature = "cortex-m")]
44pub struct ResetImmediate; 49pub struct ResetImmediate;
45 50
diff --git a/embassy-usb-logger/README.md b/embassy-usb-logger/README.md
index 81b0dcd0e..6cb18e87d 100644
--- a/embassy-usb-logger/README.md
+++ b/embassy-usb-logger/README.md
@@ -13,3 +13,17 @@ async fn logger_task(driver: Driver<'static, USB>) {
13 embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); 13 embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
14} 14}
15``` 15```
16
17## Minimum supported Rust version (MSRV)
18
19Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
20
21## License
22
23This work is licensed under either of
24
25- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
26 <http://www.apache.org/licenses/LICENSE-2.0>)
27- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
28
29at your option.
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index 5f11750b2..b52bac650 100644
--- a/examples/boot/application/nrf/Cargo.toml
+++ b/examples/boot/application/nrf/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [] }
11embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } 11embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] }
12embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = [] } 12embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = [] }
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs
index 8b510ed35..f3abfddbc 100644
--- a/examples/boot/application/nrf/src/bin/a.rs
+++ b/examples/boot/application/nrf/src/bin/a.rs
@@ -1,7 +1,6 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![macro_use] 3#![macro_use]
4#![feature(type_alias_impl_trait)]
5 4
6use embassy_boot_nrf::{FirmwareUpdater, FirmwareUpdaterConfig}; 5use embassy_boot_nrf::{FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 6use embassy_embedded_hal::adapter::BlockingAsync;
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs
index a88c3c56c..de97b6a22 100644
--- a/examples/boot/application/nrf/src/bin/b.rs
+++ b/examples/boot/application/nrf/src/bin/b.rs
@@ -1,7 +1,6 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![macro_use] 3#![macro_use]
4#![feature(type_alias_impl_trait)]
5 4
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 6use embassy_nrf::gpio::{Level, Output, OutputDrive};
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml
index 89ac5a8f6..08ce16877 100644
--- a/examples/boot/application/rp/Cargo.toml
+++ b/examples/boot/application/rp/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [] }
11embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", ] } 11embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", ] }
12embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = [] } 12embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = [] }
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs
index 6fd5d7f60..3f0bf90e2 100644
--- a/examples/boot/application/rp/src/bin/a.rs
+++ b/examples/boot/application/rp/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::cell::RefCell; 4use core::cell::RefCell;
6 5
diff --git a/examples/boot/application/rp/src/bin/b.rs b/examples/boot/application/rp/src/bin/b.rs
index 1eca5b4a2..a46d095bf 100644
--- a/examples/boot/application/rp/src/bin/b.rs
+++ b/examples/boot/application/rp/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_rp::gpio; 5use embassy_rp::gpio;
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml
index 1a0f8cee5..248ec6dce 100644
--- a/examples/boot/application/stm32f3/Cargo.toml
+++ b/examples/boot/application/stm32f3/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs
index 8be39bfb7..96ae5c47b 100644
--- a/examples/boot/application/stm32f3/src/bin/a.rs
+++ b/examples/boot/application/stm32f3/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32f3/src/bin/b.rs b/examples/boot/application/stm32f3/src/bin/b.rs
index 8411f384c..22ba82d5e 100644
--- a/examples/boot/application/stm32f3/src/bin/b.rs
+++ b/examples/boot/application/stm32f3/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml
index e42d1d421..aa5f87615 100644
--- a/examples/boot/application/stm32f7/Cargo.toml
+++ b/examples/boot/application/stm32f7/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs
index 0c3819bed..a6107386a 100644
--- a/examples/boot/application/stm32f7/src/bin/a.rs
+++ b/examples/boot/application/stm32f7/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::cell::RefCell; 4use core::cell::RefCell;
6 5
diff --git a/examples/boot/application/stm32f7/src/bin/b.rs b/examples/boot/application/stm32f7/src/bin/b.rs
index 4c2ad06a2..190477204 100644
--- a/examples/boot/application/stm32f7/src/bin/b.rs
+++ b/examples/boot/application/stm32f7/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml
index 8450d8639..78e33de28 100644
--- a/examples/boot/application/stm32h7/Cargo.toml
+++ b/examples/boot/application/stm32h7/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs
index f239e3732..b73506cf3 100644
--- a/examples/boot/application/stm32h7/src/bin/a.rs
+++ b/examples/boot/application/stm32h7/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::cell::RefCell; 4use core::cell::RefCell;
6 5
diff --git a/examples/boot/application/stm32h7/src/bin/b.rs b/examples/boot/application/stm32h7/src/bin/b.rs
index 5c03e2d0c..5f3f35207 100644
--- a/examples/boot/application/stm32h7/src/bin/b.rs
+++ b/examples/boot/application/stm32h7/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml
index d6684bedb..240afe4c6 100644
--- a/examples/boot/application/stm32l0/Cargo.toml
+++ b/examples/boot/application/stm32l0/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs
index 42e1a71eb..02f74bdef 100644
--- a/examples/boot/application/stm32l0/src/bin/a.rs
+++ b/examples/boot/application/stm32l0/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l0/src/bin/b.rs b/examples/boot/application/stm32l0/src/bin/b.rs
index 52d42395f..6bf00f41a 100644
--- a/examples/boot/application/stm32l0/src/bin/b.rs
+++ b/examples/boot/application/stm32l0/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml
index cca8bf443..97f1e277b 100644
--- a/examples/boot/application/stm32l1/Cargo.toml
+++ b/examples/boot/application/stm32l1/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs
index 42e1a71eb..02f74bdef 100644
--- a/examples/boot/application/stm32l1/src/bin/a.rs
+++ b/examples/boot/application/stm32l1/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l1/src/bin/b.rs b/examples/boot/application/stm32l1/src/bin/b.rs
index 52d42395f..6bf00f41a 100644
--- a/examples/boot/application/stm32l1/src/bin/b.rs
+++ b/examples/boot/application/stm32l1/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml
index 30d61056c..0c3830f97 100644
--- a/examples/boot/application/stm32l4/Cargo.toml
+++ b/examples/boot/application/stm32l4/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs
index eefa25f75..892446968 100644
--- a/examples/boot/application/stm32l4/src/bin/a.rs
+++ b/examples/boot/application/stm32l4/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32l4/src/bin/b.rs b/examples/boot/application/stm32l4/src/bin/b.rs
index 8411f384c..22ba82d5e 100644
--- a/examples/boot/application/stm32l4/src/bin/b.rs
+++ b/examples/boot/application/stm32l4/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml
index f6beea498..cdaee802e 100644
--- a/examples/boot/application/stm32wb-dfu/Cargo.toml
+++ b/examples/boot/application/stm32wb-dfu/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs
index fbecbf23b..b2ccb9e1a 100644
--- a/examples/boot/application/stm32wb-dfu/src/main.rs
+++ b/examples/boot/application/stm32wb-dfu/src/main.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::cell::RefCell; 4use core::cell::RefCell;
6 5
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml
index 7489a2fe9..b5677e148 100644
--- a/examples/boot/application/stm32wl/Cargo.toml
+++ b/examples/boot/application/stm32wl/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.5.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = [] }
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs
index c837e47b5..d9665e6ee 100644
--- a/examples/boot/application/stm32wl/src/bin/a.rs
+++ b/examples/boot/application/stm32wl/src/bin/a.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/boot/application/stm32wl/src/bin/b.rs b/examples/boot/application/stm32wl/src/bin/b.rs
index 1ca3c6ea8..8dd15d8cd 100644
--- a/examples/boot/application/stm32wl/src/bin/b.rs
+++ b/examples/boot/application/stm32wl/src/bin/b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5#[cfg(feature = "defmt-rtt")] 4#[cfg(feature = "defmt-rtt")]
6use defmt_rtt::*; 5use defmt_rtt::*;
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
index 888375693..41cc06417 100644
--- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
+++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::future::poll_fn; 4use core::future::poll_fn;
6use core::task::Poll; 5use core::task::Poll;
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 1c49c32e1..bc8a7f2d6 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -4,12 +4,6 @@ name = "embassy-nrf52840-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7[features]
8default = ["nightly"]
9nightly = [
10 "static_cell/nightly",
11]
12
13[dependencies] 7[dependencies]
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
15embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
diff --git a/examples/nrf52840/src/bin/blinky.rs b/examples/nrf52840/src/bin/blinky.rs
index d3d1a7122..58a3d2cd9 100644
--- a/examples/nrf52840/src/bin/blinky.rs
+++ b/examples/nrf52840/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive}; 5use embassy_nrf::gpio::{Level, Output, OutputDrive};
diff --git a/examples/nrf52840/src/bin/buffered_uart.rs b/examples/nrf52840/src/bin/buffered_uart.rs
index d9c505786..6ac72bcaf 100644
--- a/examples/nrf52840/src/bin/buffered_uart.rs
+++ b/examples/nrf52840/src/bin/buffered_uart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs
index d3c7b47d2..7fcea9dbd 100644
--- a/examples/nrf52840/src/bin/channel.rs
+++ b/examples/nrf52840/src/bin/channel.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::unwrap; 4use defmt::unwrap;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs
index 79d2c4048..3095a04ec 100644
--- a/examples/nrf52840/src/bin/channel_sender_receiver.rs
+++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::unwrap; 4use defmt::unwrap;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
index d1b796fab..a8e64b38a 100644
--- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs
+++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -14,7 +13,7 @@ use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::Delay; 13use embassy_time::Delay;
15use embedded_hal_bus::spi::ExclusiveDevice; 14use embedded_hal_bus::spi::ExclusiveDevice;
16use embedded_io_async::Write; 15use embedded_io_async::Write;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -70,11 +69,20 @@ async fn main(spawner: Spawner) {
70 let seed = u64::from_le_bytes(seed); 69 let seed = u64::from_le_bytes(seed);
71 70
72 // Init network stack 71 // Init network stack
73 let stack = &*make_static!(Stack::new( 72 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
73 static STACK: StaticCell<
74 Stack<
75 Enc28j60<
76 ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_15>, Delay>,
77 Output<'static, peripherals::P0_13>,
78 >,
79 >,
80 > = StaticCell::new();
81 let stack = STACK.init(Stack::new(
74 device, 82 device,
75 config, 83 config,
76 make_static!(StackResources::<2>::new()), 84 RESOURCES.init(StackResources::<2>::new()),
77 seed 85 seed,
78 )); 86 ));
79 87
80 unwrap!(spawner.spawn(net_task(stack))); 88 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/nrf52840/src/bin/executor_fairness_test.rs b/examples/nrf52840/src/bin/executor_fairness_test.rs
index f111b272e..df6e7af3f 100644
--- a/examples/nrf52840/src/bin/executor_fairness_test.rs
+++ b/examples/nrf52840/src/bin/executor_fairness_test.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::future::poll_fn; 4use core::future::poll_fn;
6use core::task::Poll; 5use core::task::Poll;
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs
index 5bfd02465..e254d613d 100644
--- a/examples/nrf52840/src/bin/gpiote_channel.rs
+++ b/examples/nrf52840/src/bin/gpiote_channel.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/gpiote_port.rs b/examples/nrf52840/src/bin/gpiote_port.rs
index 0155d539e..c1afe2f20 100644
--- a/examples/nrf52840/src/bin/gpiote_port.rs
+++ b/examples/nrf52840/src/bin/gpiote_port.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/i2s_effect.rs b/examples/nrf52840/src/bin/i2s_effect.rs
index 391514d93..9eadeb4e4 100644
--- a/examples/nrf52840/src/bin/i2s_effect.rs
+++ b/examples/nrf52840/src/bin/i2s_effect.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::f32::consts::PI; 4use core::f32::consts::PI;
6 5
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs
index 4ed597c0d..799be351f 100644
--- a/examples/nrf52840/src/bin/i2s_monitor.rs
+++ b/examples/nrf52840/src/bin/i2s_monitor.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{debug, error, info}; 4use defmt::{debug, error, info};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/i2s_waveform.rs b/examples/nrf52840/src/bin/i2s_waveform.rs
index f2c1166b1..137d82840 100644
--- a/examples/nrf52840/src/bin/i2s_waveform.rs
+++ b/examples/nrf52840/src/bin/i2s_waveform.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::f32::consts::PI; 4use core::f32::consts::PI;
6 5
diff --git a/examples/nrf52840/src/bin/manually_create_executor.rs b/examples/nrf52840/src/bin/manually_create_executor.rs
index 80364d34a..7ca39348e 100644
--- a/examples/nrf52840/src/bin/manually_create_executor.rs
+++ b/examples/nrf52840/src/bin/manually_create_executor.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use cortex_m_rt::entry; 7use cortex_m_rt::entry;
9use defmt::{info, unwrap}; 8use defmt::{info, unwrap};
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs
index 352f62bf2..b634d8569 100644
--- a/examples/nrf52840/src/bin/multiprio.rs
+++ b/examples/nrf52840/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::{info, unwrap}; 60use defmt::{info, unwrap};
diff --git a/examples/nrf52840/src/bin/mutex.rs b/examples/nrf52840/src/bin/mutex.rs
index 11b47d991..5c22279b5 100644
--- a/examples/nrf52840/src/bin/mutex.rs
+++ b/examples/nrf52840/src/bin/mutex.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/nvmc.rs b/examples/nrf52840/src/bin/nvmc.rs
index 624829863..a79385b98 100644
--- a/examples/nrf52840/src/bin/nvmc.rs
+++ b/examples/nrf52840/src/bin/nvmc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs
index bff323974..52dadc805 100644
--- a/examples/nrf52840/src/bin/pdm.rs
+++ b/examples/nrf52840/src/bin/pdm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pdm_continuous.rs b/examples/nrf52840/src/bin/pdm_continuous.rs
index 7d8531475..e948203a5 100644
--- a/examples/nrf52840/src/bin/pdm_continuous.rs
+++ b/examples/nrf52840/src/bin/pdm_continuous.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::cmp::Ordering; 4use core::cmp::Ordering;
6 5
diff --git a/examples/nrf52840/src/bin/ppi.rs b/examples/nrf52840/src/bin/ppi.rs
index d74ce4064..129ad06e7 100644
--- a/examples/nrf52840/src/bin/ppi.rs
+++ b/examples/nrf52840/src/bin/ppi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::future::pending; 4use core::future::pending;
6 5
diff --git a/examples/nrf52840/src/bin/pubsub.rs b/examples/nrf52840/src/bin/pubsub.rs
index 17d902227..5ebea9220 100644
--- a/examples/nrf52840/src/bin/pubsub.rs
+++ b/examples/nrf52840/src/bin/pubsub.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::unwrap; 4use defmt::unwrap;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs
index 9750935c8..a5bb1347a 100644
--- a/examples/nrf52840/src/bin/pwm.rs
+++ b/examples/nrf52840/src/bin/pwm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pwm_double_sequence.rs b/examples/nrf52840/src/bin/pwm_double_sequence.rs
index 1bfe6e15a..386c483b8 100644
--- a/examples/nrf52840/src/bin/pwm_double_sequence.rs
+++ b/examples/nrf52840/src/bin/pwm_double_sequence.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pwm_sequence.rs b/examples/nrf52840/src/bin/pwm_sequence.rs
index f282cf910..87eda265f 100644
--- a/examples/nrf52840/src/bin/pwm_sequence.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
index 6594fa348..60ea712b5 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::future::pending; 4use core::future::pending;
6 5
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
index 8596e6545..751cf4425 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs
index 92ded1f88..d772d2f5d 100644
--- a/examples/nrf52840/src/bin/pwm_servo.rs
+++ b/examples/nrf52840/src/bin/pwm_servo.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/qdec.rs b/examples/nrf52840/src/bin/qdec.rs
index 59783d312..ea849be63 100644
--- a/examples/nrf52840/src/bin/qdec.rs
+++ b/examples/nrf52840/src/bin/qdec.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/qspi.rs b/examples/nrf52840/src/bin/qspi.rs
index 9e8a01f4e..4539dd0e3 100644
--- a/examples/nrf52840/src/bin/qspi.rs
+++ b/examples/nrf52840/src/bin/qspi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{assert_eq, info, unwrap}; 4use defmt::{assert_eq, info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/qspi_lowpower.rs b/examples/nrf52840/src/bin/qspi_lowpower.rs
index 42b5454e0..516c9b481 100644
--- a/examples/nrf52840/src/bin/qspi_lowpower.rs
+++ b/examples/nrf52840/src/bin/qspi_lowpower.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
diff --git a/examples/nrf52840/src/bin/rng.rs b/examples/nrf52840/src/bin/rng.rs
index 855743f50..326054c9a 100644
--- a/examples/nrf52840/src/bin/rng.rs
+++ b/examples/nrf52840/src/bin/rng.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_nrf::rng::Rng; 5use embassy_nrf::rng::Rng;
diff --git a/examples/nrf52840/src/bin/saadc.rs b/examples/nrf52840/src/bin/saadc.rs
index d651834f5..653b7d606 100644
--- a/examples/nrf52840/src/bin/saadc.rs
+++ b/examples/nrf52840/src/bin/saadc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/saadc_continuous.rs b/examples/nrf52840/src/bin/saadc_continuous.rs
index a5f8a4dd7..f76fa3570 100644
--- a/examples/nrf52840/src/bin/saadc_continuous.rs
+++ b/examples/nrf52840/src/bin/saadc_continuous.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs
index 8a58396a4..5bfefc2af 100644
--- a/examples/nrf52840/src/bin/self_spawn.rs
+++ b/examples/nrf52840/src/bin/self_spawn.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
index 65d50f8c3..ec9569a64 100644
--- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs
+++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/spim.rs b/examples/nrf52840/src/bin/spim.rs
index 9d1843a8f..131187660 100644
--- a/examples/nrf52840/src/bin/spim.rs
+++ b/examples/nrf52840/src/bin/spim.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/spis.rs b/examples/nrf52840/src/bin/spis.rs
index 77b6e8b64..613cd37ab 100644
--- a/examples/nrf52840/src/bin/spis.rs
+++ b/examples/nrf52840/src/bin/spis.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/temp.rs b/examples/nrf52840/src/bin/temp.rs
index d94dea38d..1d28f8ecf 100644
--- a/examples/nrf52840/src/bin/temp.rs
+++ b/examples/nrf52840/src/bin/temp.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/timer.rs b/examples/nrf52840/src/bin/timer.rs
index 9b9bb3eb4..365695a20 100644
--- a/examples/nrf52840/src/bin/timer.rs
+++ b/examples/nrf52840/src/bin/timer.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/twim.rs b/examples/nrf52840/src/bin/twim.rs
index 959e3a4be..a9a0765e8 100644
--- a/examples/nrf52840/src/bin/twim.rs
+++ b/examples/nrf52840/src/bin/twim.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/twim_lowpower.rs b/examples/nrf52840/src/bin/twim_lowpower.rs
index bf9f966ef..c743614b8 100644
--- a/examples/nrf52840/src/bin/twim_lowpower.rs
+++ b/examples/nrf52840/src/bin/twim_lowpower.rs
@@ -6,7 +6,6 @@
6 6
7#![no_std] 7#![no_std]
8#![no_main] 8#![no_main]
9#![feature(type_alias_impl_trait)]
10 9
11use core::mem; 10use core::mem;
12 11
diff --git a/examples/nrf52840/src/bin/twis.rs b/examples/nrf52840/src/bin/twis.rs
index aa42b679e..88bd4cceb 100644
--- a/examples/nrf52840/src/bin/twis.rs
+++ b/examples/nrf52840/src/bin/twis.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/uart.rs b/examples/nrf52840/src/bin/uart.rs
index 50d5cab8c..accaccea1 100644
--- a/examples/nrf52840/src/bin/uart.rs
+++ b/examples/nrf52840/src/bin/uart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/uart_idle.rs b/examples/nrf52840/src/bin/uart_idle.rs
index e1f42fa6c..fa93bcf21 100644
--- a/examples/nrf52840/src/bin/uart_idle.rs
+++ b/examples/nrf52840/src/bin/uart_idle.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs
index b748bfcd8..c7510a9a8 100644
--- a/examples/nrf52840/src/bin/uart_split.rs
+++ b/examples/nrf52840/src/bin/uart_split.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index b7806f418..3469c6e5f 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
@@ -16,7 +15,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState
16use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 15use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
17use embassy_usb::{Builder, Config, UsbDevice}; 16use embassy_usb::{Builder, Config, UsbDevice};
18use embedded_io_async::Write; 17use embedded_io_async::Write;
19use static_cell::make_static; 18use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
21 20
22bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
@@ -71,14 +70,19 @@ async fn main(spawner: Spawner) {
71 config.device_protocol = 0x01; 70 config.device_protocol = 0x01;
72 71
73 // Create embassy-usb DeviceBuilder using the driver and config. 72 // Create embassy-usb DeviceBuilder using the driver and config.
73 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
74 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
75 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
76 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new();
77 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
74 let mut builder = Builder::new( 78 let mut builder = Builder::new(
75 driver, 79 driver,
76 config, 80 config,
77 &mut make_static!([0; 256])[..], 81 &mut DEVICE_DESC.init([0; 256])[..],
78 &mut make_static!([0; 256])[..], 82 &mut CONFIG_DESC.init([0; 256])[..],
79 &mut make_static!([0; 256])[..], 83 &mut BOS_DESC.init([0; 256])[..],
80 &mut make_static!([0; 128])[..], 84 &mut MSOS_DESC.init([0; 128])[..],
81 &mut make_static!([0; 128])[..], 85 &mut CONTROL_BUF.init([0; 128])[..],
82 ); 86 );
83 87
84 // Our MAC addr. 88 // Our MAC addr.
@@ -87,14 +91,16 @@ async fn main(spawner: Spawner) {
87 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; 91 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88];
88 92
89 // Create classes on the builder. 93 // Create classes on the builder.
90 let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); 94 static STATE: StaticCell<State> = StaticCell::new();
95 let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64);
91 96
92 // Build the builder. 97 // Build the builder.
93 let usb = builder.build(); 98 let usb = builder.build();
94 99
95 unwrap!(spawner.spawn(usb_task(usb))); 100 unwrap!(spawner.spawn(usb_task(usb)));
96 101
97 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); 102 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
103 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
98 unwrap!(spawner.spawn(usb_ncm_task(runner))); 104 unwrap!(spawner.spawn(usb_ncm_task(runner)));
99 105
100 let config = embassy_net::Config::dhcpv4(Default::default()); 106 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -111,12 +117,9 @@ async fn main(spawner: Spawner) {
111 let seed = u64::from_le_bytes(seed); 117 let seed = u64::from_le_bytes(seed);
112 118
113 // Init network stack 119 // Init network stack
114 let stack = &*make_static!(Stack::new( 120 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
115 device, 121 static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new();
116 config, 122 let stack = &*STACK.init(Stack::new(device, config, RESOURCES.init(StackResources::new()), seed));
117 make_static!(StackResources::<2>::new()),
118 seed
119 ));
120 123
121 unwrap!(spawner.spawn(net_task(stack))); 124 unwrap!(spawner.spawn(net_task(stack)));
122 125
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
index 7ccd2946a..45850b4a4 100644
--- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6use core::sync::atomic::{AtomicBool, Ordering}; 5use core::sync::atomic::{AtomicBool, Ordering};
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index 96fcf8a66..04ad841b7 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs
index dc95cde84..aff539b1b 100644
--- a/examples/nrf52840/src/bin/usb_serial.rs
+++ b/examples/nrf52840/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index cd4392903..4e8118fb8 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
@@ -12,7 +11,7 @@ use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
14use embassy_usb::{Builder, Config, UsbDevice}; 13use embassy_usb::{Builder, Config, UsbDevice};
15use static_cell::make_static; 14use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
18bind_interrupts!(struct Irqs { 17bind_interrupts!(struct Irqs {
@@ -64,17 +63,23 @@ async fn main(spawner: Spawner) {
64 config.device_protocol = 0x01; 63 config.device_protocol = 0x01;
65 config.composite_with_iads = true; 64 config.composite_with_iads = true;
66 65
67 let state = make_static!(State::new()); 66 static STATE: StaticCell<State> = StaticCell::new();
67 let state = STATE.init(State::new());
68 68
69 // Create embassy-usb DeviceBuilder using the driver and config. 69 // Create embassy-usb DeviceBuilder using the driver and config.
70 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
71 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
72 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
73 static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new();
74 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
70 let mut builder = Builder::new( 75 let mut builder = Builder::new(
71 driver, 76 driver,
72 config, 77 config,
73 &mut make_static!([0; 256])[..], 78 &mut DEVICE_DESC.init([0; 256])[..],
74 &mut make_static!([0; 256])[..], 79 &mut CONFIG_DESC.init([0; 256])[..],
75 &mut make_static!([0; 256])[..], 80 &mut BOS_DESC.init([0; 256])[..],
76 &mut make_static!([0; 128])[..], 81 &mut MSOS_DESC.init([0; 128])[..],
77 &mut make_static!([0; 128])[..], 82 &mut CONTROL_BUF.init([0; 128])[..],
78 ); 83 );
79 84
80 // Create classes on the builder. 85 // Create classes on the builder.
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs
index 1d39d3841..060f9ba94 100644
--- a/examples/nrf52840/src/bin/usb_serial_winusb.rs
+++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::mem; 4use core::mem;
6 5
diff --git a/examples/nrf52840/src/bin/wdt.rs b/examples/nrf52840/src/bin/wdt.rs
index 058746518..ede88cc26 100644
--- a/examples/nrf52840/src/bin/wdt.rs
+++ b/examples/nrf52840/src/bin/wdt.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
index a60822fd9..fc2086f75 100644
--- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs
+++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap, warn}; 4use defmt::{info, unwrap, warn};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -13,7 +12,7 @@ use embassy_nrf::{bind_interrupts, peripherals};
13use embassy_time::Delay; 12use embassy_time::Delay;
14use embedded_hal_bus::spi::ExclusiveDevice; 13use embedded_hal_bus::spi::ExclusiveDevice;
15use embedded_io_async::Write; 14use embedded_io_async::Write;
16use static_cell::make_static; 15use static_cell::StaticCell;
17use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; 16use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _};
18 17
19const WIFI_NETWORK: &str = "EmbassyTest"; 18const WIFI_NETWORK: &str = "EmbassyTest";
@@ -61,8 +60,9 @@ async fn main(spawner: Spawner) {
61 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); 60 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
62 let spi = ExclusiveDevice::new(spi, cs, Delay); 61 let spi = ExclusiveDevice::new(spi, cs, Delay);
63 62
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) = embassy_net_esp_hosted::new(
65 make_static!(embassy_net_esp_hosted::State::new()), 65 ESP_STATE.init(embassy_net_esp_hosted::State::new()),
66 spi, 66 spi,
67 handshake, 67 handshake,
68 ready, 68 ready,
@@ -89,11 +89,13 @@ async fn main(spawner: Spawner) {
89 let seed = u64::from_le_bytes(seed); 89 let seed = u64::from_le_bytes(seed);
90 90
91 // Init network stack 91 // Init network stack
92 let stack = &*make_static!(Stack::new( 92 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
93 static STACK: StaticCell<Stack<hosted::NetDriver<'static>>> = StaticCell::new();
94 let stack = &*STACK.init(Stack::new(
93 device, 95 device,
94 config, 96 config,
95 make_static!(StackResources::<2>::new()), 97 RESOURCES.init(StackResources::<2>::new()),
96 seed 98 seed,
97 )); 99 ));
98 100
99 unwrap!(spawner.spawn(net_task(stack))); 101 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index 17d3e30e4..fc0346f90 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
9embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "defmt", "integrated-timers"] } 10embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
11embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } 12embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] }
13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
@@ -17,7 +17,7 @@ embedded-io-async = { version = "0.6.1" }
17defmt = "0.3" 17defmt = "0.3"
18defmt-rtt = "0.4" 18defmt-rtt = "0.4"
19 19
20static_cell = { version = "2", features = ["nightly"]} 20static_cell = "2"
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
23panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "0.3", features = ["print-defmt"] }
diff --git a/examples/nrf5340/src/bin/blinky.rs b/examples/nrf5340/src/bin/blinky.rs
index b784564a5..5c533c9b1 100644
--- a/examples/nrf5340/src/bin/blinky.rs
+++ b/examples/nrf5340/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive}; 5use embassy_nrf::gpio::{Level, Output, OutputDrive};
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs
index ceab1194a..c0a55142f 100644
--- a/examples/nrf5340/src/bin/gpiote_channel.rs
+++ b/examples/nrf5340/src/bin/gpiote_channel.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/nrf5340/src/bin/uart.rs b/examples/nrf5340/src/bin/uart.rs
index d68539702..7b41d7463 100644
--- a/examples/nrf5340/src/bin/uart.rs
+++ b/examples/nrf5340/src/bin/uart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 521f17b82..07de83203 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8[dependencies] 8[dependencies]
9embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } 9embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -43,7 +43,7 @@ embedded-hal-async = "1.0.0-rc.3"
43embedded-hal-bus = { version = "0.1.0-rc.3", features = ["async"] } 43embedded-hal-bus = { version = "0.1.0-rc.3", features = ["async"] }
44embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 44embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
45embedded-storage = { version = "0.3" } 45embedded-storage = { version = "0.3" }
46static_cell = { version = "2", features = ["nightly"]} 46static_cell = "2"
47portable-atomic = { version = "1.5", features = ["critical-section"] } 47portable-atomic = { version = "1.5", features = ["critical-section"] }
48log = "0.4" 48log = "0.4"
49pio-proc = "0.2" 49pio-proc = "0.2"
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs
index a579be139..1bb7c2249 100644
--- a/examples/rp/src/bin/adc.rs
+++ b/examples/rp/src/bin/adc.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs
index 66c8773fa..60fc45a70 100644
--- a/examples/rp/src/bin/blinky.rs
+++ b/examples/rp/src/bin/blinky.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs
index a9f34ab5d..e9054fd48 100644
--- a/examples/rp/src/bin/button.rs
+++ b/examples/rp/src/bin/button.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
10use embassy_rp::gpio::{Input, Level, Output, Pull}; 9use embassy_rp::gpio::{Input, Level, Output, Pull};
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
index c0fde62ab..a16ea0007 100644
--- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs
+++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -20,7 +19,7 @@ use embassy_time::{Delay, Duration};
20use embedded_hal_bus::spi::ExclusiveDevice; 19use embedded_hal_bus::spi::ExclusiveDevice;
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use rand::RngCore; 21use rand::RngCore;
23use static_cell::make_static; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
26#[embassy_executor::task] 25#[embassy_executor::task]
@@ -55,7 +54,8 @@ async fn main(spawner: Spawner) {
55 let w5500_reset = Output::new(p.PIN_20, Level::High); 54 let w5500_reset = Output::new(p.PIN_20, Level::High);
56 55
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 56 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 let state = make_static!(State::<8, 8>::new()); 57 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
58 let state = STATE.init(State::<8, 8>::new());
59 let (device, runner) = embassy_net_wiznet::new( 59 let (device, runner) = embassy_net_wiznet::new(
60 mac_addr, 60 mac_addr,
61 state, 61 state,
@@ -70,11 +70,13 @@ async fn main(spawner: Spawner) {
70 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
71 71
72 // Init network stack 72 // Init network stack
73 let stack = &*make_static!(Stack::new( 73 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
74 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
75 let stack = &*STACK.init(Stack::new(
74 device, 76 device,
75 embassy_net::Config::dhcpv4(Default::default()), 77 embassy_net::Config::dhcpv4(Default::default()),
76 make_static!(StackResources::<3>::new()), 78 RESOURCES.init(StackResources::<3>::new()),
77 seed 79 seed,
78 )); 80 ));
79 81
80 // Launch network task 82 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
index b19362fc1..975b3d385 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use core::str::FromStr; 8use core::str::FromStr;
10 9
@@ -22,7 +21,7 @@ use embassy_time::{Delay, Duration, Timer};
22use embedded_hal_bus::spi::ExclusiveDevice; 21use embedded_hal_bus::spi::ExclusiveDevice;
23use embedded_io_async::Write; 22use embedded_io_async::Write;
24use rand::RngCore; 23use rand::RngCore;
25use static_cell::make_static; 24use static_cell::StaticCell;
26use {defmt_rtt as _, panic_probe as _}; 25use {defmt_rtt as _, panic_probe as _};
27 26
28#[embassy_executor::task] 27#[embassy_executor::task]
@@ -58,7 +57,8 @@ async fn main(spawner: Spawner) {
58 let w5500_reset = Output::new(p.PIN_20, Level::High); 57 let w5500_reset = Output::new(p.PIN_20, Level::High);
59 58
60 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 59 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
61 let state = make_static!(State::<8, 8>::new()); 60 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
61 let state = STATE.init(State::<8, 8>::new());
62 let (device, runner) = embassy_net_wiznet::new( 62 let (device, runner) = embassy_net_wiznet::new(
63 mac_addr, 63 mac_addr,
64 state, 64 state,
@@ -73,11 +73,13 @@ async fn main(spawner: Spawner) {
73 let seed = rng.next_u64(); 73 let seed = rng.next_u64();
74 74
75 // Init network stack 75 // Init network stack
76 let stack = &*make_static!(Stack::new( 76 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
77 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
78 let stack = &*STACK.init(Stack::new(
77 device, 79 device,
78 embassy_net::Config::dhcpv4(Default::default()), 80 embassy_net::Config::dhcpv4(Default::default()),
79 make_static!(StackResources::<2>::new()), 81 RESOURCES.init(StackResources::<2>::new()),
80 seed 82 seed,
81 )); 83 ));
82 84
83 // Launch network task 85 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
index c62caed7a..489af2c76 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
@@ -21,7 +20,7 @@ use embassy_time::{Delay, Duration};
21use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
22use embedded_io_async::Write; 21use embedded_io_async::Write;
23use rand::RngCore; 22use rand::RngCore;
24use static_cell::make_static; 23use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
26 25
27#[embassy_executor::task] 26#[embassy_executor::task]
@@ -57,7 +56,8 @@ async fn main(spawner: Spawner) {
57 let w5500_reset = Output::new(p.PIN_20, Level::High); 56 let w5500_reset = Output::new(p.PIN_20, Level::High);
58 57
59 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 58 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
60 let state = make_static!(State::<8, 8>::new()); 59 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
60 let state = STATE.init(State::<8, 8>::new());
61 let (device, runner) = embassy_net_wiznet::new( 61 let (device, runner) = embassy_net_wiznet::new(
62 mac_addr, 62 mac_addr,
63 state, 63 state,
@@ -72,11 +72,13 @@ async fn main(spawner: Spawner) {
72 let seed = rng.next_u64(); 72 let seed = rng.next_u64();
73 73
74 // Init network stack 74 // Init network stack
75 let stack = &*make_static!(Stack::new( 75 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
76 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
77 let stack = &*STACK.init(Stack::new(
76 device, 78 device,
77 embassy_net::Config::dhcpv4(Default::default()), 79 embassy_net::Config::dhcpv4(Default::default()),
78 make_static!(StackResources::<2>::new()), 80 RESOURCES.init(StackResources::<2>::new()),
79 seed 81 seed,
80 )); 82 ));
81 83
82 // Launch network task 84 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs
index 76dabce1c..41bd7d077 100644
--- a/examples/rp/src/bin/ethernet_w5500_udp.rs
+++ b/examples/rp/src/bin/ethernet_w5500_udp.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -20,7 +19,7 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::Delay; 19use embassy_time::Delay;
21use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
22use rand::RngCore; 21use rand::RngCore;
23use static_cell::make_static; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
26#[embassy_executor::task] 25#[embassy_executor::task]
@@ -55,7 +54,8 @@ async fn main(spawner: Spawner) {
55 let w5500_reset = Output::new(p.PIN_20, Level::High); 54 let w5500_reset = Output::new(p.PIN_20, Level::High);
56 55
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 56 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 let state = make_static!(State::<8, 8>::new()); 57 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
58 let state = STATE.init(State::<8, 8>::new());
59 let (device, runner) = embassy_net_wiznet::new( 59 let (device, runner) = embassy_net_wiznet::new(
60 mac_addr, 60 mac_addr,
61 state, 61 state,
@@ -70,11 +70,13 @@ async fn main(spawner: Spawner) {
70 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
71 71
72 // Init network stack 72 // Init network stack
73 let stack = &*make_static!(Stack::new( 73 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
74 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
75 let stack = &*STACK.init(Stack::new(
74 device, 76 device,
75 embassy_net::Config::dhcpv4(Default::default()), 77 embassy_net::Config::dhcpv4(Default::default()),
76 make_static!(StackResources::<2>::new()), 78 RESOURCES.init(StackResources::<2>::new()),
77 seed 79 seed,
78 )); 80 ));
79 81
80 // Launch network task 82 // Launch network task
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs
index 129a8497f..eb3e6a2b9 100644
--- a/examples/rp/src/bin/flash.rs
+++ b/examples/rp/src/bin/flash.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs
index 98209fe41..b79fb2a15 100644
--- a/examples/rp/src/bin/gpio_async.rs
+++ b/examples/rp/src/bin/gpio_async.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs
index 896cc15ee..011359253 100644
--- a/examples/rp/src/bin/gpout.rs
+++ b/examples/rp/src/bin/gpout.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs
index 7b53aae72..e31cc894c 100644
--- a/examples/rp/src/bin/i2c_async.rs
+++ b/examples/rp/src/bin/i2c_async.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs
index 9ddb48d69..c9c8a2760 100644
--- a/examples/rp/src/bin/i2c_blocking.rs
+++ b/examples/rp/src/bin/i2c_blocking.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs
index 151b083a4..479f9a16a 100644
--- a/examples/rp/src/bin/i2c_slave.rs
+++ b/examples/rp/src/bin/i2c_slave.rs
@@ -1,7 +1,6 @@
1//! This example shows how to use the 2040 as an i2c slave. 1//! This example shows how to use the 2040 as an i2c slave.
2#![no_std] 2#![no_std]
3#![no_main] 3#![no_main]
4#![feature(type_alias_impl_trait)]
5 4
6use defmt::*; 5use defmt::*;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index 43eaf8b0a..a1678d99a 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Executor; 9use embassy_executor::Executor;
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs
index 28f621437..26b80c11d 100644
--- a/examples/rp/src/bin/multiprio.rs
+++ b/examples/rp/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::{info, unwrap}; 60use defmt::{info, unwrap};
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index a6d6144be..ee248591b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6use defmt::info; 5use defmt::info;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
8use embassy_rp::bind_interrupts; 7use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 86e5017ac..02700269c 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6use defmt::info; 5use defmt::info;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
8use embassy_futures::join::join; 7use embassy_futures::join::join;
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 5e5a6f9a3..3fab7b5f2 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use core::fmt::Write; 7use core::fmt::Write;
9 8
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs
index 6d9d59df6..58bdadbc0 100644
--- a/examples/rp/src/bin/pio_rotary_encoder.rs
+++ b/examples/rp/src/bin/pio_rotary_encoder.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::info; 6use defmt::info;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/pio_stepper.rs b/examples/rp/src/bin/pio_stepper.rs
index 02fb20699..ab9ecf623 100644
--- a/examples/rp/src/bin/pio_stepper.rs
+++ b/examples/rp/src/bin/pio_stepper.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7use core::mem::{self, MaybeUninit}; 6use core::mem::{self, MaybeUninit};
8 7
9use defmt::info; 8use defmt::info;
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs
index c0ea23607..a07f1c180 100644
--- a/examples/rp/src/bin/pio_uart.rs
+++ b/examples/rp/src/bin/pio_uart.rs
@@ -8,7 +8,6 @@
8 8
9#![no_std] 9#![no_std]
10#![no_main] 10#![no_main]
11#![feature(type_alias_impl_trait)]
12#![allow(async_fn_in_trait)] 11#![allow(async_fn_in_trait)]
13 12
14use defmt::{info, panic, trace}; 13use defmt::{info, panic, trace};
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs
index 7b3259538..9a97cb8a7 100644
--- a/examples/rp/src/bin/pio_ws2812.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs
index a99e88003..4fb62546d 100644
--- a/examples/rp/src/bin/pwm.rs
+++ b/examples/rp/src/bin/pwm.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/pwm_input.rs b/examples/rp/src/bin/pwm_input.rs
index 0fc2e40c3..e7bcbfbd4 100644
--- a/examples/rp/src/bin/pwm_input.rs
+++ b/examples/rp/src/bin/pwm_input.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/rosc.rs b/examples/rp/src/bin/rosc.rs
index f841043b6..942b72319 100644
--- a/examples/rp/src/bin/rosc.rs
+++ b/examples/rp/src/bin/rosc.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs
index 667876db5..e9a5e43a8 100644
--- a/examples/rp/src/bin/rtc.rs
+++ b/examples/rp/src/bin/rtc.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs
index 602348f7a..4cc4f5210 100644
--- a/examples/rp/src/bin/spi.rs
+++ b/examples/rp/src/bin/spi.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs
index f5a2d334e..266584efc 100644
--- a/examples/rp/src/bin/spi_async.rs
+++ b/examples/rp/src/bin/spi_async.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs
index 26c258e1c..e937b9d0a 100644
--- a/examples/rp/src/bin/spi_display.rs
+++ b/examples/rp/src/bin/spi_display.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use core::cell::RefCell; 9use core::cell::RefCell;
11 10
diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs
index 451c3c396..6a2816cd0 100644
--- a/examples/rp/src/bin/uart.rs
+++ b/examples/rp/src/bin/uart.rs
@@ -6,7 +6,6 @@
6 6
7#![no_std] 7#![no_std]
8#![no_main] 8#![no_main]
9#![feature(type_alias_impl_trait)]
10 9
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
12use embassy_rp::uart; 11use embassy_rp::uart;
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs
index 14e8810a4..fac61aa04 100644
--- a/examples/rp/src/bin/uart_buffered_split.rs
+++ b/examples/rp/src/bin/uart_buffered_split.rs
@@ -6,7 +6,6 @@
6 6
7#![no_std] 7#![no_std]
8#![no_main] 8#![no_main]
9#![feature(type_alias_impl_trait)]
10 9
11use defmt::*; 10use defmt::*;
12use embassy_executor::Spawner; 11use embassy_executor::Spawner;
@@ -15,7 +14,7 @@ use embassy_rp::peripherals::UART0;
15use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; 14use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config};
16use embassy_time::Timer; 15use embassy_time::Timer;
17use embedded_io_async::{Read, Write}; 16use embedded_io_async::{Read, Write};
18use static_cell::make_static; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
21bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
@@ -27,8 +26,10 @@ async fn main(spawner: Spawner) {
27 let p = embassy_rp::init(Default::default()); 26 let p = embassy_rp::init(Default::default());
28 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); 27 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0);
29 28
30 let tx_buf = &mut make_static!([0u8; 16])[..]; 29 static TX_BUF: StaticCell<[u8; 16]> = StaticCell::new();
31 let rx_buf = &mut make_static!([0u8; 16])[..]; 30 let tx_buf = &mut TX_BUF.init([0; 16])[..];
31 static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new();
32 let rx_buf = &mut RX_BUF.init([0; 16])[..];
32 let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); 33 let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
33 let (rx, mut tx) = uart.split(); 34 let (rx, mut tx) = uart.split();
34 35
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index 42c8b432e..a45f40756 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -7,7 +7,6 @@
7 7
8#![no_std] 8#![no_std]
9#![no_main] 9#![no_main]
10#![feature(type_alias_impl_trait)]
11 10
12use defmt::*; 11use defmt::*;
13use embassy_executor::Spawner; 12use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index cc63029fb..01f0d5967 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -17,7 +16,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState
17use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 16use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
18use embassy_usb::{Builder, Config, UsbDevice}; 17use embassy_usb::{Builder, Config, UsbDevice};
19use embedded_io_async::Write; 18use embedded_io_async::Write;
20use static_cell::make_static; 19use static_cell::StaticCell;
21use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
22 21
23bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
@@ -65,14 +64,18 @@ async fn main(spawner: Spawner) {
65 config.device_protocol = 0x01; 64 config.device_protocol = 0x01;
66 65
67 // Create embassy-usb DeviceBuilder using the driver and config. 66 // Create embassy-usb DeviceBuilder using the driver and config.
67 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
68 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
69 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
70 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
68 let mut builder = Builder::new( 71 let mut builder = Builder::new(
69 driver, 72 driver,
70 config, 73 config,
71 &mut make_static!([0; 256])[..], 74 &mut DEVICE_DESC.init([0; 256])[..],
72 &mut make_static!([0; 256])[..], 75 &mut CONFIG_DESC.init([0; 256])[..],
73 &mut make_static!([0; 256])[..], 76 &mut BOS_DESC.init([0; 256])[..],
74 &mut [], // no msos descriptors 77 &mut [], // no msos descriptors
75 &mut make_static!([0; 128])[..], 78 &mut CONTROL_BUF.init([0; 128])[..],
76 ); 79 );
77 80
78 // Our MAC addr. 81 // Our MAC addr.
@@ -81,14 +84,16 @@ async fn main(spawner: Spawner) {
81 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; 84 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88];
82 85
83 // Create classes on the builder. 86 // Create classes on the builder.
84 let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); 87 static STATE: StaticCell<State> = StaticCell::new();
88 let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64);
85 89
86 // Build the builder. 90 // Build the builder.
87 let usb = builder.build(); 91 let usb = builder.build();
88 92
89 unwrap!(spawner.spawn(usb_task(usb))); 93 unwrap!(spawner.spawn(usb_task(usb)));
90 94
91 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); 95 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
96 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
92 unwrap!(spawner.spawn(usb_ncm_task(runner))); 97 unwrap!(spawner.spawn(usb_ncm_task(runner)));
93 98
94 let config = embassy_net::Config::dhcpv4(Default::default()); 99 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -102,11 +107,13 @@ async fn main(spawner: Spawner) {
102 let seed = 1234; // guaranteed random, chosen by a fair dice roll 107 let seed = 1234; // guaranteed random, chosen by a fair dice roll
103 108
104 // Init network stack 109 // Init network stack
105 let stack = &*make_static!(Stack::new( 110 static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new();
111 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
112 let stack = &*STACK.init(Stack::new(
106 device, 113 device,
107 config, 114 config,
108 make_static!(StackResources::<2>::new()), 115 RESOURCES.init(StackResources::<2>::new()),
109 seed 116 seed,
110 )); 117 ));
111 118
112 unwrap!(spawner.spawn(net_task(stack))); 119 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index 569c9b12b..b5ac16245 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, Ordering};
6 5
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs
index 791f15e56..af401ed63 100644
--- a/examples/rp/src/bin/usb_logger.rs
+++ b/examples/rp/src/bin/usb_logger.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts; 9use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs
index d5cdae319..95306a35c 100644
--- a/examples/rp/src/bin/usb_midi.rs
+++ b/examples/rp/src/bin/usb_midi.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::{info, panic}; 8use defmt::{info, panic};
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/usb_raw.rs b/examples/rp/src/bin/usb_raw.rs
index f59262e5c..a6c8a5b2e 100644
--- a/examples/rp/src/bin/usb_raw.rs
+++ b/examples/rp/src/bin/usb_raw.rs
@@ -48,7 +48,6 @@
48 48
49#![no_std] 49#![no_std]
50#![no_main] 50#![no_main]
51#![feature(type_alias_impl_trait)]
52 51
53use defmt::info; 52use defmt::info;
54use embassy_executor::Spawner; 53use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs
index 288be5a4e..0dc8e9f72 100644
--- a/examples/rp/src/bin/usb_raw_bulk.rs
+++ b/examples/rp/src/bin/usb_raw_bulk.rs
@@ -26,7 +26,6 @@
26 26
27#![no_std] 27#![no_std]
28#![no_main] 28#![no_main]
29#![feature(type_alias_impl_trait)]
30 29
31use defmt::info; 30use defmt::info;
32use embassy_executor::Spawner; 31use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 30347d920..ab24a994c 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::{info, panic}; 8use defmt::{info, panic};
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs
index b6af518af..b9d4ef22f 100644
--- a/examples/rp/src/bin/watchdog.rs
+++ b/examples/rp/src/bin/watchdog.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::info; 8use defmt::info;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs
index ad1fa6462..1bd75607e 100644
--- a/examples/rp/src/bin/wifi_ap_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str::from_utf8; 8use core::str::from_utf8;
@@ -19,7 +18,7 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
19use embassy_rp::pio::{InterruptHandler, Pio}; 18use embassy_rp::pio::{InterruptHandler, Pio};
20use embassy_time::Duration; 19use embassy_time::Duration;
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use static_cell::make_static; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
25bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
@@ -59,7 +58,8 @@ async fn main(spawner: Spawner) {
59 let mut pio = Pio::new(p.PIO0, Irqs); 58 let mut pio = Pio::new(p.PIO0, Irqs);
60 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 59 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
61 60
62 let state = make_static!(cyw43::State::new()); 61 static STATE: StaticCell<cyw43::State> = StaticCell::new();
62 let state = STATE.init(cyw43::State::new());
63 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 63 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
64 unwrap!(spawner.spawn(wifi_task(runner))); 64 unwrap!(spawner.spawn(wifi_task(runner)));
65 65
@@ -79,11 +79,13 @@ async fn main(spawner: Spawner) {
79 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. 79 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
80 80
81 // Init network stack 81 // Init network stack
82 let stack = &*make_static!(Stack::new( 82 static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new();
83 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
84 let stack = &*STACK.init(Stack::new(
83 net_device, 85 net_device,
84 config, 86 config,
85 make_static!(StackResources::<2>::new()), 87 RESOURCES.init(StackResources::<2>::new()),
86 seed 88 seed,
87 )); 89 ));
88 90
89 unwrap!(spawner.spawn(net_task(stack))); 91 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs
index 14ace74e9..1ed74993c 100644
--- a/examples/rp/src/bin/wifi_blinky.rs
+++ b/examples/rp/src/bin/wifi_blinky.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use cyw43_pio::PioSpi; 8use cyw43_pio::PioSpi;
10use defmt::*; 9use defmt::*;
@@ -14,7 +13,7 @@ use embassy_rp::gpio::{Level, Output};
14use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 13use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
15use embassy_rp::pio::{InterruptHandler, Pio}; 14use embassy_rp::pio::{InterruptHandler, Pio};
16use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -46,7 +45,8 @@ async fn main(spawner: Spawner) {
46 let mut pio = Pio::new(p.PIO0, Irqs); 45 let mut pio = Pio::new(p.PIO0, Irqs);
47 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 46 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
48 47
49 let state = make_static!(cyw43::State::new()); 48 static STATE: StaticCell<cyw43::State> = StaticCell::new();
49 let state = STATE.init(cyw43::State::new());
50 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 50 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
51 unwrap!(spawner.spawn(wifi_task(runner))); 51 unwrap!(spawner.spawn(wifi_task(runner)));
52 52
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs
index 7adf52b88..45bb5b76c 100644
--- a/examples/rp/src/bin/wifi_scan.rs
+++ b/examples/rp/src/bin/wifi_scan.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str; 8use core::str;
@@ -16,7 +15,7 @@ use embassy_rp::bind_interrupts;
16use embassy_rp::gpio::{Level, Output}; 15use embassy_rp::gpio::{Level, Output};
17use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 16use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
18use embassy_rp::pio::{InterruptHandler, Pio}; 17use embassy_rp::pio::{InterruptHandler, Pio};
19use static_cell::make_static; 18use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
21 20
22bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
@@ -56,7 +55,8 @@ async fn main(spawner: Spawner) {
56 let mut pio = Pio::new(p.PIO0, Irqs); 55 let mut pio = Pio::new(p.PIO0, Irqs);
57 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 56 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
58 57
59 let state = make_static!(cyw43::State::new()); 58 static STATE: StaticCell<cyw43::State> = StaticCell::new();
59 let state = STATE.init(cyw43::State::new());
60 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 60 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
61 unwrap!(spawner.spawn(wifi_task(runner))); 61 unwrap!(spawner.spawn(wifi_task(runner)));
62 62
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs
index ec6b4ee74..c346f1ded 100644
--- a/examples/rp/src/bin/wifi_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_tcp_server.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str::from_utf8; 8use core::str::from_utf8;
@@ -19,7 +18,7 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
19use embassy_rp::pio::{InterruptHandler, Pio}; 18use embassy_rp::pio::{InterruptHandler, Pio};
20use embassy_time::{Duration, Timer}; 19use embassy_time::{Duration, Timer};
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use static_cell::make_static; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
25bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
@@ -62,7 +61,8 @@ async fn main(spawner: Spawner) {
62 let mut pio = Pio::new(p.PIO0, Irqs); 61 let mut pio = Pio::new(p.PIO0, Irqs);
63 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 62 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
64 63
65 let state = make_static!(cyw43::State::new()); 64 static STATE: StaticCell<cyw43::State> = StaticCell::new();
65 let state = STATE.init(cyw43::State::new());
66 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 66 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
67 unwrap!(spawner.spawn(wifi_task(runner))); 67 unwrap!(spawner.spawn(wifi_task(runner)));
68 68
@@ -82,11 +82,13 @@ async fn main(spawner: Spawner) {
82 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. 82 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
83 83
84 // Init network stack 84 // Init network stack
85 let stack = &*make_static!(Stack::new( 85 static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new();
86 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
87 let stack = &*STACK.init(Stack::new(
86 net_device, 88 net_device,
87 config, 89 config,
88 make_static!(StackResources::<2>::new()), 90 RESOURCES.init(StackResources::<2>::new()),
89 seed 91 seed,
90 )); 92 ));
91 93
92 unwrap!(spawner.spawn(net_task(stack))); 94 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index ccc0a4afc..a4f306865 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["log"] } 8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["log"] }
9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../embassy-time", features = ["log", "std", ] } 10embassy-time = { version = "0.2", path = "../../embassy-time", features = ["log", "std", ] }
11embassy-net = { version = "0.2.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } 11embassy-net = { version = "0.2.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] }
12embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } 12embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" }
@@ -23,7 +23,7 @@ nix = "0.26.2"
23clap = { version = "3.0.0-beta.5", features = ["derive"] } 23clap = { version = "3.0.0-beta.5", features = ["derive"] }
24rand_core = { version = "0.6.3", features = ["std"] } 24rand_core = { version = "0.6.3", features = ["std"] }
25heapless = { version = "0.8", default-features = false } 25heapless = { version = "0.8", default-features = false }
26static_cell = { version = "2", features = ["nightly"]} 26static_cell = "2"
27 27
28[profile.release] 28[profile.release]
29debug = 2 29debug = 2
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs
index 8d8345057..dad93d0a1 100644
--- a/examples/std/src/bin/net.rs
+++ b/examples/std/src/bin/net.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use std::default::Default; 1use std::default::Default;
4 2
5use clap::Parser; 3use clap::Parser;
@@ -12,7 +10,7 @@ use embedded_io_async::Write;
12use heapless::Vec; 10use heapless::Vec;
13use log::*; 11use log::*;
14use rand_core::{OsRng, RngCore}; 12use rand_core::{OsRng, RngCore};
15use static_cell::{make_static, StaticCell}; 13use static_cell::StaticCell;
16 14
17#[derive(Parser)] 15#[derive(Parser)]
18#[clap(version = "1.0")] 16#[clap(version = "1.0")]
@@ -54,11 +52,13 @@ async fn main_task(spawner: Spawner) {
54 let seed = u64::from_le_bytes(seed); 52 let seed = u64::from_le_bytes(seed);
55 53
56 // Init network stack 54 // Init network stack
57 let stack = &*make_static!(Stack::new( 55 static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new();
56 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
57 let stack = &*STACK.init(Stack::new(
58 device, 58 device,
59 config, 59 config,
60 make_static!(StackResources::<3>::new()), 60 RESOURCES.init(StackResources::<3>::new()),
61 seed 61 seed,
62 )); 62 ));
63 63
64 // Launch network task 64 // Launch network task
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs
index 6c19874d5..fca1e076e 100644
--- a/examples/std/src/bin/net_dns.rs
+++ b/examples/std/src/bin/net_dns.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use std::default::Default; 1use std::default::Default;
4 2
5use clap::Parser; 3use clap::Parser;
@@ -10,7 +8,7 @@ use embassy_net_tuntap::TunTapDevice;
10use heapless::Vec; 8use heapless::Vec;
11use log::*; 9use log::*;
12use rand_core::{OsRng, RngCore}; 10use rand_core::{OsRng, RngCore};
13use static_cell::{make_static, StaticCell}; 11use static_cell::StaticCell;
14 12
15#[derive(Parser)] 13#[derive(Parser)]
16#[clap(version = "1.0")] 14#[clap(version = "1.0")]
@@ -53,11 +51,13 @@ async fn main_task(spawner: Spawner) {
53 let seed = u64::from_le_bytes(seed); 51 let seed = u64::from_le_bytes(seed);
54 52
55 // Init network stack 53 // Init network stack
56 let stack: &Stack<_> = &*make_static!(Stack::new( 54 static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new();
55 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
56 let stack: &Stack<_> = &*STACK.init(Stack::new(
57 device, 57 device,
58 config, 58 config,
59 make_static!(StackResources::<3>::new()), 59 RESOURCES.init(StackResources::<3>::new()),
60 seed 60 seed,
61 )); 61 ));
62 62
63 // Launch network task 63 // Launch network task
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs
index cee04e558..9ec0ea91f 100644
--- a/examples/std/src/bin/net_ppp.rs
+++ b/examples/std/src/bin/net_ppp.rs
@@ -7,7 +7,6 @@
7//! ping 192.168.7.10 7//! ping 192.168.7.10
8//! nc 192.168.7.10 1234 8//! nc 192.168.7.10 1234
9 9
10#![feature(type_alias_impl_trait)]
11#![allow(async_fn_in_trait)] 10#![allow(async_fn_in_trait)]
12 11
13#[path = "../serial_port.rs"] 12#[path = "../serial_port.rs"]
@@ -25,7 +24,7 @@ use heapless::Vec;
25use log::*; 24use log::*;
26use nix::sys::termios; 25use nix::sys::termios;
27use rand_core::{OsRng, RngCore}; 26use rand_core::{OsRng, RngCore};
28use static_cell::{make_static, StaticCell}; 27use static_cell::StaticCell;
29 28
30use crate::serial_port::SerialPort; 29use crate::serial_port::SerialPort;
31 30
@@ -88,7 +87,8 @@ async fn main_task(spawner: Spawner) {
88 let port = SerialPort::new(opts.device.as_str(), baudrate).unwrap(); 87 let port = SerialPort::new(opts.device.as_str(), baudrate).unwrap();
89 88
90 // Init network device 89 // Init network device
91 let state = make_static!(embassy_net_ppp::State::<4, 4>::new()); 90 static STATE: StaticCell<embassy_net_ppp::State<4, 4>> = StaticCell::new();
91 let state = STATE.init(embassy_net_ppp::State::<4, 4>::new());
92 let (device, runner) = embassy_net_ppp::new(state); 92 let (device, runner) = embassy_net_ppp::new(state);
93 93
94 // Generate random seed 94 // Generate random seed
@@ -97,11 +97,13 @@ async fn main_task(spawner: Spawner) {
97 let seed = u64::from_le_bytes(seed); 97 let seed = u64::from_le_bytes(seed);
98 98
99 // Init network stack 99 // Init network stack
100 let stack = &*make_static!(Stack::new( 100 static STACK: StaticCell<Stack<embassy_net_ppp::Device<'static>>> = StaticCell::new();
101 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
102 let stack = &*STACK.init(Stack::new(
101 device, 103 device,
102 Config::default(), // don't configure IP yet 104 Config::default(), // don't configure IP yet
103 make_static!(StackResources::<3>::new()), 105 RESOURCES.init(StackResources::<3>::new()),
104 seed 106 seed,
105 )); 107 ));
106 108
107 // Launch network task 109 // Launch network task
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs
index 98dcc9925..bee91990d 100644
--- a/examples/std/src/bin/net_udp.rs
+++ b/examples/std/src/bin/net_udp.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use clap::Parser; 1use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 2use embassy_executor::{Executor, Spawner};
5use embassy_net::udp::{PacketMetadata, UdpSocket}; 3use embassy_net::udp::{PacketMetadata, UdpSocket};
@@ -8,7 +6,7 @@ use embassy_net_tuntap::TunTapDevice;
8use heapless::Vec; 6use heapless::Vec;
9use log::*; 7use log::*;
10use rand_core::{OsRng, RngCore}; 8use rand_core::{OsRng, RngCore};
11use static_cell::{make_static, StaticCell}; 9use static_cell::StaticCell;
12 10
13#[derive(Parser)] 11#[derive(Parser)]
14#[clap(version = "1.0")] 12#[clap(version = "1.0")]
@@ -50,11 +48,13 @@ async fn main_task(spawner: Spawner) {
50 let seed = u64::from_le_bytes(seed); 48 let seed = u64::from_le_bytes(seed);
51 49
52 // Init network stack 50 // Init network stack
53 let stack = &*make_static!(Stack::new( 51 static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new();
52 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
53 let stack = &*STACK.init(Stack::new(
54 device, 54 device,
55 config, 55 config,
56 make_static!(StackResources::<3>::new()), 56 RESOURCES.init(StackResources::<3>::new()),
57 seed 57 seed,
58 )); 58 ));
59 59
60 // Launch network task 60 // Launch network task
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs
index 0b289c74d..435089aad 100644
--- a/examples/std/src/bin/serial.rs
+++ b/examples/std/src/bin/serial.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3#[path = "../serial_port.rs"] 1#[path = "../serial_port.rs"]
4mod serial_port; 2mod serial_port;
5 3
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
index 79fa375cd..00ccd83a7 100644
--- a/examples/std/src/bin/tcp_accept.rs
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use core::fmt::Write as _; 1use core::fmt::Write as _;
4use std::default::Default; 2use std::default::Default;
5 3
@@ -13,7 +11,7 @@ use embedded_io_async::Write as _;
13use heapless::Vec; 11use heapless::Vec;
14use log::*; 12use log::*;
15use rand_core::{OsRng, RngCore}; 13use rand_core::{OsRng, RngCore};
16use static_cell::{make_static, StaticCell}; 14use static_cell::StaticCell;
17 15
18#[derive(Parser)] 16#[derive(Parser)]
19#[clap(version = "1.0")] 17#[clap(version = "1.0")]
@@ -65,11 +63,13 @@ async fn main_task(spawner: Spawner) {
65 let seed = u64::from_le_bytes(seed); 63 let seed = u64::from_le_bytes(seed);
66 64
67 // Init network stack 65 // Init network stack
68 let stack = &*make_static!(Stack::new( 66 static STACK: StaticCell<Stack<TunTapDevice>> = StaticCell::new();
67 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
68 let stack = &*STACK.init(Stack::new(
69 device, 69 device,
70 config, 70 config,
71 make_static!(StackResources::<3>::new()), 71 RESOURCES.init(StackResources::<3>::new()),
72 seed 72 seed,
73 )); 73 ));
74 74
75 // Launch network task 75 // Launch network task
diff --git a/examples/std/src/bin/tick.rs b/examples/std/src/bin/tick.rs
index a3f99067e..f23cf3549 100644
--- a/examples/std/src/bin/tick.rs
+++ b/examples/std/src/bin/tick.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use embassy_executor::Spawner; 1use embassy_executor::Spawner;
4use embassy_time::Timer; 2use embassy_time::Timer;
5use log::*; 3use log::*;
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index 2d831ba5d..0fd3939c6 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32c031c6 to your chip name, if necessary. 8# Change stm32c031c6 to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
diff --git a/examples/stm32c0/src/bin/blinky.rs b/examples/stm32c0/src/bin/blinky.rs
index cbeb0dee1..90e479aae 100644
--- a/examples/stm32c0/src/bin/blinky.rs
+++ b/examples/stm32c0/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32c0/src/bin/button.rs b/examples/stm32c0/src/bin/button.rs
index 40c58013b..265200132 100644
--- a/examples/stm32c0/src/bin/button.rs
+++ b/examples/stm32c0/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32c0/src/bin/button_exti.rs b/examples/stm32c0/src/bin/button_exti.rs
index ef32d4c4a..1e970fdd6 100644
--- a/examples/stm32c0/src/bin/button_exti.rs
+++ b/examples/stm32c0/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 2b066d731..9fdc4798a 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -15,9 +15,9 @@ defmt = "0.3"
15defmt-rtt = "0.4" 15defmt-rtt = "0.4"
16panic-probe = "0.3" 16panic-probe = "0.3"
17embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 17embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
18embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 18embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
19embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 19embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
20static_cell = { version = "2", features = ["nightly"]} 20static_cell = "2"
21portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 21portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
22 22
23[profile.release] 23[profile.release]
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs
index 96f234402..8fef062b3 100644
--- a/examples/stm32f0/src/bin/adc.rs
+++ b/examples/stm32f0/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f0/src/bin/blinky.rs b/examples/stm32f0/src/bin/blinky.rs
index 899394546..2572be1bc 100644
--- a/examples/stm32f0/src/bin/blinky.rs
+++ b/examples/stm32f0/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs
index 306df1752..360d153c3 100644
--- a/examples/stm32f0/src/bin/button_controlled_blink.rs
+++ b/examples/stm32f0/src/bin/button_controlled_blink.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use core::sync::atomic::{AtomicU32, Ordering}; 6use core::sync::atomic::{AtomicU32, Ordering};
8 7
diff --git a/examples/stm32f0/src/bin/button_exti.rs b/examples/stm32f0/src/bin/button_exti.rs
index 40c0d5848..ce17c1a48 100644
--- a/examples/stm32f0/src/bin/button_exti.rs
+++ b/examples/stm32f0/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f0/src/bin/hello.rs b/examples/stm32f0/src/bin/hello.rs
index 0f98d9865..ccd6a0a39 100644
--- a/examples/stm32f0/src/bin/hello.rs
+++ b/examples/stm32f0/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs
index 870c7c45b..e49951726 100644
--- a/examples/stm32f0/src/bin/multiprio.rs
+++ b/examples/stm32f0/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::*; 60use defmt::*;
diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs
index b51dee8ee..b974bff91 100644
--- a/examples/stm32f0/src/bin/wdg.rs
+++ b/examples/stm32f0/src/bin/wdg.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index f04d41317..c933a4368 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32f103c8 to your chip name, if necessary. 8# Change stm32f103c8 to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs
index 1edac3d83..1440460a9 100644
--- a/examples/stm32f1/src/bin/adc.rs
+++ b/examples/stm32f1/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f1/src/bin/blinky.rs b/examples/stm32f1/src/bin/blinky.rs
index 3425b0536..cc43f85f4 100644
--- a/examples/stm32f1/src/bin/blinky.rs
+++ b/examples/stm32f1/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs
index a5ce819d4..c1c4f8359 100644
--- a/examples/stm32f1/src/bin/can.rs
+++ b/examples/stm32f1/src/bin/can.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f1/src/bin/hello.rs b/examples/stm32f1/src/bin/hello.rs
index e63bcaae0..7b761ecc1 100644
--- a/examples/stm32f1/src/bin/hello.rs
+++ b/examples/stm32f1/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index 31519555f..e28381893 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 66cc1e15b..eaaadeec5 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32f207zg to your chip name, if necessary. 8# Change stm32f207zg to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
diff --git a/examples/stm32f2/src/bin/blinky.rs b/examples/stm32f2/src/bin/blinky.rs
index f6d7a0005..d9833ba8b 100644
--- a/examples/stm32f2/src/bin/blinky.rs
+++ b/examples/stm32f2/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs
index aae7637dc..e32f283d1 100644
--- a/examples/stm32f2/src/bin/pll.rs
+++ b/examples/stm32f2/src/bin/pll.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::convert::TryFrom; 4use core::convert::TryFrom;
6 5
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index ed1367858..d5ab0b25a 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32f303ze to your chip name, if necessary. 8# Change stm32f303ze to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -24,7 +24,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
24heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
25nb = "1.0.0" 25nb = "1.0.0"
26embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
27static_cell = { version = "2", features = ["nightly"]} 27static_cell = "2"
28 28
29[profile.release] 29[profile.release]
30debug = 2 30debug = 2
diff --git a/examples/stm32f3/src/bin/blinky.rs b/examples/stm32f3/src/bin/blinky.rs
index e71031b30..0ea10522d 100644
--- a/examples/stm32f3/src/bin/blinky.rs
+++ b/examples/stm32f3/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f3/src/bin/button.rs b/examples/stm32f3/src/bin/button.rs
index 2f47d8f80..2cd356787 100644
--- a/examples/stm32f3/src/bin/button.rs
+++ b/examples/stm32f3/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index 9df6d680d..2f7da4ef5 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -8,7 +8,6 @@
8 8
9#![no_std] 9#![no_std]
10#![no_main] 10#![no_main]
11#![feature(type_alias_impl_trait)]
12 11
13use defmt::*; 12use defmt::*;
14use embassy_executor::Spawner; 13use embassy_executor::Spawner;
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs
index 1266778c1..86ff68492 100644
--- a/examples/stm32f3/src/bin/button_exti.rs
+++ b/examples/stm32f3/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs
index 236fb36c1..28125697d 100644
--- a/examples/stm32f3/src/bin/flash.rs
+++ b/examples/stm32f3/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f3/src/bin/hello.rs b/examples/stm32f3/src/bin/hello.rs
index b3285f3c1..fd54da53d 100644
--- a/examples/stm32f3/src/bin/hello.rs
+++ b/examples/stm32f3/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index 74f3bb1c5..328447210 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::*; 60use defmt::*;
diff --git a/examples/stm32f3/src/bin/spi_dma.rs b/examples/stm32f3/src/bin/spi_dma.rs
index a27c1d547..54498d53d 100644
--- a/examples/stm32f3/src/bin/spi_dma.rs
+++ b/examples/stm32f3/src/bin/spi_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6use core::str::from_utf8; 5use core::str::from_utf8;
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs
index ce8c212ae..5234e53b9 100644
--- a/examples/stm32f3/src/bin/usart_dma.rs
+++ b/examples/stm32f3/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index d5d068d62..cf9ecedfa 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml
index 320cf7d7b..b29a08e7c 100644
--- a/examples/stm32f334/Cargo.toml
+++ b/examples/stm32f334/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
10embassy-time = { version = "0.2.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.2.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
12embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 12embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -23,4 +23,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
23heapless = { version = "0.8", default-features = false } 23heapless = { version = "0.8", default-features = false }
24nb = "1.0.0" 24nb = "1.0.0"
25embedded-storage = "0.3.1" 25embedded-storage = "0.3.1"
26static_cell = { version = "2", features = ["nightly"]} 26static_cell = "2"
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index f259135d2..063ee9dac 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f334/src/bin/button.rs b/examples/stm32f334/src/bin/button.rs
index 501fb080c..256f9a44a 100644
--- a/examples/stm32f334/src/bin/button.rs
+++ b/examples/stm32f334/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f334/src/bin/hello.rs b/examples/stm32f334/src/bin/hello.rs
index b3285f3c1..fd54da53d 100644
--- a/examples/stm32f334/src/bin/hello.rs
+++ b/examples/stm32f334/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index 10e7b3543..850a0e335 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
index 8040c3f18..c149cad92 100644
--- a/examples/stm32f334/src/bin/pwm.rs
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 6ea0018cd..a74e0f674 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -6,9 +6,9 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8# Change stm32f429zi to your chip name, if necessary. 8# Change stm32f429zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt" ] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt" ] }
14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] }
@@ -27,7 +27,7 @@ heapless = { version = "0.8", default-features = false }
27nb = "1.0.0" 27nb = "1.0.0"
28embedded-storage = "0.3.1" 28embedded-storage = "0.3.1"
29micromath = "2.0.0" 29micromath = "2.0.0"
30static_cell = { version = "2", features = ["nightly"]} 30static_cell = "2"
31chrono = { version = "^0.4", default-features = false} 31chrono = { version = "^0.4", default-features = false}
32 32
33[profile.release] 33[profile.release]
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs
index f19328727..699c29c05 100644
--- a/examples/stm32f4/src/bin/adc.rs
+++ b/examples/stm32f4/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; 4use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f4/src/bin/blinky.rs b/examples/stm32f4/src/bin/blinky.rs
index 4bfc5a50d..31cce8225 100644
--- a/examples/stm32f4/src/bin/blinky.rs
+++ b/examples/stm32f4/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/button.rs b/examples/stm32f4/src/bin/button.rs
index aa1eed46f..ad30a56a2 100644
--- a/examples/stm32f4/src/bin/button.rs
+++ b/examples/stm32f4/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f4/src/bin/button_exti.rs b/examples/stm32f4/src/bin/button_exti.rs
index dfe587d41..67751187d 100644
--- a/examples/stm32f4/src/bin/button_exti.rs
+++ b/examples/stm32f4/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs
index 20ce4edce..d074b4265 100644
--- a/examples/stm32f4/src/bin/can.rs
+++ b/examples/stm32f4/src/bin/can.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs
index 8f14d6078..9c7754c4f 100644
--- a/examples/stm32f4/src/bin/dac.rs
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs
index 088d83c06..7f5c8fdb1 100644
--- a/examples/stm32f4/src/bin/eth.rs
+++ b/examples/stm32f4/src/bin/eth.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -14,7 +13,7 @@ use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::Timer; 14use embassy_time::Timer;
16use embedded_io_async::Write; 15use embedded_io_async::Write;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -63,8 +62,9 @@ async fn main(spawner: Spawner) -> ! {
63 62
64 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 63 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
65 64
65 static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new();
66 let device = Ethernet::new( 66 let device = Ethernet::new(
67 make_static!(PacketQueue::<16, 16>::new()), 67 PACKETS.init(PacketQueue::<16, 16>::new()),
68 p.ETH, 68 p.ETH,
69 Irqs, 69 Irqs,
70 p.PA1, 70 p.PA1,
@@ -88,11 +88,13 @@ async fn main(spawner: Spawner) -> ! {
88 //}); 88 //});
89 89
90 // Init network stack 90 // Init network stack
91 let stack = &*make_static!(Stack::new( 91 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
92 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
93 let stack = &*STACK.init(Stack::new(
92 device, 94 device,
93 config, 95 config,
94 make_static!(StackResources::<2>::new()), 96 RESOURCES.init(StackResources::<2>::new()),
95 seed 97 seed,
96 )); 98 ));
97 99
98 // Launch network task 100 // Launch network task
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs
index 93c54e943..1e8cabab4 100644
--- a/examples/stm32f4/src/bin/flash.rs
+++ b/examples/stm32f4/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -31,7 +30,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) {
31 30
32 info!("Reading..."); 31 info!("Reading...");
33 let mut buf = [0u8; 32]; 32 let mut buf = [0u8; 32];
34 unwrap!(f.read(offset, &mut buf)); 33 unwrap!(f.blocking_read(offset, &mut buf));
35 info!("Read: {=[u8]:x}", buf); 34 info!("Read: {=[u8]:x}", buf);
36 35
37 info!("Erasing..."); 36 info!("Erasing...");
@@ -39,7 +38,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) {
39 38
40 info!("Reading..."); 39 info!("Reading...");
41 let mut buf = [0u8; 32]; 40 let mut buf = [0u8; 32];
42 unwrap!(f.read(offset, &mut buf)); 41 unwrap!(f.blocking_read(offset, &mut buf));
43 info!("Read after erase: {=[u8]:x}", buf); 42 info!("Read after erase: {=[u8]:x}", buf);
44 43
45 info!("Writing..."); 44 info!("Writing...");
@@ -53,7 +52,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) {
53 52
54 info!("Reading..."); 53 info!("Reading...");
55 let mut buf = [0u8; 32]; 54 let mut buf = [0u8; 32];
56 unwrap!(f.read(offset, &mut buf)); 55 unwrap!(f.blocking_read(offset, &mut buf));
57 info!("Read: {=[u8]:x}", buf); 56 info!("Read: {=[u8]:x}", buf);
58 assert_eq!( 57 assert_eq!(
59 &buf[..], 58 &buf[..],
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs
index f0a65a725..493a536f3 100644
--- a/examples/stm32f4/src/bin/flash_async.rs
+++ b/examples/stm32f4/src/bin/flash_async.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -48,7 +47,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) {
48 47
49 info!("Reading..."); 48 info!("Reading...");
50 let mut buf = [0u8; 32]; 49 let mut buf = [0u8; 32];
51 unwrap!(f.read(offset, &mut buf)); 50 unwrap!(f.blocking_read(offset, &mut buf));
52 info!("Read: {=[u8]:x}", buf); 51 info!("Read: {=[u8]:x}", buf);
53 52
54 info!("Erasing..."); 53 info!("Erasing...");
@@ -56,7 +55,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) {
56 55
57 info!("Reading..."); 56 info!("Reading...");
58 let mut buf = [0u8; 32]; 57 let mut buf = [0u8; 32];
59 unwrap!(f.read(offset, &mut buf)); 58 unwrap!(f.blocking_read(offset, &mut buf));
60 info!("Read after erase: {=[u8]:x}", buf); 59 info!("Read after erase: {=[u8]:x}", buf);
61 60
62 info!("Writing..."); 61 info!("Writing...");
@@ -73,7 +72,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) {
73 72
74 info!("Reading..."); 73 info!("Reading...");
75 let mut buf = [0u8; 32]; 74 let mut buf = [0u8; 32];
76 unwrap!(f.read(offset, &mut buf)); 75 unwrap!(f.blocking_read(offset, &mut buf));
77 info!("Read: {=[u8]:x}", buf); 76 info!("Read: {=[u8]:x}", buf);
78 assert_eq!( 77 assert_eq!(
79 &buf[..], 78 &buf[..],
diff --git a/examples/stm32f4/src/bin/hello.rs b/examples/stm32f4/src/bin/hello.rs
index a2a287110..3c295612c 100644
--- a/examples/stm32f4/src/bin/hello.rs
+++ b/examples/stm32f4/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
index 4f4adde28..4b5da774d 100644
--- a/examples/stm32f4/src/bin/i2c.rs
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs
index 9f59e4d41..90d11d4b4 100644
--- a/examples/stm32f4/src/bin/i2c_async.rs
+++ b/examples/stm32f4/src/bin/i2c_async.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5// Example originally designed for stm32f411ceu6 reading an A1454 hall effect sensor on I2C1 4// Example originally designed for stm32f411ceu6 reading an A1454 hall effect sensor on I2C1
6// DMA peripherals changed to compile for stm32f429zi, for the CI. 5// DMA peripherals changed to compile for stm32f429zi, for the CI.
diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs
index 6d23c0ed8..30cfbdf57 100644
--- a/examples/stm32f4/src/bin/i2c_comparison.rs
+++ b/examples/stm32f4/src/bin/i2c_comparison.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5// Example originally designed for stm32f411ceu6 with three A1454 hall effect sensors, connected to I2C1, 2 and 3 4// Example originally designed for stm32f411ceu6 with three A1454 hall effect sensors, connected to I2C1, 2 and 3
6// on the pins referenced in the peripheral definitions. 5// on the pins referenced in the peripheral definitions.
diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs
index e8d7b5f77..97a04b2aa 100644
--- a/examples/stm32f4/src/bin/i2s_dma.rs
+++ b/examples/stm32f4/src/bin/i2s_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs
index 3315e7652..eb7bb6261 100644
--- a/examples/stm32f4/src/bin/mco.rs
+++ b/examples/stm32f4/src/bin/mco.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index 74f3bb1c5..328447210 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::*; 60use defmt::*;
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 8e41d0e78..8844a9f0e 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index d925f26d9..161f43c48 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs
index 44b4303c0..abab07b6b 100644
--- a/examples/stm32f4/src/bin/rtc.rs
+++ b/examples/stm32f4/src/bin/rtc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index 91747b2d5..66e4e527c 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index 0919e9874..dc9141c62 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f4/src/bin/spi_dma.rs b/examples/stm32f4/src/bin/spi_dma.rs
index f291f7dba..7249c831a 100644
--- a/examples/stm32f4/src/bin/spi_dma.rs
+++ b/examples/stm32f4/src/bin/spi_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6use core::str::from_utf8; 5use core::str::from_utf8;
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index 45e94715f..40d9d70f1 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f4/src/bin/usart_buffered.rs b/examples/stm32f4/src/bin/usart_buffered.rs
index 71abc2893..c99807f11 100644
--- a/examples/stm32f4/src/bin/usart_buffered.rs
+++ b/examples/stm32f4/src/bin/usart_buffered.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index dca25a78c..dd6de599c 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 6bf5b1cba..a196259a8 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -14,7 +13,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState
14use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
15use embassy_usb::{Builder, UsbDevice}; 14use embassy_usb::{Builder, UsbDevice};
16use embedded_io_async::Write; 15use embedded_io_async::Write;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20type UsbDriver = Driver<'static, embassy_stm32::peripherals::USB_OTG_FS>; 19type UsbDriver = Driver<'static, embassy_stm32::peripherals::USB_OTG_FS>;
@@ -68,7 +67,8 @@ async fn main(spawner: Spawner) {
68 let p = embassy_stm32::init(config); 67 let p = embassy_stm32::init(config);
69 68
70 // Create the driver, from the HAL. 69 // Create the driver, from the HAL.
71 let ep_out_buffer = &mut make_static!([0; 256])[..]; 70 static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new();
71 let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..];
72 let mut config = embassy_stm32::usb_otg::Config::default(); 72 let mut config = embassy_stm32::usb_otg::Config::default();
73 config.vbus_detection = true; 73 config.vbus_detection = true;
74 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config); 74 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config);
@@ -88,14 +88,18 @@ async fn main(spawner: Spawner) {
88 config.device_protocol = 0x01; 88 config.device_protocol = 0x01;
89 89
90 // Create embassy-usb DeviceBuilder using the driver and config. 90 // Create embassy-usb DeviceBuilder using the driver and config.
91 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
92 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
93 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
94 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
91 let mut builder = Builder::new( 95 let mut builder = Builder::new(
92 driver, 96 driver,
93 config, 97 config,
94 &mut make_static!([0; 256])[..], 98 &mut DEVICE_DESC.init([0; 256])[..],
95 &mut make_static!([0; 256])[..], 99 &mut CONFIG_DESC.init([0; 256])[..],
96 &mut make_static!([0; 256])[..], 100 &mut BOS_DESC.init([0; 256])[..],
97 &mut [], // no msos descriptors 101 &mut [], // no msos descriptors
98 &mut make_static!([0; 128])[..], 102 &mut CONTROL_BUF.init([0; 128])[..],
99 ); 103 );
100 104
101 // Our MAC addr. 105 // Our MAC addr.
@@ -104,14 +108,16 @@ async fn main(spawner: Spawner) {
104 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; 108 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88];
105 109
106 // Create classes on the builder. 110 // Create classes on the builder.
107 let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); 111 static STATE: StaticCell<State> = StaticCell::new();
112 let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64);
108 113
109 // Build the builder. 114 // Build the builder.
110 let usb = builder.build(); 115 let usb = builder.build();
111 116
112 unwrap!(spawner.spawn(usb_task(usb))); 117 unwrap!(spawner.spawn(usb_task(usb)));
113 118
114 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); 119 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
120 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
115 unwrap!(spawner.spawn(usb_ncm_task(runner))); 121 unwrap!(spawner.spawn(usb_ncm_task(runner)));
116 122
117 let config = embassy_net::Config::dhcpv4(Default::default()); 123 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -128,11 +134,13 @@ async fn main(spawner: Spawner) {
128 let seed = u64::from_le_bytes(seed); 134 let seed = u64::from_le_bytes(seed);
129 135
130 // Init network stack 136 // Init network stack
131 let stack = &*make_static!(Stack::new( 137 static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new();
138 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
139 let stack = &*STACK.init(Stack::new(
132 device, 140 device,
133 config, 141 config,
134 make_static!(StackResources::<2>::new()), 142 RESOURCES.init(StackResources::<2>::new()),
135 seed 143 seed,
136 )); 144 ));
137 145
138 unwrap!(spawner.spawn(net_task(stack))); 146 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs
index 719b22bb9..afff55187 100644
--- a/examples/stm32f4/src/bin/usb_raw.rs
+++ b/examples/stm32f4/src/bin/usb_raw.rs
@@ -48,7 +48,6 @@
48 48
49#![no_std] 49#![no_std]
50#![no_main] 50#![no_main]
51#![feature(type_alias_impl_trait)]
52 51
53use defmt::*; 52use defmt::*;
54use embassy_executor::Spawner; 53use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index e2ccc9142..58d994a61 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs
index 0443b61c5..ea27ebce0 100644
--- a/examples/stm32f4/src/bin/wdt.rs
+++ b/examples/stm32f4/src/bin/wdt.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f4/src/bin/ws2812_pwm_dma.rs b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
index dccd639ac..dc397eff1 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm_dma.rs
@@ -17,7 +17,6 @@
17 17
18#![no_std] 18#![no_std]
19#![no_main] 19#![no_main]
20#![feature(type_alias_impl_trait)]
21 20
22use embassy_executor::Spawner; 21use embassy_executor::Spawner;
23use embassy_stm32::gpio::OutputType; 22use embassy_stm32::gpio::OutputType;
@@ -118,7 +117,7 @@ async fn main(_spawner: Spawner) {
118 &mut dp.DMA1_CH2, 117 &mut dp.DMA1_CH2,
119 5, 118 5,
120 color, 119 color,
121 pac::TIM3.ccr(pwm_channel.raw()).as_ptr() as *mut _, 120 pac::TIM3.ccr(pwm_channel.index()).as_ptr() as *mut _,
122 dma_transfer_option, 121 dma_transfer_option,
123 ) 122 )
124 .await; 123 .await;
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 4cca0d93c..b76a848a8 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32f767zi to your chip name, if necessary. 8# Change stm32f767zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
14embedded-io-async = { version = "0.6.1" } 14embedded-io-async = { version = "0.6.1" }
@@ -27,7 +27,7 @@ nb = "1.0.0"
27rand_core = "0.6.3" 27rand_core = "0.6.3"
28critical-section = "1.1" 28critical-section = "1.1"
29embedded-storage = "0.3.1" 29embedded-storage = "0.3.1"
30static_cell = { version = "2", features = ["nightly"]} 30static_cell = "2"
31 31
32[profile.release] 32[profile.release]
33debug = 2 33debug = 2
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs
index 48c59eaf0..f8d7b691f 100644
--- a/examples/stm32f7/src/bin/adc.rs
+++ b/examples/stm32f7/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/blinky.rs b/examples/stm32f7/src/bin/blinky.rs
index 4bfc5a50d..31cce8225 100644
--- a/examples/stm32f7/src/bin/blinky.rs
+++ b/examples/stm32f7/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/button.rs b/examples/stm32f7/src/bin/button.rs
index aa1eed46f..ad30a56a2 100644
--- a/examples/stm32f7/src/bin/button.rs
+++ b/examples/stm32f7/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32f7/src/bin/button_exti.rs b/examples/stm32f7/src/bin/button_exti.rs
index dfe587d41..67751187d 100644
--- a/examples/stm32f7/src/bin/button_exti.rs
+++ b/examples/stm32f7/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index 78b21ceaa..bcfdb67a8 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -12,6 +11,7 @@ use embassy_stm32::can::{
12}; 11};
13use embassy_stm32::gpio::{Input, Pull}; 12use embassy_stm32::gpio::{Input, Pull};
14use embassy_stm32::peripherals::CAN3; 13use embassy_stm32::peripherals::CAN3;
14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs { 17bind_interrupts!(struct Irqs {
@@ -43,7 +43,8 @@ async fn main(spawner: Spawner) {
43 let rx_pin = Input::new(&mut p.PA15, Pull::Up); 43 let rx_pin = Input::new(&mut p.PA15, Pull::Up);
44 core::mem::forget(rx_pin); 44 core::mem::forget(rx_pin);
45 45
46 let can: &'static mut Can<'static, CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); 46 static CAN: StaticCell<Can<'static, CAN3>> = StaticCell::new();
47 let can = CAN.init(Can::new(p.CAN3, p.PA8, p.PA15, Irqs));
47 can.as_mut() 48 can.as_mut()
48 .modify_filters() 49 .modify_filters()
49 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); 50 .enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
@@ -56,7 +57,8 @@ async fn main(spawner: Spawner) {
56 57
57 let (tx, mut rx) = can.split(); 58 let (tx, mut rx) = can.split();
58 59
59 let tx: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); 60 static CAN_TX: StaticCell<CanTx<'static, 'static, CAN3>> = StaticCell::new();
61 let tx = CAN_TX.init(tx);
60 spawner.spawn(send_can_message(tx)).unwrap(); 62 spawner.spawn(send_can_message(tx)).unwrap();
61 63
62 loop { 64 loop {
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index dd0069447..5bff48197 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -15,7 +14,7 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::Timer; 14use embassy_time::Timer;
16use embedded_io_async::Write; 15use embedded_io_async::Write;
17use rand_core::RngCore; 16use rand_core::RngCore;
18use static_cell::make_static; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
21bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
@@ -64,8 +63,9 @@ async fn main(spawner: Spawner) -> ! {
64 63
65 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 64 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
66 65
66 static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new();
67 let device = Ethernet::new( 67 let device = Ethernet::new(
68 make_static!(PacketQueue::<16, 16>::new()), 68 PACKETS.init(PacketQueue::<16, 16>::new()),
69 p.ETH, 69 p.ETH,
70 Irqs, 70 Irqs,
71 p.PA1, 71 p.PA1,
@@ -89,11 +89,13 @@ async fn main(spawner: Spawner) -> ! {
89 //}); 89 //});
90 90
91 // Init network stack 91 // Init network stack
92 let stack = &*make_static!(Stack::new( 92 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
93 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
94 let stack = &*STACK.init(Stack::new(
93 device, 95 device,
94 config, 96 config,
95 make_static!(StackResources::<2>::new()), 97 RESOURCES.init(StackResources::<2>::new()),
96 seed 98 seed,
97 )); 99 ));
98 100
99 // Launch network task 101 // Launch network task
diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs
index 06a94f1c8..885570478 100644
--- a/examples/stm32f7/src/bin/flash.rs
+++ b/examples/stm32f7/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/hello.rs b/examples/stm32f7/src/bin/hello.rs
index a2a287110..3c295612c 100644
--- a/examples/stm32f7/src/bin/hello.rs
+++ b/examples/stm32f7/src/bin/hello.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::info; 4use defmt::info;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs
index 990de0ab1..6d36ef518 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/usart_dma.rs b/examples/stm32f7/src/bin/usart_dma.rs
index ba064081e..fb604b34f 100644
--- a/examples/stm32f7/src/bin/usart_dma.rs
+++ b/examples/stm32f7/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index 4991edbf0..97daf6bd1 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index b1e749440..0abc0a638 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32g071rb to your chip name, if necessary. 8# Change stm32g071rb to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
diff --git a/examples/stm32g0/src/bin/blinky.rs b/examples/stm32g0/src/bin/blinky.rs
index 4bfc5a50d..31cce8225 100644
--- a/examples/stm32g0/src/bin/blinky.rs
+++ b/examples/stm32g0/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g0/src/bin/button.rs b/examples/stm32g0/src/bin/button.rs
index 40c58013b..265200132 100644
--- a/examples/stm32g0/src/bin/button.rs
+++ b/examples/stm32g0/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32g0/src/bin/button_exti.rs b/examples/stm32g0/src/bin/button_exti.rs
index ef32d4c4a..1e970fdd6 100644
--- a/examples/stm32g0/src/bin/button_exti.rs
+++ b/examples/stm32g0/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g0/src/bin/flash.rs b/examples/stm32g0/src/bin/flash.rs
index ed9f2e843..acef87b92 100644
--- a/examples/stm32g0/src/bin/flash.rs
+++ b/examples/stm32g0/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g0/src/bin/spi_neopixel.rs b/examples/stm32g0/src/bin/spi_neopixel.rs
index 214462d0e..c5ea51721 100644
--- a/examples/stm32g0/src/bin/spi_neopixel.rs
+++ b/examples/stm32g0/src/bin/spi_neopixel.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index c56a63623..987f23b3a 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32g491re to your chip name, if necessary. 8# Change stm32g491re to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs
index 63b20c0d4..35324d931 100644
--- a/examples/stm32g4/src/bin/adc.rs
+++ b/examples/stm32g4/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/src/bin/blinky.rs b/examples/stm32g4/src/bin/blinky.rs
index cbeb0dee1..90e479aae 100644
--- a/examples/stm32g4/src/bin/blinky.rs
+++ b/examples/stm32g4/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/src/bin/button.rs b/examples/stm32g4/src/bin/button.rs
index 127efb08a..6f3db0819 100644
--- a/examples/stm32g4/src/bin/button.rs
+++ b/examples/stm32g4/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32g4/src/bin/button_exti.rs b/examples/stm32g4/src/bin/button_exti.rs
index dfe587d41..67751187d 100644
--- a/examples/stm32g4/src/bin/button_exti.rs
+++ b/examples/stm32g4/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs
index 09ef59d44..46ebe0b0d 100644
--- a/examples/stm32g4/src/bin/pll.rs
+++ b/examples/stm32g4/src/bin/pll.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index a84394005..d4809a481 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs
index 565b25d60..c26fa76b7 100644
--- a/examples/stm32g4/src/bin/usb_serial.rs
+++ b/examples/stm32g4/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index f714a3984..8815b8e47 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32h563zi to your chip name, if necessary. 8# Change stm32h563zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -31,7 +31,7 @@ critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = { version = "2", features = ["nightly"]} 34static_cell = "2"
35 35
36# cargo build/run 36# cargo build/run
37[profile.dev] 37[profile.dev]
diff --git a/examples/stm32h5/src/bin/blinky.rs b/examples/stm32h5/src/bin/blinky.rs
index 1394f03fa..f37e8b1d8 100644
--- a/examples/stm32h5/src/bin/blinky.rs
+++ b/examples/stm32h5/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/src/bin/button_exti.rs b/examples/stm32h5/src/bin/button_exti.rs
index dfe587d41..67751187d 100644
--- a/examples/stm32h5/src/bin/button_exti.rs
+++ b/examples/stm32h5/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index b2758cba0..2370656e6 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -18,7 +17,7 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
18use embassy_time::Timer; 17use embassy_time::Timer;
19use embedded_io_async::Write; 18use embedded_io_async::Write;
20use rand_core::RngCore; 19use rand_core::RngCore;
21use static_cell::make_static; 20use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
23 22
24bind_interrupts!(struct Irqs { 23bind_interrupts!(struct Irqs {
@@ -67,8 +66,9 @@ async fn main(spawner: Spawner) -> ! {
67 66
68 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 67 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
69 68
69 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
70 let device = Ethernet::new( 70 let device = Ethernet::new(
71 make_static!(PacketQueue::<4, 4>::new()), 71 PACKETS.init(PacketQueue::<4, 4>::new()),
72 p.ETH, 72 p.ETH,
73 Irqs, 73 Irqs,
74 p.PA1, 74 p.PA1,
@@ -92,11 +92,13 @@ async fn main(spawner: Spawner) -> ! {
92 //}); 92 //});
93 93
94 // Init network stack 94 // Init network stack
95 let stack = &*make_static!(Stack::new( 95 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
96 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
97 let stack = &*STACK.init(Stack::new(
96 device, 98 device,
97 config, 99 config,
98 make_static!(StackResources::<2>::new()), 100 RESOURCES.init(StackResources::<2>::new()),
99 seed 101 seed,
100 )); 102 ));
101 103
102 // Launch network task 104 // Launch network task
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs
index 31783a2bf..31e83cbb5 100644
--- a/examples/stm32h5/src/bin/i2c.rs
+++ b/examples/stm32h5/src/bin/i2c.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/src/bin/rng.rs b/examples/stm32h5/src/bin/rng.rs
index 7c8c50eca..9c0d704b5 100644
--- a/examples/stm32h5/src/bin/rng.rs
+++ b/examples/stm32h5/src/bin/rng.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs
index db04d4e55..f9cbad6af 100644
--- a/examples/stm32h5/src/bin/usart.rs
+++ b/examples/stm32h5/src/bin/usart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs
index bafe50839..caae0dd18 100644
--- a/examples/stm32h5/src/bin/usart_dma.rs
+++ b/examples/stm32h5/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs
index d9037c014..92047de8d 100644
--- a/examples/stm32h5/src/bin/usart_split.rs
+++ b/examples/stm32h5/src/bin/usart_split.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index 7d45818af..208493d8c 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index c6aea3e11..31feeda45 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32h743bi to your chip name, if necessary. 8# Change stm32h743bi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -31,7 +31,7 @@ critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = { version = "2", features = ["nightly"]} 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
36 36
37# cargo build/run 37# cargo build/run
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs
index e367827e9..fe6fe69a1 100644
--- a/examples/stm32h7/src/bin/adc.rs
+++ b/examples/stm32h7/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/blinky.rs b/examples/stm32h7/src/bin/blinky.rs
index a9cab1ff4..1ee90a870 100644
--- a/examples/stm32h7/src/bin/blinky.rs
+++ b/examples/stm32h7/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/button_exti.rs b/examples/stm32h7/src/bin/button_exti.rs
index dfe587d41..67751187d 100644
--- a/examples/stm32h7/src/bin/button_exti.rs
+++ b/examples/stm32h7/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 489fb03dd..e5a104baf 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use embassy_executor::Spawner; 4use embassy_executor::Spawner;
6use embassy_stm32::dcmi::{self, *}; 5use embassy_stm32::dcmi::{self, *};
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index f66268151..a9bf46de0 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index c19fdd623..1481dd967 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index dbddfc22f..cd9a27fcd 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -14,7 +13,7 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
14use embassy_time::Timer; 13use embassy_time::Timer;
15use embedded_io_async::Write; 14use embedded_io_async::Write;
16use rand_core::RngCore; 15use rand_core::RngCore;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -64,8 +63,9 @@ async fn main(spawner: Spawner) -> ! {
64 63
65 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 64 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
66 65
66 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
67 let device = Ethernet::new( 67 let device = Ethernet::new(
68 make_static!(PacketQueue::<16, 16>::new()), 68 PACKETS.init(PacketQueue::<4, 4>::new()),
69 p.ETH, 69 p.ETH,
70 Irqs, 70 Irqs,
71 p.PA1, 71 p.PA1,
@@ -89,11 +89,13 @@ async fn main(spawner: Spawner) -> ! {
89 //}); 89 //});
90 90
91 // Init network stack 91 // Init network stack
92 let stack = &*make_static!(Stack::new( 92 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
93 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
94 let stack = &*STACK.init(Stack::new(
93 device, 95 device,
94 config, 96 config,
95 make_static!(StackResources::<3>::new()), 97 RESOURCES.init(StackResources::<3>::new()),
96 seed 98 seed,
97 )); 99 ));
98 100
99 // Launch network task 101 // Launch network task
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 17e1d9fb7..dcc6e36e2 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -15,7 +14,7 @@ use embassy_time::Timer;
15use embedded_io_async::Write; 14use embedded_io_async::Write;
16use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; 15use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
17use rand_core::RngCore; 16use rand_core::RngCore;
18use static_cell::make_static; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
21bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
@@ -65,8 +64,9 @@ async fn main(spawner: Spawner) -> ! {
65 64
66 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 65 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
67 66
67 static PACKETS: StaticCell<PacketQueue<16, 16>> = StaticCell::new();
68 let device = Ethernet::new( 68 let device = Ethernet::new(
69 make_static!(PacketQueue::<16, 16>::new()), 69 PACKETS.init(PacketQueue::<16, 16>::new()),
70 p.ETH, 70 p.ETH,
71 Irqs, 71 Irqs,
72 p.PA1, 72 p.PA1,
@@ -90,11 +90,13 @@ async fn main(spawner: Spawner) -> ! {
90 //}); 90 //});
91 91
92 // Init network stack 92 // Init network stack
93 let stack = &*make_static!(Stack::new( 93 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
94 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
95 let stack = &*STACK.init(Stack::new(
94 device, 96 device,
95 config, 97 config,
96 make_static!(StackResources::<3>::new()), 98 RESOURCES.init(StackResources::<3>::new()),
97 seed 99 seed,
98 )); 100 ));
99 101
100 // Launch network task 102 // Launch network task
diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs
index 89c0c8a66..4f9f6bb0a 100644
--- a/examples/stm32h7/src/bin/flash.rs
+++ b/examples/stm32h7/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs
index 54e2c3629..5e5e6ccc8 100644
--- a/examples/stm32h7/src/bin/fmc.rs
+++ b/examples/stm32h7/src/bin/fmc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
index aea21ec6f..3bf39eb44 100644
--- a/examples/stm32h7/src/bin/i2c.rs
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index e0be495d1..cc508c3cf 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -85,7 +84,7 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
85 84
86 let mut this = Self { inner: tim }; 85 let mut this = Self { inner: tim };
87 86
88 this.set_freq(freq); 87 this.set_frequency(freq);
89 this.inner.start(); 88 this.inner.start();
90 89
91 let r = T::regs_gp32(); 90 let r = T::regs_gp32();
@@ -102,14 +101,14 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
102 } 101 }
103 102
104 pub fn enable(&mut self, channel: Channel) { 103 pub fn enable(&mut self, channel: Channel) {
105 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), true)); 104 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true));
106 } 105 }
107 106
108 pub fn disable(&mut self, channel: Channel) { 107 pub fn disable(&mut self, channel: Channel) {
109 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), false)); 108 T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false));
110 } 109 }
111 110
112 pub fn set_freq(&mut self, freq: Hertz) { 111 pub fn set_frequency(&mut self, freq: Hertz) {
113 <T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::set_frequency(&mut self.inner, freq); 112 <T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::set_frequency(&mut self.inner, freq);
114 } 113 }
115 114
@@ -119,6 +118,6 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
119 118
120 pub fn set_duty(&mut self, channel: Channel, duty: u32) { 119 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
121 defmt::assert!(duty < self.get_max_duty()); 120 defmt::assert!(duty < self.get_max_duty());
122 T::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(duty)) 121 T::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(duty))
123 } 122 }
124} 123}
diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs
index c023f4584..a6ee27625 100644
--- a/examples/stm32h7/src/bin/mco.rs
+++ b/examples/stm32h7/src/bin/mco.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index c55d780a0..1e48ba67b 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs
index 1fb4cfec0..a9ef7200d 100644
--- a/examples/stm32h7/src/bin/rng.rs
+++ b/examples/stm32h7/src/bin/rng.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs
index 78cea9c89..c6b9cf57e 100644
--- a/examples/stm32h7/src/bin/rtc.rs
+++ b/examples/stm32h7/src/bin/rtc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index be968ff77..abe2d4ba7 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs
index b5f583289..b73360f32 100644
--- a/examples/stm32h7/src/bin/signal.rs
+++ b/examples/stm32h7/src/bin/signal.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index a8db0ff77..aed27723a 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6use core::str::from_utf8; 5use core::str::from_utf8;
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 561052e48..54d4d7656 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6use core::str::from_utf8; 5use core::str::from_utf8;
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index db04d4e55..f9cbad6af 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index 249050fd1..ae1f3a2e9 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index 61c9f1954..b98c40877 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index f80cf63ec..d81efb541 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs
index 76fd9dfc0..a4184aa96 100644
--- a/examples/stm32h7/src/bin/wdg.rs
+++ b/examples/stm32h7/src/bin/wdg.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 7c8264739..739aa6cb1 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -4,10 +4,6 @@ name = "embassy-stm32l0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7[features]
8default = ["nightly"]
9nightly = ["embassy-executor/nightly"]
10
11[dependencies] 7[dependencies]
12# Change stm32l072cz to your chip name, if necessary. 8# Change stm32l072cz to your chip name, if necessary.
13embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
diff --git a/examples/stm32l0/src/bin/blinky.rs b/examples/stm32l0/src/bin/blinky.rs
index ea40bfc48..caca5759f 100644
--- a/examples/stm32l0/src/bin/blinky.rs
+++ b/examples/stm32l0/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/button.rs b/examples/stm32l0/src/bin/button.rs
index 3e56160e9..165a714a5 100644
--- a/examples/stm32l0/src/bin/button.rs
+++ b/examples/stm32l0/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index ffede253e..f517fce04 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs
index 86f6c70b9..1865748fd 100644
--- a/examples/stm32l0/src/bin/flash.rs
+++ b/examples/stm32l0/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs
index 583e3d127..f23a537b8 100644
--- a/examples/stm32l0/src/bin/spi.rs
+++ b/examples/stm32l0/src/bin/spi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/usart_dma.rs b/examples/stm32l0/src/bin/usart_dma.rs
index 62c9b5595..74889c838 100644
--- a/examples/stm32l0/src/bin/usart_dma.rs
+++ b/examples/stm32l0/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs
index 5107a1a0a..2c96a8bc2 100644
--- a/examples/stm32l0/src/bin/usart_irq.rs
+++ b/examples/stm32l0/src/bin/usart_irq.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index 23dd0ef87..071d6a502 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 8embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 9embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
10embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
12 12
diff --git a/examples/stm32l1/src/bin/blinky.rs b/examples/stm32l1/src/bin/blinky.rs
index 06f732eb7..da6777b2d 100644
--- a/examples/stm32l1/src/bin/blinky.rs
+++ b/examples/stm32l1/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs
index aeb535cca..e9ce4eae8 100644
--- a/examples/stm32l1/src/bin/flash.rs
+++ b/examples/stm32l1/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l1/src/bin/spi.rs b/examples/stm32l1/src/bin/spi.rs
index 905b4d75c..8be686c5a 100644
--- a/examples/stm32l1/src/bin/spi.rs
+++ b/examples/stm32l1/src/bin/spi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 2861216d4..8a5fb5749 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32l4s5vi to your chip name, if necessary. 8# Change stm32l4s5vi to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "chrono"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", ] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
@@ -32,7 +32,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
32heapless = { version = "0.8", default-features = false } 32heapless = { version = "0.8", default-features = false }
33chrono = { version = "^0.4", default-features = false } 33chrono = { version = "^0.4", default-features = false }
34rand = { version = "0.8.5", default-features = false } 34rand = { version = "0.8.5", default-features = false }
35static_cell = { version = "2", features = ["nightly"]} 35static_cell = "2"
36 36
37micromath = "2.0.0" 37micromath = "2.0.0"
38 38
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs
index a0ec5c33e..d01e9f1b3 100644
--- a/examples/stm32l4/src/bin/adc.rs
+++ b/examples/stm32l4/src/bin/adc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_stm32::adc::{Adc, Resolution}; 5use embassy_stm32::adc::{Adc, Resolution};
diff --git a/examples/stm32l4/src/bin/blinky.rs b/examples/stm32l4/src/bin/blinky.rs
index 6202fe2f7..b55dfd35e 100644
--- a/examples/stm32l4/src/bin/blinky.rs
+++ b/examples/stm32l4/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/button.rs b/examples/stm32l4/src/bin/button.rs
index 0a102c2d6..15288c61e 100644
--- a/examples/stm32l4/src/bin/button.rs
+++ b/examples/stm32l4/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_stm32::gpio::{Input, Pull}; 5use embassy_stm32::gpio::{Input, Pull};
diff --git a/examples/stm32l4/src/bin/button_exti.rs b/examples/stm32l4/src/bin/button_exti.rs
index ef32d4c4a..1e970fdd6 100644
--- a/examples/stm32l4/src/bin/button_exti.rs
+++ b/examples/stm32l4/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index d6a7ff624..fdbf1d374 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_stm32::dac::{DacCh1, Value}; 5use embassy_stm32::dac::{DacCh1, Value};
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index dc86dbf43..64c541caa 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs
index 07dc12e8c..f553deb82 100644
--- a/examples/stm32l4/src/bin/i2c.rs
+++ b/examples/stm32l4/src/bin/i2c.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs
index 60a4e2eb3..1b8652bcc 100644
--- a/examples/stm32l4/src/bin/i2c_blocking_async.rs
+++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_embedded_hal::adapter::BlockingAsync; 5use embassy_embedded_hal::adapter::BlockingAsync;
diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs
index 4c2c224a6..794972a33 100644
--- a/examples/stm32l4/src/bin/i2c_dma.rs
+++ b/examples/stm32l4/src/bin/i2c_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs
index 504879887..36c002952 100644
--- a/examples/stm32l4/src/bin/mco.rs
+++ b/examples/stm32l4/src/bin/mco.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs
index e5ad56fb9..638b3e9e4 100644
--- a/examples/stm32l4/src/bin/rng.rs
+++ b/examples/stm32l4/src/bin/rng.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index d2a2aa1f2..526620bfb 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 8ec810c7f..9565ae168 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -1,10 +1,7 @@
1#![deny(clippy::pedantic)]
2#![allow(clippy::doc_markdown)]
3#![no_main] 1#![no_main]
4#![no_std] 2#![no_std]
5// Needed unitl https://github.com/rust-lang/rust/issues/63063 is stablised. 3#![deny(clippy::pedantic)]
6#![feature(type_alias_impl_trait)] 4#![allow(clippy::doc_markdown)]
7#![feature(associated_type_bounds)]
8#![allow(clippy::missing_errors_doc)] 5#![allow(clippy::missing_errors_doc)]
9 6
10// This example works on a ANALOG DEVICE EVAL-ADIN110EBZ board. 7// This example works on a ANALOG DEVICE EVAL-ADIN110EBZ board.
@@ -36,7 +33,7 @@ use hal::rng::{self, Rng};
36use hal::{bind_interrupts, exti, pac, peripherals}; 33use hal::{bind_interrupts, exti, pac, peripherals};
37use heapless::Vec; 34use heapless::Vec;
38use rand::RngCore; 35use rand::RngCore;
39use static_cell::make_static; 36use static_cell::StaticCell;
40use {embassy_stm32 as hal, panic_probe as _}; 37use {embassy_stm32 as hal, panic_probe as _};
41 38
42bind_interrupts!(struct Irqs { 39bind_interrupts!(struct Irqs {
@@ -180,7 +177,8 @@ async fn main(spawner: Spawner) {
180 } 177 }
181 }; 178 };
182 179
183 let state = make_static!(embassy_net_adin1110::State::<8, 8>::new()); 180 static STATE: StaticCell<embassy_net_adin1110::State<8, 8>> = StaticCell::new();
181 let state = STATE.init(embassy_net_adin1110::State::<8, 8>::new());
184 182
185 let (device, runner) = embassy_net_adin1110::new( 183 let (device, runner) = embassy_net_adin1110::new(
186 MAC, 184 MAC,
@@ -217,11 +215,13 @@ async fn main(spawner: Spawner) {
217 }; 215 };
218 216
219 // Init network stack 217 // Init network stack
220 let stack = &*make_static!(Stack::new( 218 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
219 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
220 let stack = &*STACK.init(Stack::new(
221 device, 221 device,
222 ip_cfg, 222 ip_cfg,
223 make_static!(StackResources::<2>::new()), 223 RESOURCES.init(StackResources::<2>::new()),
224 seed 224 seed,
225 )); 225 ));
226 226
227 // Launch network task 227 // Launch network task
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 54cf68f7b..6653e4516 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_stm32::dma::NoDma; 5use embassy_stm32::dma::NoDma;
diff --git a/examples/stm32l4/src/bin/spi_blocking_async.rs b/examples/stm32l4/src/bin/spi_blocking_async.rs
index 903ca58df..a989a5a4a 100644
--- a/examples/stm32l4/src/bin/spi_blocking_async.rs
+++ b/examples/stm32l4/src/bin/spi_blocking_async.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_embedded_hal::adapter::BlockingAsync; 5use embassy_embedded_hal::adapter::BlockingAsync;
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs
index 58cf2e51e..7922165df 100644
--- a/examples/stm32l4/src/bin/spi_dma.rs
+++ b/examples/stm32l4/src/bin/spi_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
index f4da6b5ae..7bab23950 100644
--- a/examples/stm32l4/src/bin/usart.rs
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_stm32::dma::NoDma; 5use embassy_stm32::dma::NoDma;
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
index 2f3b2a0f0..031888f70 100644
--- a/examples/stm32l4/src/bin/usart_dma.rs
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::fmt::Write; 4use core::fmt::Write;
6 5
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index 4baf5f05d..8cc9a7aed 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 2557ef42d..0d236ec90 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32l552ze to your chip name, if necessary. 8# Change stm32l552ze to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
@@ -26,7 +26,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27rand_core = { version = "0.6.3", default-features = false } 27rand_core = { version = "0.6.3", default-features = false }
28embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.6.1" }
29static_cell = { version = "2", features = ["nightly"]} 29static_cell = "2"
30 30
31[profile.release] 31[profile.release]
32debug = 2 32debug = 2
diff --git a/examples/stm32l5/src/bin/button_exti.rs b/examples/stm32l5/src/bin/button_exti.rs
index e80ad2b3a..91d0ccc2e 100644
--- a/examples/stm32l5/src/bin/button_exti.rs
+++ b/examples/stm32l5/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs
index 279f4f65d..50da6c946 100644
--- a/examples/stm32l5/src/bin/rng.rs
+++ b/examples/stm32l5/src/bin/rng.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 0b0a0e2db..88060b6b0 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -15,7 +14,7 @@ use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
15use embassy_usb::{Builder, UsbDevice}; 14use embassy_usb::{Builder, UsbDevice};
16use embedded_io_async::Write; 15use embedded_io_async::Write;
17use rand_core::RngCore; 16use rand_core::RngCore;
18use static_cell::make_static; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
21type MyDriver = Driver<'static, embassy_stm32::peripherals::USB>; 20type MyDriver = Driver<'static, embassy_stm32::peripherals::USB>;
@@ -76,14 +75,18 @@ async fn main(spawner: Spawner) {
76 config.device_protocol = 0x01; 75 config.device_protocol = 0x01;
77 76
78 // Create embassy-usb DeviceBuilder using the driver and config. 77 // Create embassy-usb DeviceBuilder using the driver and config.
78 static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new();
79 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
80 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
81 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
79 let mut builder = Builder::new( 82 let mut builder = Builder::new(
80 driver, 83 driver,
81 config, 84 config,
82 &mut make_static!([0; 256])[..], 85 &mut DEVICE_DESC.init([0; 256])[..],
83 &mut make_static!([0; 256])[..], 86 &mut CONFIG_DESC.init([0; 256])[..],
84 &mut make_static!([0; 256])[..], 87 &mut BOS_DESC.init([0; 256])[..],
85 &mut [], // no msos descriptors 88 &mut [], // no msos descriptors
86 &mut make_static!([0; 128])[..], 89 &mut CONTROL_BUF.init([0; 128])[..],
87 ); 90 );
88 91
89 // Our MAC addr. 92 // Our MAC addr.
@@ -92,14 +95,16 @@ async fn main(spawner: Spawner) {
92 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; 95 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88];
93 96
94 // Create classes on the builder. 97 // Create classes on the builder.
95 let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); 98 static STATE: StaticCell<State> = StaticCell::new();
99 let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64);
96 100
97 // Build the builder. 101 // Build the builder.
98 let usb = builder.build(); 102 let usb = builder.build();
99 103
100 unwrap!(spawner.spawn(usb_task(usb))); 104 unwrap!(spawner.spawn(usb_task(usb)));
101 105
102 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); 106 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
107 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
103 unwrap!(spawner.spawn(usb_ncm_task(runner))); 108 unwrap!(spawner.spawn(usb_ncm_task(runner)));
104 109
105 let config = embassy_net::Config::dhcpv4(Default::default()); 110 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -114,11 +119,13 @@ async fn main(spawner: Spawner) {
114 let seed = rng.next_u64(); 119 let seed = rng.next_u64();
115 120
116 // Init network stack 121 // Init network stack
117 let stack = &*make_static!(Stack::new( 122 static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new();
123 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
124 let stack = &*STACK.init(Stack::new(
118 device, 125 device,
119 config, 126 config,
120 make_static!(StackResources::<2>::new()), 127 RESOURCES.init(StackResources::<2>::new()),
121 seed 128 seed,
122 )); 129 ));
123 130
124 unwrap!(spawner.spawn(net_task(stack))); 131 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index 3614a8e0a..7c8a8ebfb 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index f2b894b68..75053ce4b 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index 1afbd8db4..029b2cfe0 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32u585ai to your chip name, if necessary. 8# Change stm32u585ai to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
14 14
diff --git a/examples/stm32u5/src/bin/blinky.rs b/examples/stm32u5/src/bin/blinky.rs
index 4b44cb12b..7fe88c183 100644
--- a/examples/stm32u5/src/bin/blinky.rs
+++ b/examples/stm32u5/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32u5/src/bin/boot.rs b/examples/stm32u5/src/bin/boot.rs
index e2112ce5c..23c7f8b22 100644
--- a/examples/stm32u5/src/bin/boot.rs
+++ b/examples/stm32u5/src/bin/boot.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use {defmt_rtt as _, embassy_stm32 as _, panic_probe as _}; 5use {defmt_rtt as _, embassy_stm32 as _, panic_probe as _};
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index 839d6472f..44d1df4f1 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{panic, *}; 4use defmt::{panic, *};
6use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index ada1f32e9..bce53c440 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
10embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } 10embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
11embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 12embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
13embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true }
15 15
@@ -22,7 +22,7 @@ embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "0.3", features = ["print-defmt"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 23futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
25static_cell = { version = "2", features = ["nightly"]} 25static_cell = "2"
26 26
27[features] 27[features]
28default = ["ble", "mac"] 28default = ["ble", "mac"]
diff --git a/examples/stm32wb/src/bin/blinky.rs b/examples/stm32wb/src/bin/blinky.rs
index 1394f03fa..f37e8b1d8 100644
--- a/examples/stm32wb/src/bin/blinky.rs
+++ b/examples/stm32wb/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs
index 3648db6ff..d34dde3e9 100644
--- a/examples/stm32wb/src/bin/button_exti.rs
+++ b/examples/stm32wb/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs
index e58da8e35..cf9a5aa28 100644
--- a/examples/stm32wb/src/bin/eddystone_beacon.rs
+++ b/examples/stm32wb/src/bin/eddystone_beacon.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::time::Duration; 4use core::time::Duration;
6 5
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs
index 80e835c1d..5ce620350 100644
--- a/examples/stm32wb/src/bin/gatt_server.rs
+++ b/examples/stm32wb/src/bin/gatt_server.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::time::Duration; 4use core::time::Duration;
6 5
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index 881dc488d..5cd660543 100644
--- a/examples/stm32wb/src/bin/mac_ffd.rs
+++ b/examples/stm32wb/src/bin/mac_ffd.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index f8c76b5a4..7a42bf577 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
@@ -12,7 +11,7 @@ use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
12use embassy_stm32_wpan::mac::{self, Runner}; 11use embassy_stm32_wpan::mac::{self, Runner};
13use embassy_stm32_wpan::sub::mm; 12use embassy_stm32_wpan::sub::mm;
14use embassy_stm32_wpan::TlMbox; 13use embassy_stm32_wpan::TlMbox;
15use static_cell::make_static; 14use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
18bind_interrupts!(struct Irqs{ 17bind_interrupts!(struct Irqs{
@@ -154,15 +153,21 @@ async fn main(spawner: Spawner) {
154 .unwrap(); 153 .unwrap();
155 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 154 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
156 155
156 static TX1: StaticCell<[u8; 127]> = StaticCell::new();
157 static TX2: StaticCell<[u8; 127]> = StaticCell::new();
158 static TX3: StaticCell<[u8; 127]> = StaticCell::new();
159 static TX4: StaticCell<[u8; 127]> = StaticCell::new();
160 static TX5: StaticCell<[u8; 127]> = StaticCell::new();
157 let tx_queue = [ 161 let tx_queue = [
158 make_static!([0u8; 127]), 162 TX1.init([0u8; 127]),
159 make_static!([0u8; 127]), 163 TX2.init([0u8; 127]),
160 make_static!([0u8; 127]), 164 TX3.init([0u8; 127]),
161 make_static!([0u8; 127]), 165 TX4.init([0u8; 127]),
162 make_static!([0u8; 127]), 166 TX5.init([0u8; 127]),
163 ]; 167 ];
164 168
165 let runner = make_static!(Runner::new(mbox.mac_subsystem, tx_queue)); 169 static RUNNER: StaticCell<Runner> = StaticCell::new();
170 let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue));
166 171
167 spawner.spawn(run_mac(runner)).unwrap(); 172 spawner.spawn(run_mac(runner)).unwrap();
168 173
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index 000355de6..7949211fb 100644
--- a/examples/stm32wb/src/bin/mac_rfd.rs
+++ b/examples/stm32wb/src/bin/mac_rfd.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 9d0e0070c..cb92d462d 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs
index 12c6aeebb..2599e1151 100644
--- a/examples/stm32wb/src/bin/tl_mbox_ble.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
index f32e07d96..5d868412a 100644
--- a/examples/stm32wb/src/bin/tl_mbox_mac.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml
index c97605937..84eb6c831 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } 8embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] }
9embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 10embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
11embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 11embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
12embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } 12embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true }
13 13
@@ -20,7 +20,7 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.8", default-features = false } 22heapless = { version = "0.8", default-features = false }
23static_cell = { version = "2", features = ["nightly"]} 23static_cell = "2"
24 24
25[profile.release] 25[profile.release]
26debug = 2 26debug = 2
diff --git a/examples/stm32wba/src/bin/blinky.rs b/examples/stm32wba/src/bin/blinky.rs
index 6b9635e66..0d803b257 100644
--- a/examples/stm32wba/src/bin/blinky.rs
+++ b/examples/stm32wba/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wba/src/bin/button_exti.rs b/examples/stm32wba/src/bin/button_exti.rs
index ef32d4c4a..1e970fdd6 100644
--- a/examples/stm32wba/src/bin/button_exti.rs
+++ b/examples/stm32wba/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index 070d27cb6..62c34b792 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8# Change stm32wl55jc-cm4 to your chip name, if necessary. 8# Change stm32wl55jc-cm4 to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
14 14
diff --git a/examples/stm32wl/src/bin/blinky.rs b/examples/stm32wl/src/bin/blinky.rs
index 5bd5745f0..347bd093f 100644
--- a/examples/stm32wl/src/bin/blinky.rs
+++ b/examples/stm32wl/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wl/src/bin/button.rs b/examples/stm32wl/src/bin/button.rs
index 6c1f5a5ef..3397e5ba6 100644
--- a/examples/stm32wl/src/bin/button.rs
+++ b/examples/stm32wl/src/bin/button.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use cortex_m_rt::entry; 4use cortex_m_rt::entry;
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32wl/src/bin/button_exti.rs b/examples/stm32wl/src/bin/button_exti.rs
index 1f02db5cf..e6ad4b80b 100644
--- a/examples/stm32wl/src/bin/button_exti.rs
+++ b/examples/stm32wl/src/bin/button_exti.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs
index 5e52d49ec..0b7417c01 100644
--- a/examples/stm32wl/src/bin/flash.rs
+++ b/examples/stm32wl/src/bin/flash.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 2fd234966..3610392be 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index 4ffb0bb58..4738d5770 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 5use defmt::*;
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs
index 44e8f83a2..8e545834c 100644
--- a/examples/stm32wl/src/bin/uart_async.rs
+++ b/examples/stm32wl/src/bin/uart_async.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use defmt::*; 4use defmt::*;
6use embassy_executor::Spawner; 5use embassy_executor::Spawner;
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index c96a428b9..305ebd526 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -9,7 +9,7 @@ crate-type = ["cdylib"]
9 9
10[dependencies] 10[dependencies]
11embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["log"] } 11embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["log"] }
12embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } 12embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "integrated-timers"] }
13embassy-time = { version = "0.2", path = "../../embassy-time", features = ["log", "wasm", ] } 13embassy-time = { version = "0.2", path = "../../embassy-time", features = ["log", "wasm", ] }
14 14
15wasm-logger = "0.2.0" 15wasm-logger = "0.2.0"
diff --git a/examples/wasm/src/lib.rs b/examples/wasm/src/lib.rs
index 1141096fb..71cf980dd 100644
--- a/examples/wasm/src/lib.rs
+++ b/examples/wasm/src/lib.rs
@@ -1,5 +1,3 @@
1#![feature(type_alias_impl_trait)]
2
3use embassy_executor::Spawner; 1use embassy_executor::Spawner;
4use embassy_time::Timer; 2use embassy_time::Timer;
5 3
diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml
new file mode 100644
index 000000000..b8a7db353
--- /dev/null
+++ b/rust-toolchain-nightly.toml
@@ -0,0 +1,12 @@
1[toolchain]
2channel = "nightly-2023-12-20"
3components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
4targets = [
5 "thumbv7em-none-eabi",
6 "thumbv7m-none-eabi",
7 "thumbv6m-none-eabi",
8 "thumbv7em-none-eabihf",
9 "thumbv8m.main-none-eabihf",
10 "riscv32imac-unknown-none-elf",
11 "wasm32-unknown-unknown",
12]
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 11f53ee4a..e1af0b647 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,8 +1,6 @@
1# Before upgrading check that everything is available on all tier1 targets here:
2# https://rust-lang.github.io/rustup-components-history
3[toolchain] 1[toolchain]
4channel = "nightly-2023-11-01" 2channel = "beta-2023-12-17"
5components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] 3components = [ "rust-src", "rustfmt", "llvm-tools" ]
6targets = [ 4targets = [
7 "thumbv7em-none-eabi", 5 "thumbv7em-none-eabi",
8 "thumbv7m-none-eabi", 6 "thumbv7m-none-eabi",
@@ -11,4 +9,4 @@ targets = [
11 "thumbv8m.main-none-eabihf", 9 "thumbv8m.main-none-eabihf",
12 "riscv32imac-unknown-none-elf", 10 "riscv32imac-unknown-none-elf",
13 "wasm32-unknown-unknown", 11 "wasm32-unknown-unknown",
14] \ No newline at end of file 12]
diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml
index b6067abcc..ccdca0844 100644
--- a/tests/nrf/Cargo.toml
+++ b/tests/nrf/Cargo.toml
@@ -18,7 +18,7 @@ embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-host
18embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } 18embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] }
19embedded-hal-async = { version = "1.0.0-rc.3" } 19embedded-hal-async = { version = "1.0.0-rc.3" }
20embedded-hal-bus = { version = "0.1.0-rc.3", features = ["async"] } 20embedded-hal-bus = { version = "0.1.0-rc.3", features = ["async"] }
21static_cell = { version = "2", features = [ "nightly" ] } 21static_cell = "2"
22perf-client = { path = "../perf-client" } 22perf-client = { path = "../perf-client" }
23 23
24defmt = "0.3" 24defmt = "0.3"
diff --git a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs
index 60d30a2ff..7dc1941d7 100644
--- a/tests/nrf/src/bin/ethernet_enc28j60_perf.rs
+++ b/tests/nrf/src/bin/ethernet_enc28j60_perf.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4teleprobe_meta::target!(b"ak-gwe-r7"); 3teleprobe_meta::target!(b"ak-gwe-r7");
5teleprobe_meta::timeout!(120); 4teleprobe_meta::timeout!(120);
6 5
@@ -14,7 +13,7 @@ use embassy_nrf::spim::{self, Spim};
14use embassy_nrf::{bind_interrupts, peripherals}; 13use embassy_nrf::{bind_interrupts, peripherals};
15use embassy_time::Delay; 14use embassy_time::Delay;
16use embedded_hal_bus::spi::ExclusiveDevice; 15use embedded_hal_bus::spi::ExclusiveDevice;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -68,11 +67,13 @@ async fn main(spawner: Spawner) {
68 let seed = u64::from_le_bytes(seed); 67 let seed = u64::from_le_bytes(seed);
69 68
70 // Init network stack 69 // Init network stack
71 let stack = &*make_static!(Stack::new( 70 static STACK: StaticCell<Stack<MyDriver>> = StaticCell::new();
71 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
72 let stack = &*STACK.init(Stack::new(
72 device, 73 device,
73 config, 74 config,
74 make_static!(StackResources::<2>::new()), 75 RESOURCES.init(StackResources::<2>::new()),
75 seed 76 seed,
76 )); 77 ));
77 78
78 unwrap!(spawner.spawn(net_task(stack))); 79 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
index 9eee39ccf..c96064f84 100644
--- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
+++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4teleprobe_meta::target!(b"nrf52840-dk"); 3teleprobe_meta::target!(b"nrf52840-dk");
5teleprobe_meta::timeout!(120); 4teleprobe_meta::timeout!(120);
6 5
@@ -13,7 +12,7 @@ use embassy_nrf::spim::{self, Spim};
13use embassy_nrf::{bind_interrupts, peripherals}; 12use embassy_nrf::{bind_interrupts, peripherals};
14use embassy_time::Delay; 13use embassy_time::Delay;
15use embedded_hal_bus::spi::ExclusiveDevice; 14use embedded_hal_bus::spi::ExclusiveDevice;
16use static_cell::make_static; 15use static_cell::StaticCell;
17use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; 16use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _};
18 17
19bind_interrupts!(struct Irqs { 18bind_interrupts!(struct Irqs {
@@ -64,8 +63,9 @@ 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 static STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
67 let (device, mut control, runner) = embassy_net_esp_hosted::new( 67 let (device, mut control, runner) = embassy_net_esp_hosted::new(
68 make_static!(embassy_net_esp_hosted::State::new()), 68 STATE.init(embassy_net_esp_hosted::State::new()),
69 spi, 69 spi,
70 handshake, 70 handshake,
71 ready, 71 ready,
@@ -85,11 +85,13 @@ async fn main(spawner: Spawner) {
85 let seed = u64::from_le_bytes(seed); 85 let seed = u64::from_le_bytes(seed);
86 86
87 // Init network stack 87 // Init network stack
88 let stack = &*make_static!(Stack::new( 88 static STACK: StaticCell<Stack<MyDriver>> = StaticCell::new();
89 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
90 let stack = &*STACK.init(Stack::new(
89 device, 91 device,
90 Config::dhcpv4(Default::default()), 92 Config::dhcpv4(Default::default()),
91 make_static!(StackResources::<2>::new()), 93 RESOURCES.init(StackResources::<2>::new()),
92 seed 94 seed,
93 )); 95 ));
94 96
95 unwrap!(spawner.spawn(net_task(stack))); 97 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 028ce43ee..c38aa8004 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -31,7 +31,7 @@ panic-probe = { version = "0.3.0", features = ["print-defmt"] }
31futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 31futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
32embedded-io-async = { version = "0.6.1" } 32embedded-io-async = { version = "0.6.1" }
33embedded-storage = { version = "0.3" } 33embedded-storage = { version = "0.3" }
34static_cell = { version = "2", features = ["nightly"]} 34static_cell = "2"
35portable-atomic = { version = "1.5", features = ["critical-section"] } 35portable-atomic = { version = "1.5", features = ["critical-section"] }
36pio = "0.2" 36pio = "0.2"
37pio-proc = "0.2" 37pio-proc = "0.2"
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs
index de29c06dd..a1b2946e6 100644
--- a/tests/rp/src/bin/cyw43-perf.rs
+++ b/tests/rp/src/bin/cyw43-perf.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4teleprobe_meta::target!(b"rpi-pico"); 3teleprobe_meta::target!(b"rpi-pico");
5 4
6use cyw43_pio::PioSpi; 5use cyw43_pio::PioSpi;
@@ -11,7 +10,7 @@ use embassy_rp::gpio::{Level, Output};
11use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 10use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
12use embassy_rp::pio::{InterruptHandler, Pio}; 11use embassy_rp::pio::{InterruptHandler, Pio};
13use embassy_rp::{bind_interrupts, rom_data}; 12use embassy_rp::{bind_interrupts, rom_data};
14use static_cell::make_static; 13use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
16 15
17bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
@@ -58,7 +57,8 @@ async fn main(spawner: Spawner) {
58 let mut pio = Pio::new(p.PIO0, Irqs); 57 let mut pio = Pio::new(p.PIO0, Irqs);
59 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 58 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
60 59
61 let state = make_static!(cyw43::State::new()); 60 static STATE: StaticCell<cyw43::State> = StaticCell::new();
61 let state = STATE.init(cyw43::State::new());
62 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 62 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
63 unwrap!(spawner.spawn(wifi_task(runner))); 63 unwrap!(spawner.spawn(wifi_task(runner)));
64 64
@@ -71,11 +71,13 @@ async fn main(spawner: Spawner) {
71 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. 71 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
72 72
73 // Init network stack 73 // Init network stack
74 let stack = &*make_static!(Stack::new( 74 static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new();
75 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
76 let stack = &*STACK.init(Stack::new(
75 net_device, 77 net_device,
76 Config::dhcpv4(Default::default()), 78 Config::dhcpv4(Default::default()),
77 make_static!(StackResources::<2>::new()), 79 RESOURCES.init(StackResources::<2>::new()),
78 seed 80 seed,
79 )); 81 ));
80 82
81 unwrap!(spawner.spawn(net_task(stack))); 83 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/tests/rp/src/bin/ethernet_w5100s_perf.rs b/tests/rp/src/bin/ethernet_w5100s_perf.rs
index a4d253b3c..8c9089d0e 100644
--- a/tests/rp/src/bin/ethernet_w5100s_perf.rs
+++ b/tests/rp/src/bin/ethernet_w5100s_perf.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4teleprobe_meta::target!(b"w5100s-evb-pico"); 3teleprobe_meta::target!(b"w5100s-evb-pico");
5teleprobe_meta::timeout!(120); 4teleprobe_meta::timeout!(120);
6 5
@@ -16,7 +15,7 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
16use embassy_time::Delay; 15use embassy_time::Delay;
17use embedded_hal_bus::spi::ExclusiveDevice; 16use embedded_hal_bus::spi::ExclusiveDevice;
18use rand::RngCore; 17use rand::RngCore;
19use static_cell::make_static; 18use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
21 20
22#[embassy_executor::task] 21#[embassy_executor::task]
@@ -51,7 +50,8 @@ async fn main(spawner: Spawner) {
51 let w5500_reset = Output::new(p.PIN_20, Level::High); 50 let w5500_reset = Output::new(p.PIN_20, Level::High);
52 51
53 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 52 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
54 let state = make_static!(State::<8, 8>::new()); 53 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
54 let state = STATE.init(State::<8, 8>::new());
55 let (device, runner) = embassy_net_wiznet::new( 55 let (device, runner) = embassy_net_wiznet::new(
56 mac_addr, 56 mac_addr,
57 state, 57 state,
@@ -66,11 +66,13 @@ async fn main(spawner: Spawner) {
66 let seed = rng.next_u64(); 66 let seed = rng.next_u64();
67 67
68 // Init network stack 68 // Init network stack
69 let stack = &*make_static!(Stack::new( 69 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
70 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
71 let stack = &*STACK.init(Stack::new(
70 device, 72 device,
71 embassy_net::Config::dhcpv4(Default::default()), 73 embassy_net::Config::dhcpv4(Default::default()),
72 make_static!(StackResources::<2>::new()), 74 RESOURCES.init(StackResources::<2>::new()),
73 seed 75 seed,
74 )); 76 ));
75 77
76 // Launch network task 78 // Launch network task
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bdec41571..c60b28a7a 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -69,7 +69,7 @@ micromath = "2.0.0"
69panic-probe = { version = "0.3.0", features = ["print-defmt"] } 69panic-probe = { version = "0.3.0", features = ["print-defmt"] }
70rand_core = { version = "0.6", default-features = false } 70rand_core = { version = "0.6", default-features = false }
71rand_chacha = { version = "0.3", default-features = false } 71rand_chacha = { version = "0.3", default-features = false }
72static_cell = { version = "2", features = ["nightly"] } 72static_cell = "2"
73portable-atomic = { version = "1.5", features = [] } 73portable-atomic = { version = "1.5", features = [] }
74 74
75chrono = { version = "^0.4", default-features = false, optional = true} 75chrono = { version = "^0.4", default-features = false, optional = true}
diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs
index 754354944..7c02f0354 100644
--- a/tests/stm32/src/bin/eth.rs
+++ b/tests/stm32/src/bin/eth.rs
@@ -1,7 +1,6 @@
1// required-features: eth 1// required-features: eth
2#![no_std] 2#![no_std]
3#![no_main] 3#![no_main]
4#![feature(type_alias_impl_trait)]
5 4
6#[path = "../common.rs"] 5#[path = "../common.rs"]
7mod common; 6mod common;
@@ -14,7 +13,7 @@ use embassy_stm32::peripherals::ETH;
14use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
15use embassy_stm32::{bind_interrupts, eth, peripherals, rng}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng};
16use rand_core::RngCore; 15use rand_core::RngCore;
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20teleprobe_meta::timeout!(120); 19teleprobe_meta::timeout!(120);
@@ -71,8 +70,9 @@ async fn main(spawner: Spawner) {
71 #[cfg(not(feature = "stm32f207zg"))] 70 #[cfg(not(feature = "stm32f207zg"))]
72 const PACKET_QUEUE_SIZE: usize = 4; 71 const PACKET_QUEUE_SIZE: usize = 4;
73 72
73 static PACKETS: StaticCell<PacketQueue<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>> = StaticCell::new();
74 let device = Ethernet::new( 74 let device = Ethernet::new(
75 make_static!(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()), 75 PACKETS.init(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()),
76 p.ETH, 76 p.ETH,
77 Irqs, 77 Irqs,
78 p.PA1, 78 p.PA1,
@@ -99,11 +99,13 @@ async fn main(spawner: Spawner) {
99 //}); 99 //});
100 100
101 // Init network stack 101 // Init network stack
102 let stack = &*make_static!(Stack::new( 102 static STACK: StaticCell<Stack<Device>> = StaticCell::new();
103 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
104 let stack = &*STACK.init(Stack::new(
103 device, 105 device,
104 config, 106 config,
105 make_static!(StackResources::<2>::new()), 107 RESOURCES.init(StackResources::<2>::new()),
106 seed 108 seed,
107 )); 109 ));
108 110
109 // Launch network task 111 // Launch network task
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs
index b9810673a..000296d46 100644
--- a/tests/stm32/src/bin/stop.rs
+++ b/tests/stm32/src/bin/stop.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6#[path = "../common.rs"] 5#[path = "../common.rs"]
7mod common; 6mod common;
8 7
@@ -15,7 +14,7 @@ use embassy_stm32::rcc::LsConfig;
15use embassy_stm32::rtc::{Rtc, RtcConfig}; 14use embassy_stm32::rtc::{Rtc, RtcConfig};
16use embassy_stm32::Config; 15use embassy_stm32::Config;
17use embassy_time::Timer; 16use embassy_time::Timer;
18use static_cell::make_static; 17use static_cell::StaticCell;
19 18
20#[entry] 19#[entry]
21fn main() -> ! { 20fn main() -> ! {
@@ -64,7 +63,8 @@ async fn async_main(spawner: Spawner) {
64 63
65 rtc.set_datetime(now.into()).expect("datetime not set"); 64 rtc.set_datetime(now.into()).expect("datetime not set");
66 65
67 let rtc = make_static!(rtc); 66 static RTC: StaticCell<Rtc> = StaticCell::new();
67 let rtc = RTC.init(rtc);
68 68
69 stop_with_rtc(rtc); 69 stop_with_rtc(rtc);
70 70