aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2023-10-20 14:17:55 +0200
committerDion Dokter <[email protected]>2023-10-20 14:17:55 +0200
commit5b3f75dc726afaf21b6c957b88f8eeb0c9ae322c (patch)
treec2b2920f63d83e32dd7f3f2ef18c64d73b997557
parent6f2995cd4c70a2b6c977f553a2d5efcd8216bba7 (diff)
parent88ada521461031b7241b09e40aa56f4e64827967 (diff)
Merge branch 'master' into center-align
-rw-r--r--README.md4
-rwxr-xr-xci.sh116
-rwxr-xr-xci_stable.sh61
-rw-r--r--cyw43/Cargo.toml5
-rw-r--r--cyw43/src/bus.rs6
-rw-r--r--cyw43/src/control.rs28
-rw-r--r--cyw43/src/runner.rs4
-rw-r--r--docs/modules/ROOT/examples/basic/Cargo.toml2
-rw-r--r--docs/modules/ROOT/nav.adoc4
-rw-r--r--docs/modules/ROOT/pages/basic_application.adoc2
-rw-r--r--docs/modules/ROOT/pages/getting_started.adoc7
-rw-r--r--docs/modules/ROOT/pages/hal.adoc4
-rw-r--r--docs/modules/ROOT/pages/index.adoc17
-rw-r--r--docs/modules/ROOT/pages/layer_by_layer.adoc5
-rw-r--r--docs/modules/ROOT/pages/nrf.adoc6
-rw-r--r--docs/modules/ROOT/pages/runtime.adoc4
-rw-r--r--embassy-embedded-hal/Cargo.toml2
-rw-r--r--embassy-embedded-hal/src/flash/partition/mod.rs2
-rw-r--r--embassy-embedded-hal/src/lib.rs16
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/i2c.rs8
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/spi.rs10
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/i2c.rs6
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/spi.rs2
-rw-r--r--embassy-embedded-hal/src/shared_bus/mod.rs6
-rw-r--r--embassy-executor/Cargo.toml2
-rw-r--r--embassy-executor/README.md2
-rw-r--r--embassy-hal-internal/README.md2
-rw-r--r--embassy-hal-internal/src/interrupt.rs32
-rw-r--r--embassy-hal-internal/src/lib.rs1
-rw-r--r--embassy-hal-internal/src/macros.rs10
-rw-r--r--embassy-hal-internal/src/ring_buffer.rs136
-rw-r--r--embassy-lora/Cargo.toml2
-rw-r--r--embassy-lora/src/lib.rs4
-rw-r--r--embassy-net-adin1110/Cargo.toml4
-rw-r--r--embassy-net-adin1110/src/lib.rs6
-rw-r--r--embassy-net-driver-channel/CHANGELOG.md16
-rw-r--r--embassy-net-driver-channel/Cargo.toml4
-rw-r--r--embassy-net-driver-channel/README.md18
-rw-r--r--embassy-net-driver-channel/src/lib.rs20
-rw-r--r--embassy-net-driver/CHANGELOG.md17
-rw-r--r--embassy-net-driver/Cargo.toml2
-rw-r--r--embassy-net-driver/src/lib.rs54
-rw-r--r--embassy-net-enc28j60/Cargo.toml4
-rw-r--r--embassy-net-enc28j60/src/lib.rs3
-rw-r--r--embassy-net-esp-hosted/Cargo.toml4
-rw-r--r--embassy-net-esp-hosted/src/control.rs4
-rw-r--r--embassy-net-esp-hosted/src/lib.rs4
-rw-r--r--embassy-net-ppp/Cargo.toml4
-rw-r--r--embassy-net-ppp/src/lib.rs17
-rw-r--r--embassy-net-tuntap/Cargo.toml2
-rw-r--r--embassy-net-wiznet/Cargo.toml4
-rw-r--r--embassy-net-wiznet/src/lib.rs58
-rw-r--r--embassy-net/CHANGELOG.md29
-rw-r--r--embassy-net/Cargo.toml12
-rw-r--r--embassy-net/src/device.rs19
-rw-r--r--embassy-net/src/lib.rs89
-rw-r--r--embassy-net/src/tcp.rs15
-rw-r--r--embassy-nrf/Cargo.toml6
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs318
-rw-r--r--embassy-nrf/src/chips/nrf5340_net.rs5
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs244
-rw-r--r--embassy-nrf/src/lib.rs2
-rw-r--r--embassy-nrf/src/spim.rs7
-rw-r--r--embassy-nrf/src/spis.rs7
-rw-r--r--embassy-nrf/src/twim.rs7
-rw-r--r--embassy-rp/Cargo.toml6
-rw-r--r--embassy-rp/src/adc.rs8
-rw-r--r--embassy-rp/src/bootsel.rs83
-rw-r--r--embassy-rp/src/flash.rs78
-rw-r--r--embassy-rp/src/gpio.rs48
-rw-r--r--embassy-rp/src/i2c.rs55
-rw-r--r--embassy-rp/src/i2c_slave.rs25
-rw-r--r--embassy-rp/src/lib.rs4
-rw-r--r--embassy-rp/src/pwm.rs29
-rw-r--r--embassy-rp/src/spi.rs5
-rw-r--r--embassy-rp/src/uart/buffered.rs6
-rw-r--r--embassy-rp/src/uart/mod.rs4
-rw-r--r--embassy-stm32-wpan/Cargo.toml4
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs11
-rw-r--r--embassy-stm32/Cargo.toml14
-rw-r--r--embassy-stm32/build.rs341
-rw-r--r--embassy-stm32/src/adc/f1.rs3
-rw-r--r--embassy-stm32/src/adc/f3.rs3
-rw-r--r--embassy-stm32/src/adc/mod.rs4
-rw-r--r--embassy-stm32/src/adc/v1.rs3
-rw-r--r--embassy-stm32/src/adc/v2.rs3
-rw-r--r--embassy-stm32/src/adc/v3.rs15
-rw-r--r--embassy-stm32/src/adc/v4.rs3
-rw-r--r--embassy-stm32/src/can/bxcan.rs3
-rw-r--r--embassy-stm32/src/crc/v1.rs4
-rw-r--r--embassy-stm32/src/crc/v2v3.rs7
-rw-r--r--embassy-stm32/src/dac/mod.rs60
-rw-r--r--embassy-stm32/src/dcmi.rs3
-rw-r--r--embassy-stm32/src/dma/bdma.rs22
-rw-r--r--embassy-stm32/src/dma/dma.rs4
-rw-r--r--embassy-stm32/src/dma/dmamux.rs2
-rw-r--r--embassy-stm32/src/dma/gpdma.rs4
-rw-r--r--embassy-stm32/src/dma/mod.rs9
-rw-r--r--embassy-stm32/src/eth/generic_smi.rs33
-rw-r--r--embassy-stm32/src/eth/mod.rs4
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs13
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs13
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/flash/f0.rs6
-rw-r--r--embassy-stm32/src/flash/f3.rs6
-rw-r--r--embassy-stm32/src/flash/f4.rs6
-rw-r--r--embassy-stm32/src/flash/f7.rs6
-rw-r--r--embassy-stm32/src/flash/g0.rs6
-rw-r--r--embassy-stm32/src/flash/h7.rs12
-rw-r--r--embassy-stm32/src/flash/l.rs18
-rw-r--r--embassy-stm32/src/fmc.rs3
-rw-r--r--embassy-stm32/src/gpio.rs17
-rw-r--r--embassy-stm32/src/hrtim/mod.rs3
-rw-r--r--embassy-stm32/src/i2c/mod.rs7
-rw-r--r--embassy-stm32/src/i2c/timeout.rs209
-rw-r--r--embassy-stm32/src/i2c/v1.rs8
-rw-r--r--embassy-stm32/src/i2c/v2.rs211
-rw-r--r--embassy-stm32/src/i2s.rs2
-rw-r--r--embassy-stm32/src/ipcc.rs3
-rw-r--r--embassy-stm32/src/lib.rs149
-rw-r--r--embassy-stm32/src/low_power.rs26
-rw-r--r--embassy-stm32/src/opamp.rs159
-rw-r--r--embassy-stm32/src/qspi/enums.rs16
-rw-r--r--embassy-stm32/src/qspi/mod.rs121
-rw-r--r--embassy-stm32/src/rcc/bd.rs289
-rw-r--r--embassy-stm32/src/rcc/bus.rs56
-rw-r--r--embassy-stm32/src/rcc/c0.rs82
-rw-r--r--embassy-stm32/src/rcc/f0.rs22
-rw-r--r--embassy-stm32/src/rcc/f1.rs30
-rw-r--r--embassy-stm32/src/rcc/f2.rs205
-rw-r--r--embassy-stm32/src/rcc/f3.rs198
-rw-r--r--embassy-stm32/src/rcc/f4.rs579
-rw-r--r--embassy-stm32/src/rcc/f4f7.rs385
-rw-r--r--embassy-stm32/src/rcc/f7.rs323
-rw-r--r--embassy-stm32/src/rcc/g0.rs211
-rw-r--r--embassy-stm32/src/rcc/g4.rs340
-rw-r--r--embassy-stm32/src/rcc/h.rs159
-rw-r--r--embassy-stm32/src/rcc/l0.rs349
-rw-r--r--embassy-stm32/src/rcc/l0l1.rs219
-rw-r--r--embassy-stm32/src/rcc/l1.rs279
-rw-r--r--embassy-stm32/src/rcc/l4.rs619
-rw-r--r--embassy-stm32/src/rcc/l4l5.rs441
-rw-r--r--embassy-stm32/src/rcc/l5.rs443
-rw-r--r--embassy-stm32/src/rcc/mco.rs46
-rw-r--r--embassy-stm32/src/rcc/mod.rs198
-rw-r--r--embassy-stm32/src/rcc/u5.rs549
-rw-r--r--embassy-stm32/src/rcc/wb.rs256
-rw-r--r--embassy-stm32/src/rcc/wba.rs37
-rw-r--r--embassy-stm32/src/rcc/wl.rs264
-rw-r--r--embassy-stm32/src/rng.rs10
-rw-r--r--embassy-stm32/src/rtc/mod.rs77
-rw-r--r--embassy-stm32/src/rtc/v2.rs33
-rw-r--r--embassy-stm32/src/sai/mod.rs306
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs9
-rw-r--r--embassy-stm32/src/spi/mod.rs13
-rw-r--r--embassy-stm32/src/time.rs7
-rw-r--r--embassy-stm32/src/time_driver.rs85
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs45
-rw-r--r--embassy-stm32/src/timer/mod.rs42
-rw-r--r--embassy-stm32/src/timer/qei.rs3
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs43
-rw-r--r--embassy-stm32/src/usart/buffered.rs30
-rw-r--r--embassy-stm32/src/usart/mod.rs48
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs5
-rw-r--r--embassy-stm32/src/usb/usb.rs3
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs3
-rw-r--r--embassy-sync/Cargo.toml2
-rw-r--r--embassy-sync/src/lib.rs2
-rw-r--r--embassy-time/CHANGELOG.md9
-rw-r--r--embassy-time/Cargo.toml9
-rw-r--r--embassy-time/build.rs3
-rw-r--r--embassy-time/src/delay.rs4
-rw-r--r--embassy-time/src/timer.rs36
-rw-r--r--embassy-usb/Cargo.toml2
-rw-r--r--embassy-usb/build.rs8
-rw-r--r--embassy-usb/src/builder.rs44
-rw-r--r--embassy-usb/src/class/cdc_acm.rs111
-rw-r--r--embassy-usb/src/class/cdc_ncm/mod.rs63
-rw-r--r--embassy-usb/src/class/hid.rs36
-rw-r--r--embassy-usb/src/class/midi.rs227
-rw-r--r--embassy-usb/src/class/mod.rs1
-rw-r--r--embassy-usb/src/control.rs2
-rw-r--r--embassy-usb/src/descriptor.rs34
-rw-r--r--embassy-usb/src/descriptor_reader.rs6
-rw-r--r--embassy-usb/src/lib.rs54
-rw-r--r--embassy-usb/src/msos.rs2
-rw-r--r--embassy-usb/src/types.rs4
-rw-r--r--examples/boot/application/nrf/Cargo.toml2
-rw-r--r--examples/boot/application/nrf/src/bin/b.rs6
-rw-r--r--examples/boot/application/rp/Cargo.toml2
-rw-r--r--examples/boot/application/rp/src/bin/a.rs4
-rw-r--r--examples/boot/application/rp/src/bin/b.rs6
-rw-r--r--examples/boot/application/stm32f3/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f3/src/bin/b.rs6
-rw-r--r--examples/boot/application/stm32f7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f7/src/bin/b.rs8
-rw-r--r--examples/boot/application/stm32h7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32h7/src/bin/b.rs8
-rw-r--r--examples/boot/application/stm32l0/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l0/src/bin/a.rs4
-rw-r--r--examples/boot/application/stm32l0/src/bin/b.rs6
-rw-r--r--examples/boot/application/stm32l1/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l1/src/bin/a.rs4
-rw-r--r--examples/boot/application/stm32l1/src/bin/b.rs6
-rw-r--r--examples/boot/application/stm32l4/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l4/src/bin/b.rs6
-rw-r--r--examples/boot/application/stm32wl/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wl/src/bin/b.rs6
-rw-r--r--examples/nrf-rtos-trace/Cargo.toml2
-rw-r--r--examples/nrf-rtos-trace/src/bin/rtos_trace.rs4
-rw-r--r--examples/nrf52840-rtic/Cargo.toml2
-rw-r--r--examples/nrf52840-rtic/memory.x7
-rw-r--r--examples/nrf52840-rtic/src/bin/blinky.rs6
-rw-r--r--examples/nrf52840/Cargo.toml8
-rw-r--r--examples/nrf52840/memory.x7
-rw-r--r--examples/nrf52840/src/bin/blinky.rs6
-rw-r--r--examples/nrf52840/src/bin/channel.rs6
-rw-r--r--examples/nrf52840/src/bin/channel_sender_receiver.rs6
-rw-r--r--examples/nrf52840/src/bin/executor_fairness_test.rs4
-rw-r--r--examples/nrf52840/src/bin/lora_cad.rs6
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_receive.rs6
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs6
-rw-r--r--examples/nrf52840/src/bin/manually_create_executor.rs6
-rw-r--r--examples/nrf52840/src/bin/multiprio.rs8
-rw-r--r--examples/nrf52840/src/bin/mutex.rs8
-rw-r--r--examples/nrf52840/src/bin/nvmc.rs4
-rw-r--r--examples/nrf52840/src/bin/pdm.rs6
-rw-r--r--examples/nrf52840/src/bin/pubsub.rs8
-rw-r--r--examples/nrf52840/src/bin/pwm.rs4
-rw-r--r--examples/nrf52840/src/bin/pwm_double_sequence.rs4
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence.rs4
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs4
-rw-r--r--examples/nrf52840/src/bin/pwm_servo.rs14
-rw-r--r--examples/nrf52840/src/bin/qspi_lowpower.rs4
-rw-r--r--examples/nrf52840/src/bin/raw_spawn.rs6
-rw-r--r--examples/nrf52840/src/bin/saadc.rs4
-rw-r--r--examples/nrf52840/src/bin/saadc_continuous.rs3
-rw-r--r--examples/nrf52840/src/bin/self_spawn.rs4
-rw-r--r--examples/nrf52840/src/bin/self_spawn_current_executor.rs4
-rw-r--r--examples/nrf52840/src/bin/temp.rs4
-rw-r--r--examples/nrf52840/src/bin/timer.rs6
-rw-r--r--examples/nrf52840/src/bin/twim_lowpower.rs4
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs4
-rw-r--r--examples/nrf5340/Cargo.toml6
-rw-r--r--examples/nrf5340/src/bin/blinky.rs6
-rw-r--r--examples/rp/Cargo.toml6
-rw-r--r--examples/rp/src/bin/adc.rs4
-rw-r--r--examples/rp/src/bin/blinky.rs6
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs2
-rw-r--r--examples/rp/src/bin/flash.rs4
-rw-r--r--examples/rp/src/bin/gpio_async.rs4
-rw-r--r--examples/rp/src/bin/gpout.rs6
-rw-r--r--examples/rp/src/bin/i2c_async.rs4
-rw-r--r--examples/rp/src/bin/i2c_blocking.rs4
-rw-r--r--examples/rp/src/bin/i2c_slave.rs6
-rw-r--r--examples/rp/src/bin/lora_p2p_receive.rs4
-rw-r--r--examples/rp/src/bin/lora_p2p_send_multicore.rs4
-rw-r--r--examples/rp/src/bin/multicore.rs6
-rw-r--r--examples/rp/src/bin/multiprio.rs8
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs4
-rw-r--r--examples/rp/src/bin/pio_ws2812.rs4
-rw-r--r--examples/rp/src/bin/pwm.rs4
-rw-r--r--examples/rp/src/bin/rosc.rs32
-rw-r--r--examples/rp/src/bin/rtc.rs6
-rw-r--r--examples/rp/src/bin/spi_async.rs4
-rw-r--r--examples/rp/src/bin/uart_buffered_split.rs4
-rw-r--r--examples/rp/src/bin/uart_unidir.rs4
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs3
-rw-r--r--examples/rp/src/bin/usb_logger.rs4
-rw-r--r--examples/rp/src/bin/usb_midi.rs110
-rw-r--r--examples/rp/src/bin/watchdog.rs10
-rw-r--r--examples/rp/src/bin/wifi_ap_tcp_server.rs2
-rw-r--r--examples/rp/src/bin/wifi_blinky.rs2
-rw-r--r--examples/rp/src/bin/wifi_scan.rs2
-rw-r--r--examples/rp/src/bin/wifi_tcp_server.rs11
-rw-r--r--examples/std/Cargo.toml8
-rw-r--r--examples/std/src/bin/net_ppp.rs2
-rw-r--r--examples/std/src/bin/tcp_accept.rs2
-rw-r--r--examples/std/src/bin/tick.rs4
-rw-r--r--examples/stm32c0/Cargo.toml2
-rw-r--r--examples/stm32c0/src/bin/blinky.rs6
-rw-r--r--examples/stm32f0/Cargo.toml2
-rw-r--r--examples/stm32f0/src/bin/adc.rs4
-rw-r--r--examples/stm32f0/src/bin/blinky.rs6
-rw-r--r--examples/stm32f0/src/bin/button_controlled_blink.rs4
-rw-r--r--examples/stm32f0/src/bin/hello.rs4
-rw-r--r--examples/stm32f0/src/bin/multiprio.rs8
-rw-r--r--examples/stm32f0/src/bin/wdg.rs4
-rw-r--r--examples/stm32f1/Cargo.toml2
-rw-r--r--examples/stm32f1/src/bin/adc.rs4
-rw-r--r--examples/stm32f1/src/bin/blinky.rs6
-rw-r--r--examples/stm32f1/src/bin/hello.rs4
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f2/Cargo.toml2
-rw-r--r--examples/stm32f2/src/bin/blinky.rs6
-rw-r--r--examples/stm32f2/src/bin/pll.rs10
-rw-r--r--examples/stm32f3/Cargo.toml2
-rw-r--r--examples/stm32f3/src/bin/blinky.rs6
-rw-r--r--examples/stm32f3/src/bin/button_events.rs4
-rw-r--r--examples/stm32f3/src/bin/hello.rs4
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs8
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f334/src/bin/adc.rs8
-rw-r--r--examples/stm32f334/src/bin/button.rs6
-rw-r--r--examples/stm32f334/src/bin/hello.rs4
-rw-r--r--examples/stm32f334/src/bin/opamp.rs59
-rw-r--r--examples/stm32f334/src/bin/pwm.rs6
-rw-r--r--examples/stm32f4/Cargo.toml8
-rw-r--r--examples/stm32f4/src/bin/adc.rs4
-rw-r--r--examples/stm32f4/src/bin/blinky.rs6
-rw-r--r--examples/stm32f4/src/bin/eth.rs31
-rw-r--r--examples/stm32f4/src/bin/flash_async.rs6
-rw-r--r--examples/stm32f4/src/bin/hello.rs8
-rw-r--r--examples/stm32f4/src/bin/i2c.rs9
-rw-r--r--examples/stm32f4/src/bin/mco.rs12
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs8
-rw-r--r--examples/stm32f4/src/bin/pwm.rs10
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs10
-rw-r--r--examples/stm32f4/src/bin/rtc.rs10
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs23
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs24
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs24
-rw-r--r--examples/stm32f4/src/bin/wdt.rs6
-rw-r--r--examples/stm32f7/Cargo.toml6
-rw-r--r--examples/stm32f7/src/bin/adc.rs4
-rw-r--r--examples/stm32f7/src/bin/blinky.rs6
-rw-r--r--examples/stm32f7/src/bin/can.rs2
-rw-r--r--examples/stm32f7/src/bin/eth.rs31
-rw-r--r--examples/stm32f7/src/bin/flash.rs4
-rw-r--r--examples/stm32f7/src/bin/hello.rs8
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs23
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs25
-rw-r--r--examples/stm32g0/Cargo.toml2
-rw-r--r--examples/stm32g0/src/bin/blinky.rs6
-rw-r--r--examples/stm32g0/src/bin/spi_neopixel.rs6
-rw-r--r--examples/stm32g4/Cargo.toml2
-rw-r--r--examples/stm32g4/src/bin/adc.rs12
-rw-r--r--examples/stm32g4/src/bin/blinky.rs6
-rw-r--r--examples/stm32g4/src/bin/pll.rs10
-rw-r--r--examples/stm32g4/src/bin/pwm.rs10
-rw-r--r--examples/stm32g4/src/bin/usb_serial.rs8
-rw-r--r--examples/stm32h5/Cargo.toml8
-rw-r--r--examples/stm32h5/src/bin/blinky.rs6
-rw-r--r--examples/stm32h5/src/bin/eth.rs21
-rw-r--r--examples/stm32h5/src/bin/i2c.rs9
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs10
-rw-r--r--examples/stm32h7/Cargo.toml11
-rw-r--r--examples/stm32h7/src/bin/adc.rs18
-rw-r--r--examples/stm32h7/src/bin/blinky.rs6
-rw-r--r--examples/stm32h7/src/bin/camera.rs26
-rw-r--r--examples/stm32h7/src/bin/dac.rs14
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs18
-rw-r--r--examples/stm32h7/src/bin/eth.rs15
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs19
-rw-r--r--examples/stm32h7/src/bin/flash.rs4
-rw-r--r--examples/stm32h7/src/bin/fmc.rs12
-rw-r--r--examples/stm32h7/src/bin/i2c.rs9
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs21
-rw-r--r--examples/stm32h7/src/bin/mco.rs10
-rw-r--r--examples/stm32h7/src/bin/pwm.rs16
-rw-r--r--examples/stm32h7/src/bin/rtc.rs37
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs8
-rw-r--r--examples/stm32h7/src/bin/signal.rs4
-rw-r--r--examples/stm32h7/src/bin/spi.rs8
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs8
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs6
-rw-r--r--examples/stm32h7/src/bin/wdg.rs4
-rw-r--r--examples/stm32l0/Cargo.toml6
-rw-r--r--examples/stm32l0/src/bin/blinky.rs6
-rw-r--r--examples/stm32l0/src/bin/lora_cad.rs6
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_receive.rs6
-rw-r--r--examples/stm32l0/src/bin/raw_spawn.rs6
-rw-r--r--examples/stm32l1/Cargo.toml2
-rw-r--r--examples/stm32l1/src/bin/blinky.rs6
-rw-r--r--examples/stm32l4/Cargo.toml8
-rw-r--r--examples/stm32l4/src/bin/adc.rs2
-rw-r--r--examples/stm32l4/src/bin/blinky.rs6
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs4
-rw-r--r--examples/stm32l4/src/bin/mco.rs10
-rw-r--r--examples/stm32l4/src/bin/rng.rs20
-rw-r--r--examples/stm32l4/src/bin/rtc.rs33
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs27
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs11
-rw-r--r--examples/stm32l5/Cargo.toml6
-rw-r--r--examples/stm32l5/src/bin/rng.rs20
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs13
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs17
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs13
-rw-r--r--examples/stm32u5/Cargo.toml2
-rw-r--r--examples/stm32u5/src/bin/blinky.rs6
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs7
-rw-r--r--examples/stm32wb/Cargo.toml4
-rw-r--r--examples/stm32wb/src/bin/blinky.rs6
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs4
-rw-r--r--examples/stm32wba/Cargo.toml4
-rw-r--r--examples/stm32wba/src/bin/blinky.rs6
-rw-r--r--examples/stm32wl/Cargo.toml2
-rw-r--r--examples/stm32wl/src/bin/blinky.rs6
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs3
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_receive.rs8
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_send.rs2
-rw-r--r--examples/stm32wl/src/bin/random.rs10
-rw-r--r--examples/stm32wl/src/bin/rtc.rs14
-rw-r--r--examples/stm32wl/src/bin/uart_async.rs2
-rw-r--r--examples/wasm/Cargo.toml2
-rw-r--r--examples/wasm/src/lib.rs4
-rw-r--r--rust-toolchain.toml4
-rw-r--r--tests/nrf/Cargo.toml6
-rw-r--r--tests/nrf/src/bin/buffered_uart_spam.rs4
-rw-r--r--tests/nrf/src/bin/timer.rs4
-rw-r--r--tests/perf-client/Cargo.toml4
-rw-r--r--tests/perf-client/src/lib.rs11
-rw-r--r--tests/riscv32/Cargo.toml2
-rw-r--r--tests/rp/Cargo.toml6
-rw-r--r--tests/rp/src/bin/adc.rs12
-rw-r--r--tests/rp/src/bin/bootsel.rs26
-rw-r--r--tests/rp/src/bin/flash.rs4
-rw-r--r--tests/rp/src/bin/float.rs4
-rw-r--r--tests/rp/src/bin/gpio_async.rs12
-rw-r--r--tests/rp/src/bin/pwm.rs44
-rw-r--r--tests/rp/src/bin/uart.rs10
-rw-r--r--tests/rp/src/bin/uart_buffered.rs10
-rw-r--r--tests/rp/src/bin/uart_dma.rs12
-rw-r--r--tests/stm32/Cargo.toml51
-rw-r--r--tests/stm32/build.rs4
-rw-r--r--tests/stm32/src/bin/dac.rs8
-rw-r--r--tests/stm32/src/bin/eth.rs122
-rw-r--r--tests/stm32/src/bin/rng.rs50
-rw-r--r--tests/stm32/src/bin/rtc.rs13
-rw-r--r--tests/stm32/src/bin/stop.rs16
-rw-r--r--tests/stm32/src/bin/timer.rs4
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs8
-rw-r--r--tests/stm32/src/common.rs215
433 files changed, 6902 insertions, 7005 deletions
diff --git a/README.md b/README.md
index c4c01dfbc..e5a970621 100644
--- a/README.md
+++ b/README.md
@@ -62,9 +62,9 @@ async fn blink(pin: AnyPin) {
62 loop { 62 loop {
63 // Timekeeping is globally available, no need to mess with hardware timers. 63 // Timekeeping is globally available, no need to mess with hardware timers.
64 led.set_high(); 64 led.set_high();
65 Timer::after(Duration::from_millis(150)).await; 65 Timer::after_millis(150).await;
66 led.set_low(); 66 led.set_low();
67 Timer::after(Duration::from_millis(150)).await; 67 Timer::after_millis(150).await;
68 } 68 }
69} 69}
70 70
diff --git a/ci.sh b/ci.sh
index af98d6ed2..ece763497 100755
--- a/ci.sh
+++ b/ci.sh
@@ -1,9 +1,12 @@
1#!/bin/bash 1#!/bin/bash
2 2
3set -euo pipefail 3set -eo pipefail
4 4
5export RUSTFLAGS=-Dwarnings 5export RUSTFLAGS=-Dwarnings
6export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info 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
7 10
8TARGET=$(rustc -vV | sed -n 's|host: ||p') 11TARGET=$(rustc -vV | sed -n 's|host: ||p')
9 12
@@ -36,7 +39,7 @@ cargo batch \
36 --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \ 39 --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \
37 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ 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,dhcpv4,medium-ethernet \ 41 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \
39 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ 42 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly,dhcpv4-hostname \
40 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ 43 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
41 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ 44 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \
42 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ 45 --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \
@@ -66,49 +69,68 @@ cargo batch \
66 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \ 69 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \
67 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,intrinsics \ 70 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,intrinsics \
68 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,qspi-as-gpio \ 71 --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,qspi-as-gpio \
69 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any,unstable-traits \ 72 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any,unstable-traits,time \
70 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any \ 73 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any,time \
71 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any \ 74 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,time \
72 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,unstable-traits \ 75 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,unstable-traits,time \
73 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti \ 76 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time \
74 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,unstable-traits \ 77 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,unstable-traits,time \
75 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt \ 78 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time \
76 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,unstable-traits \ 79 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,unstable-traits,time \
77 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any \ 80 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,time \
78 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any \ 81 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any,time \
79 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any,unstable-traits \ 82 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any,unstable-traits,time \
83 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time \
84 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,unstable-traits,time \
85 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time \
80 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti \ 86 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti \
81 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,unstable-traits \ 87 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,unstable-traits \
82 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt \ 88 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt \
83 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits \ 89 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f401ve,defmt,exti,time-driver-any,unstable-traits \
84 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits \ 90 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f405zg,defmt,exti,time-driver-any,unstable-traits \
85 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f413vh,defmt,exti,time-driver-any,unstable-traits \ 91 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f407zg,defmt,exti,time-driver-any,unstable-traits \
86 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits,embedded-sdmmc \ 92 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f401ve,defmt,exti,time-driver-any,unstable-traits,time \
87 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f730i8,defmt,exti,time-driver-any,unstable-traits \ 93 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f405zg,defmt,exti,time-driver-any,unstable-traits,time \
88 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits \ 94 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f407zg,defmt,exti,time-driver-any,unstable-traits,time \
89 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits \ 95 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits,time \
90 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \ 96 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits,time \
91 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits \ 97 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f412zg,defmt,exti,time-driver-any,unstable-traits,time \
92 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits \ 98 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f413vh,defmt,exti,time-driver-any,unstable-traits,time \
93 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits \ 99 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f415zg,defmt,exti,time-driver-any,unstable-traits,time \
94 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wb15cc,defmt,exti,time-driver-any,unstable-traits \ 100 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f417zg,defmt,exti,time-driver-any,unstable-traits,time \
95 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l072cz,defmt,exti,time-driver-any,unstable-traits \ 101 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f423zh,defmt,exti,time-driver-any,unstable-traits,time \
96 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l041f6,defmt,exti,time-driver-any,unstable-traits \ 102 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f427zi,defmt,exti,time-driver-any,unstable-traits,time \
97 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l073cz,defmt,exti,time-driver-any,unstable-traits,low-power \ 103 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits,embedded-sdmmc,time \
98 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \ 104 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f437zi,log,exti,time-driver-any,unstable-traits,time \
99 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits \ 105 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f439zi,defmt,exti,time-driver-any,unstable-traits,time \
100 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f378cc,defmt,exti,time-driver-any,unstable-traits \ 106 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f446ze,defmt,exti,time-driver-any,unstable-traits,time \
101 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits \ 107 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f469zi,defmt,exti,time-driver-any,unstable-traits,time \
102 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits \ 108 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f479zi,defmt,exti,time-driver-any,unstable-traits,embedded-sdmmc,time \
103 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \ 109 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f730i8,defmt,exti,time-driver-any,unstable-traits,time \
104 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \ 110 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits,time \
105 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5jb,defmt,exti,time-driver-any,unstable-traits \ 111 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits,time \
106 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32g474pe,defmt,exti,time-driver-any,unstable-traits \ 112 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \
107 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f107vc,defmt,exti,time-driver-any,unstable-traits \ 113 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits,time \
108 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f103re,defmt,exti,time-driver-any,unstable-traits \ 114 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \
109 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f100c4,defmt,exti,time-driver-any,unstable-traits \ 115 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits,time \
110 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h503rb,defmt,exti,time-driver-any,unstable-traits \ 116 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wb15cc,defmt,exti,time-driver-any,unstable-traits,time \
111 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h562ag,defmt,exti,time-driver-any,unstable-traits \ 117 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l072cz,defmt,exti,time-driver-any,unstable-traits,time \
118 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l041f6,defmt,exti,time-driver-any,unstable-traits,time \
119 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l073cz,defmt,exti,time-driver-any,unstable-traits,low-power,time \
120 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits,time \
121 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits,time \
122 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f378cc,defmt,exti,time-driver-any,unstable-traits,time \
123 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits,time \
124 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits,time \
125 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits,time \
126 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits,time \
127 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5jb,defmt,exti,time-driver-any,unstable-traits,time \
128 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32g474pe,defmt,exti,time-driver-any,unstable-traits,time \
129 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f107vc,defmt,exti,time-driver-any,unstable-traits,time \
130 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f103re,defmt,exti,time-driver-any,unstable-traits,time \
131 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f100c4,defmt,exti,time-driver-any,unstable-traits,time \
132 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h503rb,defmt,exti,time-driver-any,unstable-traits,time \
133 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h562ag,defmt,exti,time-driver-any,unstable-traits,time \
112 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ 134 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\
113 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ 135 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \
114 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ 136 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \
@@ -178,12 +200,20 @@ cargo batch \
178 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --out-dir out/tests/stm32l4a6zg \ 200 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --out-dir out/tests/stm32l4a6zg \
179 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --out-dir out/tests/stm32l4r5zi \ 201 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --out-dir out/tests/stm32l4r5zi \
180 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --out-dir out/tests/stm32l552ze \ 202 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --out-dir out/tests/stm32l552ze \
203 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f767zi --out-dir out/tests/stm32f767zi \
204 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f207zg --out-dir out/tests/stm32f207zg \
205 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --out-dir out/tests/stm32f303ze \
206 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --out-dir out/tests/stm32l496zg \
207 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --out-dir out/tests/stm32wl55jc \
181 --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/tests/rpi-pico \ 208 --- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/tests/rpi-pico \
182 --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/tests/nrf52840-dk \ 209 --- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/tests/nrf52840-dk \
183 --- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \ 210 --- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \
184 $BUILD_EXTRA 211 $BUILD_EXTRA
185 212
186rm out/tests/nrf52840-dk/wifi_esp_hosted_perf 213
214rm out/tests/stm32wb55rg/wpan_mac
215rm out/tests/stm32wb55rg/wpan_ble
216rm out/tests/stm32f207zg/eth
187 217
188if [[ -z "${TELEPROBE_TOKEN-}" ]]; then 218if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
189 echo No teleprobe token found, skipping running HIL tests 219 echo No teleprobe token found, skipping running HIL tests
diff --git a/ci_stable.sh b/ci_stable.sh
index 4ee5f4106..1fe4e3a1e 100755
--- a/ci_stable.sh
+++ b/ci_stable.sh
@@ -40,33 +40,38 @@ cargo batch \
40 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits \ 40 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits \
41 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,unstable-traits \ 41 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,unstable-traits \
42 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,unstable-traits \ 42 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,unstable-traits \
43 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,unstable-traits \ 43 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any,unstable-traits,time \
44 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,unstable-traits \ 44 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any,unstable-traits,time \
45 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any \ 45 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits,time \
46 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,unstable-traits \ 46 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,unstable-traits,time \
47 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any \ 47 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,unstable-traits,time \
48 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,unstable-traits \ 48 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,unstable-traits,time \
49 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any \ 49 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,unstable-traits,time \
50 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,unstable-traits \ 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 stm32l476vg,defmt,time-driver-any \ 51 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,unstable-traits,time \
52 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,unstable-traits \ 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 thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any \ 53 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,unstable-traits,time \
54 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,unstable-traits \ 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 thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any \ 55 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,unstable-traits,time \
56 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,unstable-traits \ 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 stm32f410tb,defmt,exti,time-driver-any \ 57 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,unstable-traits,time \
58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,unstable-traits \ 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 thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any \ 59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,unstable-traits,time \
60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,unstable-traits \ 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 thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any \ 61 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,unstable-traits,time \
62 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \ 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 stm32l476vg,defmt,exti,time-driver-any \ 63 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,unstable-traits,time \
64 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,unstable-traits \ 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 thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any \ 65 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,unstable-traits,time \
66 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits \ 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 thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any \ 67 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \
68 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \ 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 thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any \ 69 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \
70 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,unstable-traits \ 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,unstable-traits,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,unstable-traits,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,unstable-traits,time \
71 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf52840 --bin raw_spawn \ 76 --- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf52840 --bin raw_spawn \
72 --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --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/Cargo.toml b/cyw43/Cargo.toml
index dae7419c1..b19cabfe0 100644
--- a/cyw43/Cargo.toml
+++ b/cyw43/Cargo.toml
@@ -11,11 +11,10 @@ log = ["dep:log"]
11firmware-logs = [] 11firmware-logs = []
12 12
13[dependencies] 13[dependencies]
14embassy-time = { version = "0.1.3", path = "../embassy-time"} 14embassy-time = { version = "0.1.5", path = "../embassy-time"}
15embassy-sync = { version = "0.3.0", path = "../embassy-sync"} 15embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
16embassy-futures = { version = "0.1.0", path = "../embassy-futures"} 16embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
17embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} 17embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"}
18atomic-polyfill = "0.1.5"
19 18
20defmt = { version = "0.3", optional = true } 19defmt = { version = "0.3", optional = true }
21log = { version = "0.4.17", optional = true } 20log = { version = "0.4.17", optional = true }
diff --git a/cyw43/src/bus.rs b/cyw43/src/bus.rs
index 0b5632cf8..014109038 100644
--- a/cyw43/src/bus.rs
+++ b/cyw43/src/bus.rs
@@ -1,5 +1,5 @@
1use embassy_futures::yield_now; 1use embassy_futures::yield_now;
2use embassy_time::{Duration, Timer}; 2use embassy_time::Timer;
3use embedded_hal_1::digital::OutputPin; 3use embedded_hal_1::digital::OutputPin;
4use futures::FutureExt; 4use futures::FutureExt;
5 5
@@ -51,9 +51,9 @@ where
51 pub async fn init(&mut self) { 51 pub async fn init(&mut self) {
52 // Reset 52 // Reset
53 self.pwr.set_low().unwrap(); 53 self.pwr.set_low().unwrap();
54 Timer::after(Duration::from_millis(20)).await; 54 Timer::after_millis(20).await;
55 self.pwr.set_high().unwrap(); 55 self.pwr.set_high().unwrap();
56 Timer::after(Duration::from_millis(250)).await; 56 Timer::after_millis(250).await;
57 57
58 while self 58 while self
59 .read32_swapped(REG_BUS_TEST_RO) 59 .read32_swapped(REG_BUS_TEST_RO)
diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs
index a6d1f0bf5..d2709304c 100644
--- a/cyw43/src/control.rs
+++ b/cyw43/src/control.rs
@@ -1,8 +1,8 @@
1use core::cmp::{max, min}; 1use core::cmp::{max, min};
2 2
3use ch::driver::LinkState;
4use embassy_net_driver_channel as ch; 3use embassy_net_driver_channel as ch;
5use embassy_time::{Duration, Timer}; 4use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
5use embassy_time::Timer;
6 6
7pub use crate::bus::SpiBusCyw43; 7pub use crate::bus::SpiBusCyw43;
8use crate::consts::*; 8use crate::consts::*;
@@ -87,22 +87,22 @@ impl<'a> Control<'a> {
87 self.set_iovar("country", &country_info.to_bytes()).await; 87 self.set_iovar("country", &country_info.to_bytes()).await;
88 88
89 // set country takes some time, next ioctls fail if we don't wait. 89 // set country takes some time, next ioctls fail if we don't wait.
90 Timer::after(Duration::from_millis(100)).await; 90 Timer::after_millis(100).await;
91 91
92 // Set antenna to chip antenna 92 // Set antenna to chip antenna
93 self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await; 93 self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await;
94 94
95 self.set_iovar_u32("bus:txglom", 0).await; 95 self.set_iovar_u32("bus:txglom", 0).await;
96 Timer::after(Duration::from_millis(100)).await; 96 Timer::after_millis(100).await;
97 //self.set_iovar_u32("apsta", 1).await; // this crashes, also we already did it before...?? 97 //self.set_iovar_u32("apsta", 1).await; // this crashes, also we already did it before...??
98 //Timer::after(Duration::from_millis(100)).await; 98 //Timer::after_millis(100).await;
99 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 99 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
100 Timer::after(Duration::from_millis(100)).await; 100 Timer::after_millis(100).await;
101 self.set_iovar_u32("ampdu_mpdu", 4).await; 101 self.set_iovar_u32("ampdu_mpdu", 4).await;
102 Timer::after(Duration::from_millis(100)).await; 102 Timer::after_millis(100).await;
103 //self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes 103 //self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes
104 104
105 //Timer::after(Duration::from_millis(100)).await; 105 //Timer::after_millis(100).await;
106 106
107 // evts 107 // evts
108 let mut evts = EventMask { 108 let mut evts = EventMask {
@@ -121,19 +121,19 @@ impl<'a> Control<'a> {
121 121
122 self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await; 122 self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await;
123 123
124 Timer::after(Duration::from_millis(100)).await; 124 Timer::after_millis(100).await;
125 125
126 // set wifi up 126 // set wifi up
127 self.up().await; 127 self.up().await;
128 128
129 Timer::after(Duration::from_millis(100)).await; 129 Timer::after_millis(100).await;
130 130
131 self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto 131 self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto
132 self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any 132 self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any
133 133
134 Timer::after(Duration::from_millis(100)).await; 134 Timer::after_millis(100).await;
135 135
136 self.state_ch.set_ethernet_address(mac_addr); 136 self.state_ch.set_hardware_address(HardwareAddress::Ethernet(mac_addr));
137 137
138 debug!("INIT DONE"); 138 debug!("INIT DONE");
139 } 139 }
@@ -185,7 +185,7 @@ impl<'a> Control<'a> {
185 self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await; 185 self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await;
186 self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await; 186 self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await;
187 187
188 Timer::after(Duration::from_millis(100)).await; 188 Timer::after_millis(100).await;
189 189
190 let mut pfi = PassphraseInfo { 190 let mut pfi = PassphraseInfo {
191 len: passphrase.len() as _, 191 len: passphrase.len() as _,
@@ -297,7 +297,7 @@ impl<'a> Control<'a> {
297 if security != Security::OPEN { 297 if security != Security::OPEN {
298 self.set_iovar_u32x2("bsscfg:wpa_auth", 0, 0x0084).await; // wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK 298 self.set_iovar_u32x2("bsscfg:wpa_auth", 0, 0x0084).await; // wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK
299 299
300 Timer::after(Duration::from_millis(100)).await; 300 Timer::after_millis(100).await;
301 301
302 // Set passphrase 302 // Set passphrase
303 let mut pfi = PassphraseInfo { 303 let mut pfi = PassphraseInfo {
diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs
index 1c187faa5..83aee6b40 100644
--- a/cyw43/src/runner.rs
+++ b/cyw43/src/runner.rs
@@ -555,14 +555,14 @@ where
555 555
556 self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; 556 self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await;
557 557
558 Timer::after(Duration::from_millis(1)).await; 558 Timer::after_millis(1).await;
559 559
560 self.bus 560 self.bus
561 .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN) 561 .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN)
562 .await; 562 .await;
563 let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; 563 let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
564 564
565 Timer::after(Duration::from_millis(1)).await; 565 Timer::after_millis(1).await;
566 } 566 }
567 567
568 async fn core_is_up(&mut self, core: Core) -> bool { 568 async fn core_is_up(&mut self, core: Core) -> bool {
diff --git a/docs/modules/ROOT/examples/basic/Cargo.toml b/docs/modules/ROOT/examples/basic/Cargo.toml
index e94358a92..527ce2eda 100644
--- a/docs/modules/ROOT/examples/basic/Cargo.toml
+++ b/docs/modules/ROOT/examples/basic/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7 7
8[dependencies] 8[dependencies]
9embassy-executor = { version = "0.3.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } 9embassy-executor = { version = "0.3.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.1.0", path = "../../../../../embassy-time", features = ["defmt", "nightly"] } 10embassy-time = { version = "0.1.4", path = "../../../../../embassy-time", features = ["defmt", "nightly"] }
11embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] } 11embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] }
12 12
13defmt = "0.3" 13defmt = "0.3"
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 261a3c19c..ee559a821 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -1,6 +1,6 @@
1* xref:getting_started.adoc[Getting started] 1* xref:getting_started.adoc[Getting started]
2** xref:basic_application.adoc[Basic application] 2** xref:basic_application.adoc[Basic application]
3** xref:layer_by_layer.adoc[Layer by Layer] 3* xref:layer_by_layer.adoc[Bare metal to async]
4* xref:runtime.adoc[Executor] 4* xref:runtime.adoc[Executor]
5* xref:hal.adoc[HAL] 5* xref:hal.adoc[HAL]
6** xref:nrf.adoc[nRF] 6** xref:nrf.adoc[nRF]
@@ -9,4 +9,4 @@
9 9
10* xref:examples.adoc[Examples] 10* xref:examples.adoc[Examples]
11* xref:developer.adoc[Developer] 11* xref:developer.adoc[Developer]
12** xref:developer_stm32.adoc[Developer: STM32] \ No newline at end of file 12** xref:developer_stm32.adoc[Developer: STM32]
diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc
index 3f4f16e28..73774c71b 100644
--- a/docs/modules/ROOT/pages/basic_application.adoc
+++ b/docs/modules/ROOT/pages/basic_application.adoc
@@ -48,7 +48,7 @@ The `Spawner` is the way the main application spawns other tasks. The `Periphera
48include::example$basic/src/main.rs[lines="22..-1"] 48include::example$basic/src/main.rs[lines="22..-1"]
49---- 49----
50 50
51What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy::main]` macro. The macro does the following: 51What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy_executor::main]` macro. The macro does the following:
52 52
53. Creates an Embassy Executor 53. Creates an Embassy Executor
54. Initializes the microcontroller HAL to get the `Peripherals` 54. Initializes the microcontroller HAL to get the `Peripherals`
diff --git a/docs/modules/ROOT/pages/getting_started.adoc b/docs/modules/ROOT/pages/getting_started.adoc
index 881e449b6..2c6f4b1ee 100644
--- a/docs/modules/ROOT/pages/getting_started.adoc
+++ b/docs/modules/ROOT/pages/getting_started.adoc
@@ -3,7 +3,7 @@
3So you want to try Embassy, great! To get started, there are a few tools you need to install: 3So you want to try Embassy, great! To get started, there are a few tools you need to install:
4 4
5* link:https://rustup.rs/[rustup] - the Rust toolchain is needed to compile Rust code. 5* link:https://rustup.rs/[rustup] - the Rust toolchain is needed to compile Rust code.
6* link:https://crates.io/crates/probe-run[probe-run] - to flash the firmware on your device. If you already have other tools like `OpenOCD` setup, you can use that as well. 6* link:https://crates.io/crates/probe-rs[probe-rs] - to flash the firmware on your device. If you already have other tools like `OpenOCD` setup, you can use that as well.
7 7
8If you don't have any supported board, don't worry: you can also run embassy on your PC using the `std` examples. 8If you don't have any supported board, don't worry: you can also run embassy on your PC using the `std` examples.
9 9
@@ -30,6 +30,10 @@ Embassy supports many microcontroller families, but the easiest ways to get star
30 30
31* link:https://www.raspberrypi.com/products/raspberry-pi-pico/[Raspberry Pi Pico] 31* link:https://www.raspberrypi.com/products/raspberry-pi-pico/[Raspberry Pi Pico]
32 32
33=== ESP32
34
35* link:https://github.com/esp-rs/esp-rust-board[ESP32C3]
36
33== Running an example 37== Running an example
34 38
35First you need to clone the [github repository]; 39First you need to clone the [github repository];
@@ -38,7 +42,6 @@ First you need to clone the [github repository];
38---- 42----
39git clone https://github.com/embassy-rs/embassy.git 43git clone https://github.com/embassy-rs/embassy.git
40cd embassy 44cd embassy
41git submodule update --init
42---- 45----
43 46
44You can run an example by opening a terminal and entering the following commands: 47You can run an example by opening a terminal and entering the following commands:
diff --git a/docs/modules/ROOT/pages/hal.adoc b/docs/modules/ROOT/pages/hal.adoc
index de4ab33be..b1382e8e5 100644
--- a/docs/modules/ROOT/pages/hal.adoc
+++ b/docs/modules/ROOT/pages/hal.adoc
@@ -7,4 +7,6 @@ Embassy provides HALs for several microcontroller families:
7* `embassy-rp` for the Raspberry Pi RP2040 microcontrollers 7* `embassy-rp` for the Raspberry Pi RP2040 microcontrollers
8 8
9These HALs implement async/await functionality for most peripherals while also implementing the 9These HALs implement async/await functionality for most peripherals while also implementing the
10async traits in `embedded-hal-async`. You can also use these HALs with another executor. 10async traits in `embedded-hal` and `embedded-hal-async`. You can also use these HALs with another executor.
11
12For the ESP32 series, there is an link:https://github.com/esp-rs/esp-hal[esp-hal] which you can use.
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc
index 805a1e70e..c6dead464 100644
--- a/docs/modules/ROOT/pages/index.adoc
+++ b/docs/modules/ROOT/pages/index.adoc
@@ -17,13 +17,26 @@ The Embassy project consists of several crates that you can use together or inde
17* **Hardware Abstraction Layers** - HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed. The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy. 17* **Hardware Abstraction Layers** - HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed. The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy.
18** link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families. 18** link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families.
19** link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series. 19** link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series.
20** link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 microcontroller.
21** link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips.
22+
23NOTE: A common question is if one can use the Embassy HALs standalone. Yes, it is possible! There are no dependency on the executor within the HALs. You can even use them without async,
24as they implement both the link:https://github.com/rust-embedded/embedded-hal[Embedded HAL] blocking and async traits.
20 25
21* **Networking** - The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implements extensive networking functionality, including Ethernet, IP, TCP, UDP, ICMP and DHCP. Async drastically simplifies managing timeouts and serving multiple connections concurrently. 26* **Networking** - The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implements extensive networking functionality, including Ethernet, IP, TCP, UDP, ICMP and DHCP. Async drastically simplifies managing timeouts and serving multiple connections concurrently. Several drivers for WiFi and Ethernet chips can be found.
22 27
23* **Bluetooth** - The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers. 28* **Bluetooth** - The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers.
24 29
25* **LoRa** - link:https://docs.embassy.dev/embassy-lora/[embassy-lora] supports LoRa networking on STM32WL wireless microcontrollers and Semtech SX127x transceivers. 30* **LoRa** - link:https://github.com/embassy-rs/lora-phy[lora-phy] and link:https://docs.embassy.dev/embassy-lora/[embassy-lora] supports LoRa networking on a wide range of LoRa radios, fully integrated with a Rust link:https://github.com/ivajloip/rust-lorawan[LoRaWAN] implementation.
26 31
27* **USB** - link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own. 32* **USB** - link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own.
28 33
29* **Bootloader and DFU** - link:https://github.com/embassy-rs/embassy/tree/master/embassy-boot[embassy-boot] is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks. 34* **Bootloader and DFU** - link:https://github.com/embassy-rs/embassy/tree/master/embassy-boot[embassy-boot] is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks.
35
36== Resources
37
38For more reading material on async Rust and Embassy:
39
40* link:https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown[Comparsion of FreeRTOS and Embassy]
41* link:https://dev.to/apollolabsbin/series/20707[Tutorials]
42* link:https://blog.drogue.io/firmware-updates-part-1/[Firmware Updates with Embassy]
diff --git a/docs/modules/ROOT/pages/layer_by_layer.adoc b/docs/modules/ROOT/pages/layer_by_layer.adoc
index a78a64a97..1d7bdc89b 100644
--- a/docs/modules/ROOT/pages/layer_by_layer.adoc
+++ b/docs/modules/ROOT/pages/layer_by_layer.adoc
@@ -1,4 +1,4 @@
1= Embassy layer by layer 1= From bare metal to async Rust
2 2
3If you're new to Embassy, it can be overwhelming to grasp all the terminology and concepts. This guide aims to clarify the different layers in Embassy, which problem each layer solves for the application writer. 3If you're new to Embassy, it can be overwhelming to grasp all the terminology and concepts. This guide aims to clarify the different layers in Embassy, which problem each layer solves for the application writer.
4 4
@@ -8,8 +8,7 @@ The application we'll write is a simple 'push button, blink led' application, wh
8 8
9== PAC version 9== PAC version
10 10
11The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types 11The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code.
12to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code.
13 12
14Writing an application using the PAC directly is therefore not recommended, but if the functionality you want to use is not exposed in the upper layers, that's what you need to use. 13Writing an application using the PAC directly is therefore not recommended, but if the functionality you want to use is not exposed in the upper layers, that's what you need to use.
15 14
diff --git a/docs/modules/ROOT/pages/nrf.adoc b/docs/modules/ROOT/pages/nrf.adoc
index 10fe54b47..1706087ae 100644
--- a/docs/modules/ROOT/pages/nrf.adoc
+++ b/docs/modules/ROOT/pages/nrf.adoc
@@ -8,7 +8,7 @@ The nRF timer driver operates at 32768 Hz by default.
8 8
9== Peripherals 9== Peripherals
10 10
11The following peripherals have a HAL implementation at present: 11The following peripherals have a HAL implementation at present
12 12
13* PWM 13* PWM
14* SPIM 14* SPIM
@@ -23,3 +23,7 @@ The following peripherals have a HAL implementation at present:
23* UARTE 23* UARTE
24* TWIM 24* TWIM
25* SAADC 25* SAADC
26
27== Bluetooth
28
29For bluetooth, you can use the link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate.
diff --git a/docs/modules/ROOT/pages/runtime.adoc b/docs/modules/ROOT/pages/runtime.adoc
index 5096f5a43..8f4921f67 100644
--- a/docs/modules/ROOT/pages/runtime.adoc
+++ b/docs/modules/ROOT/pages/runtime.adoc
@@ -6,11 +6,11 @@ The Embassy executor is an async/await executor designed for embedded usage alon
6 6
7* No `alloc`, no heap needed. Task are statically allocated. 7* No `alloc`, no heap needed. Task are statically allocated.
8* No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning. 8* No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
9* Integrated timer queue: sleeping is easy, just do `Timer::after(Duration::from_secs(1)).await;`. 9* Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`.
10* No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`. 10* No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`.
11* Efficient polling: a wake will only poll the woken task, not all of them. 11* Efficient polling: a wake will only poll the woken task, not all of them.
12* Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time. 12* Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
13* Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks. 13* Creating multiple executor instances is supported, to run tasks at different priority levels. This allows higher-priority tasks to preempt lower-priority tasks.
14 14
15== Executor 15== Executor
16 16
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml
index 62a95ed91..55ef734e0 100644
--- a/embassy-embedded-hal/Cargo.toml
+++ b/embassy-embedded-hal/Cargo.toml
@@ -21,7 +21,7 @@ default = ["time"]
21[dependencies] 21[dependencies]
22embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true } 22embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true }
23embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 23embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
24embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 24embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
25embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ 25embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
26 "unproven", 26 "unproven",
27] } 27] }
diff --git a/embassy-embedded-hal/src/flash/partition/mod.rs b/embassy-embedded-hal/src/flash/partition/mod.rs
index a12e49ce1..42c8a308d 100644
--- a/embassy-embedded-hal/src/flash/partition/mod.rs
+++ b/embassy-embedded-hal/src/flash/partition/mod.rs
@@ -11,7 +11,7 @@ pub use asynch::Partition;
11pub use blocking::BlockingPartition; 11pub use blocking::BlockingPartition;
12 12
13/// Partition error 13/// Partition error
14#[derive(Debug)] 14#[derive(Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))] 15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error<T> { 16pub enum Error<T> {
17 /// The requested flash area is outside the partition 17 /// The requested flash area is outside the partition
diff --git a/embassy-embedded-hal/src/lib.rs b/embassy-embedded-hal/src/lib.rs
index 3aad838bd..ee964e404 100644
--- a/embassy-embedded-hal/src/lib.rs
+++ b/embassy-embedded-hal/src/lib.rs
@@ -1,5 +1,5 @@
1#![cfg_attr(not(feature = "std"), no_std)] 1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections, try_blocks))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, try_blocks))]
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4 4
5//! Utilities to use `embedded-hal` traits with Embassy. 5//! Utilities to use `embedded-hal` traits with Embassy.
@@ -26,6 +26,18 @@ pub trait SetConfig {
26 /// The configuration type used by this driver. 26 /// The configuration type used by this driver.
27 type Config; 27 type Config;
28 28
29 /// The error type that can occur if `set_config` fails.
30 type ConfigError;
31
29 /// Set the configuration of the driver. 32 /// Set the configuration of the driver.
30 fn set_config(&mut self, config: &Self::Config); 33 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError>;
34}
35
36/// Get the configuration of a peripheral driver.
37pub trait GetConfig {
38 /// The configuration type used by this driver.
39 type Config;
40
41 /// Get the configuration of the driver.
42 fn get_config(&self) -> Self::Config;
31} 43}
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
index 87e8a4304..1053d3849 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
@@ -125,14 +125,14 @@ where
125{ 125{
126 async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), I2cDeviceError<BUS::Error>> { 126 async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
127 let mut bus = self.bus.lock().await; 127 let mut bus = self.bus.lock().await;
128 bus.set_config(&self.config); 128 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
129 bus.read(address, buffer).await.map_err(I2cDeviceError::I2c)?; 129 bus.read(address, buffer).await.map_err(I2cDeviceError::I2c)?;
130 Ok(()) 130 Ok(())
131 } 131 }
132 132
133 async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), I2cDeviceError<BUS::Error>> { 133 async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
134 let mut bus = self.bus.lock().await; 134 let mut bus = self.bus.lock().await;
135 bus.set_config(&self.config); 135 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
136 bus.write(address, bytes).await.map_err(I2cDeviceError::I2c)?; 136 bus.write(address, bytes).await.map_err(I2cDeviceError::I2c)?;
137 Ok(()) 137 Ok(())
138 } 138 }
@@ -144,7 +144,7 @@ where
144 rd_buffer: &mut [u8], 144 rd_buffer: &mut [u8],
145 ) -> Result<(), I2cDeviceError<BUS::Error>> { 145 ) -> Result<(), I2cDeviceError<BUS::Error>> {
146 let mut bus = self.bus.lock().await; 146 let mut bus = self.bus.lock().await;
147 bus.set_config(&self.config); 147 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
148 bus.write_read(address, wr_buffer, rd_buffer) 148 bus.write_read(address, wr_buffer, rd_buffer)
149 .await 149 .await
150 .map_err(I2cDeviceError::I2c)?; 150 .map_err(I2cDeviceError::I2c)?;
@@ -153,7 +153,7 @@ where
153 153
154 async fn transaction(&mut self, address: u8, operations: &mut [i2c::Operation<'_>]) -> Result<(), Self::Error> { 154 async fn transaction(&mut self, address: u8, operations: &mut [i2c::Operation<'_>]) -> Result<(), Self::Error> {
155 let mut bus = self.bus.lock().await; 155 let mut bus = self.bus.lock().await;
156 bus.set_config(&self.config); 156 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
157 bus.transaction(address, operations) 157 bus.transaction(address, operations)
158 .await 158 .await
159 .map_err(I2cDeviceError::I2c)?; 159 .map_err(I2cDeviceError::I2c)?;
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
index 030392183..5d3cf658a 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
@@ -76,9 +76,7 @@ where
76 #[cfg(not(feature = "time"))] 76 #[cfg(not(feature = "time"))]
77 Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), 77 Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported),
78 #[cfg(feature = "time")] 78 #[cfg(feature = "time")]
79 Operation::DelayUs(us) => { 79 Operation::DelayUs(us) => embassy_time::Timer::after_micros(*us as _).await,
80 embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await
81 }
82 } 80 }
83 } 81 }
84 }; 82 };
@@ -130,7 +128,7 @@ where
130{ 128{
131 async fn transaction(&mut self, operations: &mut [spi::Operation<'_, u8>]) -> Result<(), Self::Error> { 129 async fn transaction(&mut self, operations: &mut [spi::Operation<'_, u8>]) -> Result<(), Self::Error> {
132 let mut bus = self.bus.lock().await; 130 let mut bus = self.bus.lock().await;
133 bus.set_config(&self.config); 131 bus.set_config(&self.config).map_err(|_| SpiDeviceError::Config)?;
134 self.cs.set_low().map_err(SpiDeviceError::Cs)?; 132 self.cs.set_low().map_err(SpiDeviceError::Cs)?;
135 133
136 let op_res: Result<(), BUS::Error> = try { 134 let op_res: Result<(), BUS::Error> = try {
@@ -143,9 +141,7 @@ where
143 #[cfg(not(feature = "time"))] 141 #[cfg(not(feature = "time"))]
144 Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), 142 Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported),
145 #[cfg(feature = "time")] 143 #[cfg(feature = "time")]
146 Operation::DelayUs(us) => { 144 Operation::DelayUs(us) => embassy_time::Timer::after_micros(*us as _).await,
147 embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await
148 }
149 } 145 }
150 } 146 }
151 }; 147 };
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
index af73df059..233c9e1fd 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
@@ -148,7 +148,7 @@ where
148 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 148 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
149 self.bus.lock(|bus| { 149 self.bus.lock(|bus| {
150 let mut bus = bus.borrow_mut(); 150 let mut bus = bus.borrow_mut();
151 bus.set_config(&self.config); 151 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
152 bus.read(address, buffer).map_err(I2cDeviceError::I2c) 152 bus.read(address, buffer).map_err(I2cDeviceError::I2c)
153 }) 153 })
154 } 154 }
@@ -156,7 +156,7 @@ where
156 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { 156 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
157 self.bus.lock(|bus| { 157 self.bus.lock(|bus| {
158 let mut bus = bus.borrow_mut(); 158 let mut bus = bus.borrow_mut();
159 bus.set_config(&self.config); 159 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
160 bus.write(address, bytes).map_err(I2cDeviceError::I2c) 160 bus.write(address, bytes).map_err(I2cDeviceError::I2c)
161 }) 161 })
162 } 162 }
@@ -164,7 +164,7 @@ where
164 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { 164 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
165 self.bus.lock(|bus| { 165 self.bus.lock(|bus| {
166 let mut bus = bus.borrow_mut(); 166 let mut bus = bus.borrow_mut();
167 bus.set_config(&self.config); 167 bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
168 bus.write_read(address, wr_buffer, rd_buffer) 168 bus.write_read(address, wr_buffer, rd_buffer)
169 .map_err(I2cDeviceError::I2c) 169 .map_err(I2cDeviceError::I2c)
170 }) 170 })
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
index 6d03d6263..feb0f5b7d 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
@@ -163,7 +163,7 @@ where
163 fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> { 163 fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
164 self.bus.lock(|bus| { 164 self.bus.lock(|bus| {
165 let mut bus = bus.borrow_mut(); 165 let mut bus = bus.borrow_mut();
166 bus.set_config(&self.config); 166 bus.set_config(&self.config).map_err(|_| SpiDeviceError::Config)?;
167 self.cs.set_low().map_err(SpiDeviceError::Cs)?; 167 self.cs.set_low().map_err(SpiDeviceError::Cs)?;
168 168
169 let op_res = operations.iter_mut().try_for_each(|op| match op { 169 let op_res = operations.iter_mut().try_for_each(|op| match op {
diff --git a/embassy-embedded-hal/src/shared_bus/mod.rs b/embassy-embedded-hal/src/shared_bus/mod.rs
index 79a90bd52..b0159ac09 100644
--- a/embassy-embedded-hal/src/shared_bus/mod.rs
+++ b/embassy-embedded-hal/src/shared_bus/mod.rs
@@ -14,6 +14,8 @@ pub mod blocking;
14pub enum I2cDeviceError<BUS> { 14pub enum I2cDeviceError<BUS> {
15 /// An operation on the inner I2C bus failed. 15 /// An operation on the inner I2C bus failed.
16 I2c(BUS), 16 I2c(BUS),
17 /// Configuration of the inner I2C bus failed.
18 Config,
17} 19}
18 20
19impl<BUS> i2c::Error for I2cDeviceError<BUS> 21impl<BUS> i2c::Error for I2cDeviceError<BUS>
@@ -23,6 +25,7 @@ where
23 fn kind(&self) -> i2c::ErrorKind { 25 fn kind(&self) -> i2c::ErrorKind {
24 match self { 26 match self {
25 Self::I2c(e) => e.kind(), 27 Self::I2c(e) => e.kind(),
28 Self::Config => i2c::ErrorKind::Other,
26 } 29 }
27 } 30 }
28} 31}
@@ -38,6 +41,8 @@ pub enum SpiDeviceError<BUS, CS> {
38 Cs(CS), 41 Cs(CS),
39 /// DelayUs operations are not supported when the `time` Cargo feature is not enabled. 42 /// DelayUs operations are not supported when the `time` Cargo feature is not enabled.
40 DelayUsNotSupported, 43 DelayUsNotSupported,
44 /// The SPI bus could not be configured.
45 Config,
41} 46}
42 47
43impl<BUS, CS> spi::Error for SpiDeviceError<BUS, CS> 48impl<BUS, CS> spi::Error for SpiDeviceError<BUS, CS>
@@ -50,6 +55,7 @@ where
50 Self::Spi(e) => e.kind(), 55 Self::Spi(e) => e.kind(),
51 Self::Cs(_) => spi::ErrorKind::Other, 56 Self::Cs(_) => spi::ErrorKind::Other,
52 Self::DelayUsNotSupported => spi::ErrorKind::Other, 57 Self::DelayUsNotSupported => spi::ErrorKind::Other,
58 Self::Config => spi::ErrorKind::Other,
53 } 59 }
54 } 60 }
55} 61}
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index 35944625f..a793a1980 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -59,7 +59,7 @@ rtos-trace = { version = "0.1.2", optional = true }
59 59
60futures-util = { version = "0.3.17", default-features = false } 60futures-util = { version = "0.3.17", default-features = false }
61embassy-macros = { version = "0.2.1", path = "../embassy-macros" } 61embassy-macros = { version = "0.2.1", path = "../embassy-macros" }
62embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true} 62embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true}
63atomic-polyfill = "1.0.1" 63atomic-polyfill = "1.0.1"
64critical-section = "1.1" 64critical-section = "1.1"
65static_cell = "1.1" 65static_cell = "1.1"
diff --git a/embassy-executor/README.md b/embassy-executor/README.md
index 47d0cb8a2..3c1448a18 100644
--- a/embassy-executor/README.md
+++ b/embassy-executor/README.md
@@ -4,7 +4,7 @@ An async/await executor designed for embedded usage.
4 4
5- No `alloc`, no heap needed. Task futures are statically allocated. 5- No `alloc`, no heap needed. Task futures are statically allocated.
6- No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning. 6- No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
7- Integrated timer queue: sleeping is easy, just do `Timer::after(Duration::from_secs(1)).await;`. 7- Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`.
8- No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`. 8- No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`.
9- Efficient polling: a wake will only poll the woken task, not all of them. 9- Efficient polling: a wake will only poll the woken task, not all of them.
10- Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time. 10- Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
diff --git a/embassy-hal-internal/README.md b/embassy-hal-internal/README.md
index d6539701b..6b060d1c0 100644
--- a/embassy-hal-internal/README.md
+++ b/embassy-hal-internal/README.md
@@ -1,4 +1,4 @@
1# embassy-macros 1# embassy-hal-internal
2 2
3An [Embassy](https://embassy.dev) project. 3An [Embassy](https://embassy.dev) project.
4 4
diff --git a/embassy-hal-internal/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs
index b970aa2cd..19dabcf6f 100644
--- a/embassy-hal-internal/src/interrupt.rs
+++ b/embassy-hal-internal/src/interrupt.rs
@@ -4,6 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
4 4
5use cortex_m::interrupt::InterruptNumber; 5use cortex_m::interrupt::InterruptNumber;
6use cortex_m::peripheral::NVIC; 6use cortex_m::peripheral::NVIC;
7use critical_section::CriticalSection;
7 8
8/// Generate a standard `mod interrupt` for a HAL. 9/// Generate a standard `mod interrupt` for a HAL.
9#[macro_export] 10#[macro_export]
@@ -91,6 +92,12 @@ macro_rules! interrupt_mod {
91 fn set_priority(prio: crate::interrupt::Priority) { 92 fn set_priority(prio: crate::interrupt::Priority) {
92 Self::IRQ.set_priority(prio) 93 Self::IRQ.set_priority(prio)
93 } 94 }
95
96 /// Set the interrupt priority with an already-acquired critical section
97 #[inline]
98 fn set_priority_with_cs(cs: critical_section::CriticalSection, prio: crate::interrupt::Priority) {
99 Self::IRQ.set_priority_with_cs(cs, prio)
100 }
94 } 101 }
95 102
96 $( 103 $(
@@ -195,10 +202,29 @@ pub unsafe trait InterruptExt: InterruptNumber + Copy {
195 /// Set the interrupt priority. 202 /// Set the interrupt priority.
196 #[inline] 203 #[inline]
197 fn set_priority(self, prio: Priority) { 204 fn set_priority(self, prio: Priority) {
198 critical_section::with(|_| unsafe { 205 unsafe {
206 let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(());
207
208 // On thumbv6, set_priority must do a RMW to change 8bit in a 32bit reg.
209 #[cfg(armv6m)]
210 critical_section::with(|_| nvic.set_priority(self, prio.into()));
211 // On thumbv7+, set_priority does an atomic 8bit write, so no CS needed.
212 #[cfg(not(armv6m))]
213 nvic.set_priority(self, prio.into());
214 }
215 }
216
217 /// Set the interrupt priority with an already-acquired critical section
218 ///
219 /// Equivalent to `set_priority`, except you pass a `CriticalSection` to prove
220 /// you've already acquired a critical section. This prevents acquiring another
221 /// one, which saves code size.
222 #[inline]
223 fn set_priority_with_cs(self, _cs: CriticalSection, prio: Priority) {
224 unsafe {
199 let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); 225 let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(());
200 nvic.set_priority(self, prio.into()) 226 nvic.set_priority(self, prio.into());
201 }) 227 }
202 } 228 }
203} 229}
204 230
diff --git a/embassy-hal-internal/src/lib.rs b/embassy-hal-internal/src/lib.rs
index 3640ea184..f3d59e588 100644
--- a/embassy-hal-internal/src/lib.rs
+++ b/embassy-hal-internal/src/lib.rs
@@ -10,7 +10,6 @@ pub mod drop;
10mod macros; 10mod macros;
11mod peripheral; 11mod peripheral;
12pub mod ratio; 12pub mod ratio;
13pub mod ring_buffer;
14pub use peripheral::{Peripheral, PeripheralRef}; 13pub use peripheral::{Peripheral, PeripheralRef};
15 14
16#[cfg(feature = "cortex-m")] 15#[cfg(feature = "cortex-m")]
diff --git a/embassy-hal-internal/src/macros.rs b/embassy-hal-internal/src/macros.rs
index 0eea4b667..97df38954 100644
--- a/embassy-hal-internal/src/macros.rs
+++ b/embassy-hal-internal/src/macros.rs
@@ -48,17 +48,23 @@ macro_rules! peripherals_struct {
48 ///Returns all the peripherals *once* 48 ///Returns all the peripherals *once*
49 #[inline] 49 #[inline]
50 pub(crate) fn take() -> Self { 50 pub(crate) fn take() -> Self {
51 critical_section::with(Self::take_with_cs)
52 }
51 53
54 ///Returns all the peripherals *once*
55 #[inline]
56 pub(crate) fn take_with_cs(_cs: critical_section::CriticalSection) -> Self {
52 #[no_mangle] 57 #[no_mangle]
53 static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; 58 static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false;
54 59
55 critical_section::with(|_| unsafe { 60 // safety: OK because we're inside a CS.
61 unsafe {
56 if _EMBASSY_DEVICE_PERIPHERALS { 62 if _EMBASSY_DEVICE_PERIPHERALS {
57 panic!("init called more than once!") 63 panic!("init called more than once!")
58 } 64 }
59 _EMBASSY_DEVICE_PERIPHERALS = true; 65 _EMBASSY_DEVICE_PERIPHERALS = true;
60 Self::steal() 66 Self::steal()
61 }) 67 }
62 } 68 }
63 } 69 }
64 70
diff --git a/embassy-hal-internal/src/ring_buffer.rs b/embassy-hal-internal/src/ring_buffer.rs
deleted file mode 100644
index fcad68bb1..000000000
--- a/embassy-hal-internal/src/ring_buffer.rs
+++ /dev/null
@@ -1,136 +0,0 @@
1pub struct RingBuffer<'a> {
2 buf: &'a mut [u8],
3 start: usize,
4 end: usize,
5 empty: bool,
6}
7
8impl<'a> RingBuffer<'a> {
9 pub fn new(buf: &'a mut [u8]) -> Self {
10 Self {
11 buf,
12 start: 0,
13 end: 0,
14 empty: true,
15 }
16 }
17
18 pub fn push_buf(&mut self) -> &mut [u8] {
19 if self.start == self.end && !self.empty {
20 trace!(" ringbuf: push_buf empty");
21 return &mut self.buf[..0];
22 }
23
24 let n = if self.start <= self.end {
25 self.buf.len() - self.end
26 } else {
27 self.start - self.end
28 };
29
30 trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
31 &mut self.buf[self.end..self.end + n]
32 }
33
34 pub fn push(&mut self, n: usize) {
35 trace!(" ringbuf: push {:?}", n);
36 if n == 0 {
37 return;
38 }
39
40 self.end = self.wrap(self.end + n);
41 self.empty = false;
42 }
43
44 pub fn pop_buf(&mut self) -> &mut [u8] {
45 if self.empty {
46 trace!(" ringbuf: pop_buf empty");
47 return &mut self.buf[..0];
48 }
49
50 let n = if self.end <= self.start {
51 self.buf.len() - self.start
52 } else {
53 self.end - self.start
54 };
55
56 trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
57 &mut self.buf[self.start..self.start + n]
58 }
59
60 pub fn pop(&mut self, n: usize) {
61 trace!(" ringbuf: pop {:?}", n);
62 if n == 0 {
63 return;
64 }
65
66 self.start = self.wrap(self.start + n);
67 self.empty = self.start == self.end;
68 }
69
70 pub fn is_full(&self) -> bool {
71 self.start == self.end && !self.empty
72 }
73
74 pub fn is_empty(&self) -> bool {
75 self.empty
76 }
77
78 pub fn clear(&mut self) {
79 self.start = 0;
80 self.end = 0;
81 self.empty = true;
82 }
83
84 fn wrap(&self, n: usize) -> usize {
85 assert!(n <= self.buf.len());
86 if n == self.buf.len() {
87 0
88 } else {
89 n
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn push_pop() {
100 let mut b = [0; 4];
101 let mut rb = RingBuffer::new(&mut b);
102 let buf = rb.push_buf();
103 assert_eq!(4, buf.len());
104 buf[0] = 1;
105 buf[1] = 2;
106 buf[2] = 3;
107 buf[3] = 4;
108 rb.push(4);
109
110 let buf = rb.pop_buf();
111 assert_eq!(4, buf.len());
112 assert_eq!(1, buf[0]);
113 rb.pop(1);
114
115 let buf = rb.pop_buf();
116 assert_eq!(3, buf.len());
117 assert_eq!(2, buf[0]);
118 rb.pop(1);
119
120 let buf = rb.pop_buf();
121 assert_eq!(2, buf.len());
122 assert_eq!(3, buf[0]);
123 rb.pop(1);
124
125 let buf = rb.pop_buf();
126 assert_eq!(1, buf.len());
127 assert_eq!(4, buf[0]);
128 rb.pop(1);
129
130 let buf = rb.pop_buf();
131 assert_eq!(0, buf.len());
132
133 let buf = rb.push_buf();
134 assert_eq!(4, buf.len());
135 }
136}
diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml
index 88f815cd0..846c39199 100644
--- a/embassy-lora/Cargo.toml
+++ b/embassy-lora/Cargo.toml
@@ -20,7 +20,7 @@ defmt = ["dep:defmt", "lorawan-device/defmt"]
20defmt = { version = "0.3", optional = true } 20defmt = { version = "0.3", optional = true }
21log = { version = "0.4.14", optional = true } 21log = { version = "0.4.14", optional = true }
22 22
23embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 23embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
24embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 24embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
25embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } 25embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
26embedded-hal-async = { version = "=1.0.0-rc.1" } 26embedded-hal-async = { version = "=1.0.0-rc.1" }
diff --git a/embassy-lora/src/lib.rs b/embassy-lora/src/lib.rs
index c23d1d0dd..5637802bb 100644
--- a/embassy-lora/src/lib.rs
+++ b/embassy-lora/src/lib.rs
@@ -1,5 +1,5 @@
1#![no_std] 1#![no_std]
2#![feature(async_fn_in_trait, impl_trait_projections)] 2#![feature(async_fn_in_trait)]
3//! embassy-lora holds LoRa-specific functionality. 3//! embassy-lora holds LoRa-specific functionality.
4 4
5pub(crate) mod fmt; 5pub(crate) mod fmt;
@@ -34,6 +34,6 @@ impl lorawan_device::async_device::radio::Timer for LoraTimer {
34 } 34 }
35 35
36 async fn delay_ms(&mut self, millis: u64) { 36 async fn delay_ms(&mut self, millis: u64) {
37 Timer::after(Duration::from_millis(millis)).await 37 Timer::after_millis(millis).await
38 } 38 }
39} 39}
diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml
index 8de8eadea..a781f3bd0 100644
--- a/embassy-net-adin1110/Cargo.toml
+++ b/embassy-net-adin1110/Cargo.toml
@@ -16,8 +16,8 @@ log = { version = "0.4", default-features = false, optional = true }
16embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } 16embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
17embedded-hal-async = { version = "=1.0.0-rc.1" } 17embedded-hal-async = { version = "=1.0.0-rc.1" }
18embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] } 18embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] }
19embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } 19embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
20embassy-time = { version = "0.1.3" } 20embassy-time = { version = "0.1.5", path = "../embassy-time" }
21embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 21embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
22bitfield = "0.14.0" 22bitfield = "0.14.0"
23 23
diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs
index 53f361284..edee3438b 100644
--- a/embassy-net-adin1110/src/lib.rs
+++ b/embassy-net-adin1110/src/lib.rs
@@ -20,7 +20,7 @@ pub use crc32::ETH_FCS;
20use crc8::crc8; 20use crc8::crc8;
21use embassy_futures::select::{select, Either}; 21use embassy_futures::select::{select, Either};
22use embassy_net_driver_channel as ch; 22use embassy_net_driver_channel as ch;
23use embassy_time::{Duration, Timer}; 23use embassy_time::Timer;
24use embedded_hal_1::digital::OutputPin; 24use embedded_hal_1::digital::OutputPin;
25use embedded_hal_async::digital::Wait; 25use embedded_hal_async::digital::Wait;
26use embedded_hal_async::spi::{Error, Operation, SpiDevice}; 26use embedded_hal_async::spi::{Error, Operation, SpiDevice};
@@ -609,12 +609,12 @@ pub async fn new<const N_RX: usize, const N_TX: usize, SPI: SpiDevice, INT: Wait
609 reset.set_low().unwrap(); 609 reset.set_low().unwrap();
610 610
611 // Wait t1: 20-43mS 611 // Wait t1: 20-43mS
612 Timer::after(Duration::from_millis(30)).await; 612 Timer::after_millis(30).await;
613 613
614 reset.set_high().unwrap(); 614 reset.set_high().unwrap();
615 615
616 // Wait t3: 50mS 616 // Wait t3: 50mS
617 Timer::after(Duration::from_millis(50)).await; 617 Timer::after_millis(50).await;
618 618
619 // Create device 619 // Create device
620 let mut mac = ADIN1110::new(spi_dev, spi_crc, append_fcs_on_tx); 620 let mut mac = ADIN1110::new(spi_dev, spi_crc, append_fcs_on_tx);
diff --git a/embassy-net-driver-channel/CHANGELOG.md b/embassy-net-driver-channel/CHANGELOG.md
new file mode 100644
index 000000000..b04d0a86b
--- /dev/null
+++ b/embassy-net-driver-channel/CHANGELOG.md
@@ -0,0 +1,16 @@
1# Changelog
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8## 0.2.0 - 2023-10-18
9
10- Update `embassy-net-driver` to v0.2
11- `Runner::new` now takes an `embassy_net_driver::HardwareAddress` parameter.
12- `Runner::set_ethernet_address` is now `set_hardware_address`.
13
14## 0.1.0 - 2023-06-29
15
16- First release
diff --git a/embassy-net-driver-channel/Cargo.toml b/embassy-net-driver-channel/Cargo.toml
index 4588af02d..2fd26a7ca 100644
--- a/embassy-net-driver-channel/Cargo.toml
+++ b/embassy-net-driver-channel/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2name = "embassy-net-driver-channel" 2name = "embassy-net-driver-channel"
3version = "0.1.0" 3version = "0.2.0"
4edition = "2021" 4edition = "2021"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack." 6description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack."
@@ -26,4 +26,4 @@ log = { version = "0.4.14", optional = true }
26 26
27embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 27embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
28embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 28embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
29embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 29embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
diff --git a/embassy-net-driver-channel/README.md b/embassy-net-driver-channel/README.md
index 8f904ce95..90a216388 100644
--- a/embassy-net-driver-channel/README.md
+++ b/embassy-net-driver-channel/README.md
@@ -7,7 +7,9 @@ The `embassy-net-driver` trait is polling-based. To implement it, you must write
7hand, and hook up the `Waker`s provided by `embassy-net` to the right interrupt handlers so that `embassy-net` 7hand, and hook up the `Waker`s provided by `embassy-net` to the right interrupt handlers so that `embassy-net`
8knows when to poll your driver again to make more progress. 8knows when to poll your driver again to make more progress.
9 9
10With `embassy-net-driver-channel` 10With `embassy-net-driver-channel` you get a "channel-like" interface instead, where you can send/receive packets
11to/from embassy-net. The intended usage is to spawn a "driver task" in the background that does this, passing
12packets between the hardware and the channel.
11 13
12## A note about deadlocks 14## A note about deadlocks
13 15
@@ -18,19 +20,19 @@ loop {
18 // Wait for either.. 20 // Wait for either..
19 match select( 21 match select(
20 // ... the chip signaling an interrupt, indicating a packet is available to receive, or 22 // ... the chip signaling an interrupt, indicating a packet is available to receive, or
21 irq_pin.wait_for_low(), 23 irq_pin.wait_for_low(),
22 // ... a TX buffer becoming available, i.e. embassy-net wants to send a packet 24 // ... a TX buffer becoming available, i.e. embassy-net wants to send a packet
23 tx_chan.tx_buf(), 25 tx_chan.tx_buf(),
24 ).await { 26 ).await {
25 Either::First(_) => { 27 Either::First(_) => {
26 // a packet is ready to be received! 28 // a packet is ready to be received!
27 let buf = rx_chan.rx_buf().await; // allocate a rx buf from the packet queue 29 let buf = rx_chan.rx_buf().await; // allocate a rx buf from the packet queue
28 let n = receive_packet_over_spi(buf).await; 30 let n = receive_packet_over_spi(buf).await;
29 rx_chan.rx_done(n); 31 rx_chan.rx_done(n);
30 } 32 }
31 Either::Second(buf) => { 33 Either::Second(buf) => {
32 // a packet is ready to be sent! 34 // a packet is ready to be sent!
33 send_packet_over_spi(buf).await; 35 send_packet_over_spi(buf).await;
34 tx_chan.tx_done(); 36 tx_chan.tx_done();
35 } 37 }
36 } 38 }
@@ -41,7 +43,7 @@ However, this code has a latent deadlock bug. The symptom is it can hang at `rx_
41 43
42The reason is that, under load, both the TX and RX queues can get full at the same time. When this happens, the `embassy-net` task stalls trying to send because the TX queue is full, therefore it stops processing packets in the RX queue. Your driver task also stalls because the RX queue is full, therefore it stops processing packets in the TX queue. 44The reason is that, under load, both the TX and RX queues can get full at the same time. When this happens, the `embassy-net` task stalls trying to send because the TX queue is full, therefore it stops processing packets in the RX queue. Your driver task also stalls because the RX queue is full, therefore it stops processing packets in the TX queue.
43 45
44The fix is to make sure to always service the TX queue while you're waiting for space to become available in the TX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available": 46The fix is to make sure to always service the TX queue while you're waiting for space to become available in the RX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available":
45 47
46```rust,ignore 48```rust,ignore
47loop { 49loop {
@@ -58,12 +60,12 @@ loop {
58 ).await { 60 ).await {
59 Either::First(buf) => { 61 Either::First(buf) => {
60 // a packet is ready to be received! 62 // a packet is ready to be received!
61 let n = receive_packet_over_spi(buf).await; 63 let n = receive_packet_over_spi(buf).await;
62 rx_chan.rx_done(n); 64 rx_chan.rx_done(n);
63 } 65 }
64 Either::Second(buf) => { 66 Either::Second(buf) => {
65 // a packet is ready to be sent! 67 // a packet is ready to be sent!
66 send_packet_over_spi(buf).await; 68 send_packet_over_spi(buf).await;
67 tx_chan.tx_done(); 69 tx_chan.tx_done();
68 } 70 }
69 } 71 }
@@ -79,12 +81,10 @@ These `embassy-net` drivers are implemented using this crate. You can look at th
79- [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips. 81- [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips.
80- [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU. 82- [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU.
81 83
82
83## Interoperability 84## Interoperability
84 85
85This crate can run on any executor. 86This crate can run on any executor.
86 87
87
88## License 88## License
89 89
90This work is licensed under either of 90This work is licensed under either of
diff --git a/embassy-net-driver-channel/src/lib.rs b/embassy-net-driver-channel/src/lib.rs
index bf7ae5217..bfb2c9c03 100644
--- a/embassy-net-driver-channel/src/lib.rs
+++ b/embassy-net-driver-channel/src/lib.rs
@@ -8,9 +8,8 @@ use core::cell::RefCell;
8use core::mem::MaybeUninit; 8use core::mem::MaybeUninit;
9use core::task::{Context, Poll}; 9use core::task::{Context, Poll};
10 10
11use driver::HardwareAddress;
12pub use embassy_net_driver as driver; 11pub use embassy_net_driver as driver;
13use embassy_net_driver::{Capabilities, LinkState, Medium}; 12use embassy_net_driver::{Capabilities, LinkState};
14use embassy_sync::blocking_mutex::raw::NoopRawMutex; 13use embassy_sync::blocking_mutex::raw::NoopRawMutex;
15use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
16use embassy_sync::waitqueue::WakerRegistration; 15use embassy_sync::waitqueue::WakerRegistration;
@@ -161,18 +160,10 @@ impl<'d> StateRunner<'d> {
161 }); 160 });
162 } 161 }
163 162
164 pub fn set_ethernet_address(&self, address: [u8; 6]) { 163 pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
165 self.shared.lock(|s| { 164 self.shared.lock(|s| {
166 let s = &mut *s.borrow_mut(); 165 let s = &mut *s.borrow_mut();
167 s.hardware_address = driver::HardwareAddress::Ethernet(address); 166 s.hardware_address = address;
168 s.waker.wake();
169 });
170 }
171
172 pub fn set_ieee802154_address(&self, address: [u8; 8]) {
173 self.shared.lock(|s| {
174 let s = &mut *s.borrow_mut();
175 s.hardware_address = driver::HardwareAddress::Ieee802154(address);
176 s.waker.wake(); 167 s.waker.wake();
177 }); 168 });
178 } 169 }
@@ -232,11 +223,6 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
232) -> (Runner<'d, MTU>, Device<'d, MTU>) { 223) -> (Runner<'d, MTU>, Device<'d, MTU>) {
233 let mut caps = Capabilities::default(); 224 let mut caps = Capabilities::default();
234 caps.max_transmission_unit = MTU; 225 caps.max_transmission_unit = MTU;
235 caps.medium = match &hardware_address {
236 HardwareAddress::Ethernet(_) => Medium::Ethernet,
237 HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
238 HardwareAddress::Ip => Medium::Ip,
239 };
240 226
241 // safety: this is a self-referential struct, however: 227 // safety: this is a self-referential struct, however:
242 // - it can't move while the `'d` borrow is active. 228 // - it can't move while the `'d` borrow is active.
diff --git a/embassy-net-driver/CHANGELOG.md b/embassy-net-driver/CHANGELOG.md
new file mode 100644
index 000000000..165461eff
--- /dev/null
+++ b/embassy-net-driver/CHANGELOG.md
@@ -0,0 +1,17 @@
1# Changelog
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8## 0.2.0 - 2023-10-18
9
10- Added support for IEEE 802.15.4 mediums.
11- Added `Driver::hardware_address()`, `HardwareAddress`.
12- Removed `Medium` enum. The medium is deduced out of the hardware address.
13- Removed `Driver::ethernet_address()`. Replacement is `hardware_address()`.
14
15## 0.1.0 - 2023-06-29
16
17- First release
diff --git a/embassy-net-driver/Cargo.toml b/embassy-net-driver/Cargo.toml
index e25950b6b..9cd6a2eaa 100644
--- a/embassy-net-driver/Cargo.toml
+++ b/embassy-net-driver/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2name = "embassy-net-driver" 2name = "embassy-net-driver"
3version = "0.1.0" 3version = "0.2.0"
4edition = "2021" 4edition = "2021"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6description = "Driver trait for the `embassy-net` async TCP/IP network stack." 6description = "Driver trait for the `embassy-net` async TCP/IP network stack."
diff --git a/embassy-net-driver/src/lib.rs b/embassy-net-driver/src/lib.rs
index b64c10000..87f9f6ed1 100644
--- a/embassy-net-driver/src/lib.rs
+++ b/embassy-net-driver/src/lib.rs
@@ -7,12 +7,23 @@ use core::task::Context;
7/// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address. 7/// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)] 8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))] 9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10#[non_exhaustive]
10pub enum HardwareAddress { 11pub enum HardwareAddress {
11 /// A six-octet Ethernet address 12 /// Ethernet medium, with a A six-octet Ethernet address.
13 ///
14 /// Devices of this type send and receive Ethernet frames,
15 /// and interfaces using it must do neighbor discovery via ARP or NDISC.
16 ///
17 /// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
12 Ethernet([u8; 6]), 18 Ethernet([u8; 6]),
13 /// An eight-octet IEEE802.15.4 address 19 /// 6LoWPAN over IEEE802.15.4, with an eight-octet address.
14 Ieee802154([u8; 8]), 20 Ieee802154([u8; 8]),
15 /// Indicates that a Driver is IP-native, and has no hardware address 21 /// Indicates that a Driver is IP-native, and has no hardware address.
22 ///
23 /// Devices of this type send and receive IP frames, without an
24 /// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
25 ///
26 /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
16 Ip, 27 Ip,
17} 28}
18 29
@@ -64,6 +75,10 @@ pub trait Driver {
64 fn capabilities(&self) -> Capabilities; 75 fn capabilities(&self) -> Capabilities;
65 76
66 /// Get the device's hardware address. 77 /// Get the device's hardware address.
78 ///
79 /// The returned hardware address also determines the "medium" of this driver. This indicates
80 /// what kind of packet the sent/received bytes are, and determines some behaviors of
81 /// the interface. For example, ARP/NDISC address resolution is only done for Ethernet mediums.
67 fn hardware_address(&self) -> HardwareAddress; 82 fn hardware_address(&self) -> HardwareAddress;
68} 83}
69 84
@@ -124,13 +139,6 @@ pub trait TxToken {
124#[cfg_attr(feature = "defmt", derive(defmt::Format))] 139#[cfg_attr(feature = "defmt", derive(defmt::Format))]
125#[non_exhaustive] 140#[non_exhaustive]
126pub struct Capabilities { 141pub struct Capabilities {
127 /// Medium of the device.
128 ///
129 /// This indicates what kind of packet the sent/received bytes are, and determines
130 /// some behaviors of Interface. For example, ARP/NDISC address resolution is only done
131 /// for Ethernet mediums.
132 pub medium: Medium,
133
134 /// Maximum transmission unit. 142 /// Maximum transmission unit.
135 /// 143 ///
136 /// The network device is unable to send or receive frames larger than the value returned 144 /// The network device is unable to send or receive frames larger than the value returned
@@ -161,32 +169,6 @@ pub struct Capabilities {
161 pub checksum: ChecksumCapabilities, 169 pub checksum: ChecksumCapabilities,
162} 170}
163 171
164/// Type of medium of a device.
165#[derive(Debug, Eq, PartialEq, Copy, Clone)]
166#[cfg_attr(feature = "defmt", derive(defmt::Format))]
167pub enum Medium {
168 /// Ethernet medium. Devices of this type send and receive Ethernet frames,
169 /// and interfaces using it must do neighbor discovery via ARP or NDISC.
170 ///
171 /// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
172 Ethernet,
173
174 /// IP medium. Devices of this type send and receive IP frames, without an
175 /// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
176 ///
177 /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
178 Ip,
179
180 /// IEEE 802_15_4 medium
181 Ieee802154,
182}
183
184impl Default for Medium {
185 fn default() -> Medium {
186 Medium::Ethernet
187 }
188}
189
190/// A description of checksum behavior for every supported protocol. 172/// A description of checksum behavior for every supported protocol.
191#[derive(Debug, Clone, Default)] 173#[derive(Debug, Clone, Default)]
192#[cfg_attr(feature = "defmt", derive(defmt::Format))] 174#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-net-enc28j60/Cargo.toml b/embassy-net-enc28j60/Cargo.toml
index 161d055c0..ea2ed1f77 100644
--- a/embassy-net-enc28j60/Cargo.toml
+++ b/embassy-net-enc28j60/Cargo.toml
@@ -10,8 +10,8 @@ edition = "2021"
10[dependencies] 10[dependencies]
11embedded-hal = { version = "1.0.0-rc.1" } 11embedded-hal = { version = "1.0.0-rc.1" }
12embedded-hal-async = { version = "=1.0.0-rc.1" } 12embedded-hal-async = { version = "=1.0.0-rc.1" }
13embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 13embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
14embassy-time = { version = "0.1.3", path = "../embassy-time" } 14embassy-time = { version = "0.1.5", path = "../embassy-time" }
15embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 15embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
16 16
17defmt = { version = "0.3", optional = true } 17defmt = { version = "0.3", optional = true }
diff --git a/embassy-net-enc28j60/src/lib.rs b/embassy-net-enc28j60/src/lib.rs
index f96a6ff14..f18134927 100644
--- a/embassy-net-enc28j60/src/lib.rs
+++ b/embassy-net-enc28j60/src/lib.rs
@@ -19,7 +19,7 @@ mod traits;
19use core::cmp; 19use core::cmp;
20use core::convert::TryInto; 20use core::convert::TryInto;
21 21
22use embassy_net_driver::{Capabilities, HardwareAddress, LinkState, Medium}; 22use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
23use embassy_time::Duration; 23use embassy_time::Duration;
24use embedded_hal::digital::OutputPin; 24use embedded_hal::digital::OutputPin;
25use embedded_hal::spi::{Operation, SpiDevice}; 25use embedded_hal::spi::{Operation, SpiDevice};
@@ -671,7 +671,6 @@ where
671 fn capabilities(&self) -> Capabilities { 671 fn capabilities(&self) -> Capabilities {
672 let mut caps = Capabilities::default(); 672 let mut caps = Capabilities::default();
673 caps.max_transmission_unit = MTU; 673 caps.max_transmission_unit = MTU;
674 caps.medium = Medium::Ethernet;
675 caps 674 caps
676 } 675 }
677 676
diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml
index 54cd8859f..5f901bb91 100644
--- a/embassy-net-esp-hosted/Cargo.toml
+++ b/embassy-net-esp-hosted/Cargo.toml
@@ -7,10 +7,10 @@ edition = "2021"
7defmt = { version = "0.3", optional = true } 7defmt = { version = "0.3", optional = true }
8log = { version = "0.4.14", optional = true } 8log = { version = "0.4.14", optional = true }
9 9
10embassy-time = { version = "0.1.3", path = "../embassy-time" } 10embassy-time = { version = "0.1.5", path = "../embassy-time" }
11embassy-sync = { version = "0.3.0", path = "../embassy-sync"} 11embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
12embassy-futures = { version = "0.1.0", path = "../embassy-futures"} 12embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
13embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} 13embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"}
14 14
15embedded-hal = { version = "1.0.0-rc.1" } 15embedded-hal = { version = "1.0.0-rc.1" }
16embedded-hal-async = { version = "=1.0.0-rc.1" } 16embedded-hal-async = { version = "=1.0.0-rc.1" }
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index a4996b584..50030f431 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -1,5 +1,5 @@
1use ch::driver::LinkState;
2use embassy_net_driver_channel as ch; 1use embassy_net_driver_channel as ch;
2use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
3use heapless::String; 3use heapless::String;
4 4
5use crate::ioctl::Shared; 5use crate::ioctl::Shared;
@@ -77,7 +77,7 @@ impl<'a> Control<'a> {
77 77
78 let mac_addr = self.get_mac_addr().await?; 78 let mac_addr = self.get_mac_addr().await?;
79 debug!("mac addr: {:02x}", mac_addr); 79 debug!("mac addr: {:02x}", mac_addr);
80 self.state_ch.set_ethernet_address(mac_addr); 80 self.state_ch.set_hardware_address(HardwareAddress::Ethernet(mac_addr));
81 81
82 Ok(()) 82 Ok(())
83 } 83 }
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs
index 4a318b20d..d61eaef3a 100644
--- a/embassy-net-esp-hosted/src/lib.rs
+++ b/embassy-net-esp-hosted/src/lib.rs
@@ -169,9 +169,9 @@ where
169 pub async fn run(mut self) -> ! { 169 pub async fn run(mut self) -> ! {
170 debug!("resetting..."); 170 debug!("resetting...");
171 self.reset.set_low().unwrap(); 171 self.reset.set_low().unwrap();
172 Timer::after(Duration::from_millis(100)).await; 172 Timer::after_millis(100).await;
173 self.reset.set_high().unwrap(); 173 self.reset.set_high().unwrap();
174 Timer::after(Duration::from_millis(1000)).await; 174 Timer::after_millis(1000).await;
175 175
176 let mut tx_buf = [0u8; MAX_SPI_BUFFER_SIZE]; 176 let mut tx_buf = [0u8; MAX_SPI_BUFFER_SIZE];
177 let mut rx_buf = [0u8; MAX_SPI_BUFFER_SIZE]; 177 let mut rx_buf = [0u8; MAX_SPI_BUFFER_SIZE];
diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml
index da09f780e..bd992de06 100644
--- a/embassy-net-ppp/Cargo.toml
+++ b/embassy-net-ppp/Cargo.toml
@@ -15,8 +15,8 @@ log = ["dep:log", "ppproto/log"]
15defmt = { version = "0.3", optional = true } 15defmt = { version = "0.3", optional = true }
16log = { version = "0.4.14", optional = true } 16log = { version = "0.4.14", optional = true }
17 17
18embedded-io-async = { version = "0.5.0" } 18embedded-io-async = { version = "0.6.0" }
19embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } 19embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
20embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 20embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
21ppproto = { version = "0.1.2"} 21ppproto = { version = "0.1.2"}
22embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 22embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
diff --git a/embassy-net-ppp/src/lib.rs b/embassy-net-ppp/src/lib.rs
index 66496ee0a..54a98c95f 100644
--- a/embassy-net-ppp/src/lib.rs
+++ b/embassy-net-ppp/src/lib.rs
@@ -11,7 +11,7 @@ use core::mem::MaybeUninit;
11use embassy_futures::select::{select, Either}; 11use embassy_futures::select::{select, Either};
12use embassy_net_driver_channel as ch; 12use embassy_net_driver_channel as ch;
13use embassy_net_driver_channel::driver::LinkState; 13use embassy_net_driver_channel::driver::LinkState;
14use embedded_io_async::{BufRead, Write, WriteAllError}; 14use embedded_io_async::{BufRead, Write};
15use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction}; 15use ppproto::pppos::{BufferFullError, PPPoS, PPPoSAction};
16pub use ppproto::{Config, Ipv4Status}; 16pub use ppproto::{Config, Ipv4Status};
17 17
@@ -49,23 +49,12 @@ pub enum RunError<E> {
49 Read(E), 49 Read(E),
50 /// Writing to the serial port failed. 50 /// Writing to the serial port failed.
51 Write(E), 51 Write(E),
52 /// Writing to the serial port wrote zero bytes, indicating it can't accept more data.
53 WriteZero,
54 /// Writing to the serial got EOF. 52 /// Writing to the serial got EOF.
55 Eof, 53 Eof,
56 /// PPP protocol was terminated by the peer 54 /// PPP protocol was terminated by the peer
57 Terminated, 55 Terminated,
58} 56}
59 57
60impl<E> From<WriteAllError<E>> for RunError<E> {
61 fn from(value: WriteAllError<E>) -> Self {
62 match value {
63 WriteAllError::Other(e) => Self::Write(e),
64 WriteAllError::WriteZero => Self::WriteZero,
65 }
66 }
67}
68
69impl<'d> Runner<'d> { 58impl<'d> Runner<'d> {
70 /// You must call this in a background task for the driver to operate. 59 /// You must call this in a background task for the driver to operate.
71 /// 60 ///
@@ -125,7 +114,7 @@ impl<'d> Runner<'d> {
125 buf[..pkt.len()].copy_from_slice(pkt); 114 buf[..pkt.len()].copy_from_slice(pkt);
126 rx_chan.rx_done(pkt.len()); 115 rx_chan.rx_done(pkt.len());
127 } 116 }
128 PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await?, 117 PPPoSAction::Transmit(n) => rw.write_all(&tx_buf[..n]).await.map_err(RunError::Write)?,
129 } 118 }
130 119
131 let status = ppp.status(); 120 let status = ppp.status();
@@ -148,7 +137,7 @@ impl<'d> Runner<'d> {
148 } 137 }
149 Either::Second(pkt) => { 138 Either::Second(pkt) => {
150 match ppp.send(pkt, &mut tx_buf) { 139 match ppp.send(pkt, &mut tx_buf) {
151 Ok(n) => rw.write_all(&tx_buf[..n]).await?, 140 Ok(n) => rw.write_all(&tx_buf[..n]).await.map_err(RunError::Write)?,
152 Err(BufferFullError) => unreachable!(), 141 Err(BufferFullError) => unreachable!(),
153 } 142 }
154 tx_chan.tx_done(); 143 tx_chan.tx_done();
diff --git a/embassy-net-tuntap/Cargo.toml b/embassy-net-tuntap/Cargo.toml
index 08d309680..4e374c365 100644
--- a/embassy-net-tuntap/Cargo.toml
+++ b/embassy-net-tuntap/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8edition = "2021" 8edition = "2021"
9 9
10[dependencies] 10[dependencies]
11embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 11embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
12async-io = "1.6.0" 12async-io = "1.6.0"
13log = "0.4.14" 13log = "0.4.14"
14libc = "0.2.101" 14libc = "0.2.101"
diff --git a/embassy-net-wiznet/Cargo.toml b/embassy-net-wiznet/Cargo.toml
index afa0d5cd5..0cc086b7e 100644
--- a/embassy-net-wiznet/Cargo.toml
+++ b/embassy-net-wiznet/Cargo.toml
@@ -10,8 +10,8 @@ edition = "2021"
10[dependencies] 10[dependencies]
11embedded-hal = { version = "1.0.0-rc.1" } 11embedded-hal = { version = "1.0.0-rc.1" }
12embedded-hal-async = { version = "=1.0.0-rc.1" } 12embedded-hal-async = { version = "=1.0.0-rc.1" }
13embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } 13embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
14embassy-time = { version = "0.1.3", path = "../embassy-time" } 14embassy-time = { version = "0.1.5", path = "../embassy-time" }
15embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 15embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
16defmt = { version = "0.3", optional = true } 16defmt = { version = "0.3", optional = true }
17 17
diff --git a/embassy-net-wiznet/src/lib.rs b/embassy-net-wiznet/src/lib.rs
index 3030dfb90..afdb6729c 100644
--- a/embassy-net-wiznet/src/lib.rs
+++ b/embassy-net-wiznet/src/lib.rs
@@ -1,14 +1,14 @@
1//! [`embassy-net`](https://crates.io/crates/embassy-net) driver for WIZnet ethernet chips.
2#![no_std] 1#![no_std]
3#![feature(async_fn_in_trait)] 2#![feature(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4 4
5pub mod chip; 5pub mod chip;
6mod device; 6mod device;
7 7
8use embassy_futures::select::{select, Either}; 8use embassy_futures::select::{select3, Either3};
9use embassy_net_driver_channel as ch; 9use embassy_net_driver_channel as ch;
10use embassy_net_driver_channel::driver::LinkState; 10use embassy_net_driver_channel::driver::LinkState;
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Ticker, Timer};
12use embedded_hal::digital::OutputPin; 12use embedded_hal::digital::OutputPin;
13use embedded_hal_async::digital::Wait; 13use embedded_hal_async::digital::Wait;
14use embedded_hal_async::spi::SpiDevice; 14use embedded_hal_async::spi::SpiDevice;
@@ -49,32 +49,34 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
49impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> { 49impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
50 pub async fn run(mut self) -> ! { 50 pub async fn run(mut self) -> ! {
51 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); 51 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
52 let mut tick = Ticker::every(Duration::from_millis(500));
52 loop { 53 loop {
53 if self.mac.is_link_up().await { 54 match select3(
54 state_chan.set_link_state(LinkState::Up); 55 async {
55 loop { 56 self.int.wait_for_low().await.ok();
56 match select( 57 rx_chan.rx_buf().await
57 async { 58 },
58 self.int.wait_for_low().await.ok(); 59 tx_chan.tx_buf(),
59 rx_chan.rx_buf().await 60 tick.next(),
60 }, 61 )
61 tx_chan.tx_buf(), 62 .await
62 ) 63 {
63 .await 64 Either3::First(p) => {
64 { 65 if let Ok(n) = self.mac.read_frame(p).await {
65 Either::First(p) => { 66 rx_chan.rx_done(n);
66 if let Ok(n) = self.mac.read_frame(p).await { 67 }
67 rx_chan.rx_done(n); 68 }
68 } 69 Either3::Second(p) => {
69 } 70 self.mac.write_frame(p).await.ok();
70 Either::Second(p) => { 71 tx_chan.tx_done();
71 self.mac.write_frame(p).await.ok(); 72 }
72 tx_chan.tx_done(); 73 Either3::Third(()) => {
73 } 74 if self.mac.is_link_up().await {
75 state_chan.set_link_state(LinkState::Up);
76 } else {
77 state_chan.set_link_state(LinkState::Down);
74 } 78 }
75 } 79 }
76 } else {
77 state_chan.set_link_state(LinkState::Down);
78 } 80 }
79 } 81 }
80 } 82 }
@@ -95,12 +97,12 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
95 // Reset the chip. 97 // Reset the chip.
96 reset.set_low().ok(); 98 reset.set_low().ok();
97 // Ensure the reset is registered. 99 // Ensure the reset is registered.
98 Timer::after(Duration::from_millis(1)).await; 100 Timer::after_millis(1).await;
99 reset.set_high().ok(); 101 reset.set_high().ok();
100 102
101 // Wait for PLL lock. Some chips are slower than others. 103 // Wait for PLL lock. Some chips are slower than others.
102 // Slowest is w5100s which is 100ms, so let's just wait that. 104 // Slowest is w5100s which is 100ms, so let's just wait that.
103 Timer::after(Duration::from_millis(100)).await; 105 Timer::after_millis(100).await;
104 106
105 let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap(); 107 let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap();
106 108
diff --git a/embassy-net/CHANGELOG.md b/embassy-net/CHANGELOG.md
new file mode 100644
index 000000000..7b91b844b
--- /dev/null
+++ b/embassy-net/CHANGELOG.md
@@ -0,0 +1,29 @@
1# Changelog
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8## 0.2.0 - 2023-10-18
9
10- Re-export `smoltcp::wire::IpEndpoint`
11- Add poll functions on UdpSocket
12- Make dual-stack work in embassy-net
13- Fix multicast support
14- Allow ethernet and 802.15.4 to coexist
15- Add IEEE802.15.4 address to embassy net Stack
16- Use HardwareAddress in Driver
17- Add async versions of smoltcp's `send` and `recv` closure based API
18- add error translation to tcp errors
19- Forward TCP/UDP socket capacity impls
20- allow changing IP config at runtime
21- allow non-'static drivers
22- Remove impl_trait_projections
23- update embedded-io, embedded-nal-async
24- add support for dhcp hostname option
25- Wake stack's task after queueing a DNS query
26
27## 0.1.0 - 2023-06-29
28
29- First release
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 8aca92a68..573d20fb7 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2name = "embassy-net" 2name = "embassy-net"
3version = "0.1.0" 3version = "0.2.0"
4edition = "2021" 4edition = "2021"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6description = "Async TCP/IP network stack for embedded systems" 6description = "Async TCP/IP network stack for embedded systems"
@@ -33,6 +33,7 @@ udp = ["smoltcp/socket-udp"]
33tcp = ["smoltcp/socket-tcp"] 33tcp = ["smoltcp/socket-tcp"]
34dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] 34dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"]
35dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"] 35dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"]
36dhcpv4-hostname = ["dhcpv4"]
36proto-ipv4 = ["smoltcp/proto-ipv4"] 37proto-ipv4 = ["smoltcp/proto-ipv4"]
37proto-ipv6 = ["smoltcp/proto-ipv6"] 38proto-ipv6 = ["smoltcp/proto-ipv6"]
38medium-ethernet = ["smoltcp/medium-ethernet"] 39medium-ethernet = ["smoltcp/medium-ethernet"]
@@ -50,10 +51,10 @@ smoltcp = { version = "0.10.0", default-features = false, features = [
50 "async", 51 "async",
51] } 52] }
52 53
53embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 54embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
54embassy-time = { version = "0.1.3", path = "../embassy-time" } 55embassy-time = { version = "0.1.5", path = "../embassy-time" }
55embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 56embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
56embedded-io-async = { version = "0.5.0", optional = true } 57embedded-io-async = { version = "0.6.0", optional = true }
57 58
58managed = { version = "0.8.0", default-features = false, features = [ "map" ] } 59managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
59heapless = { version = "0.7.5", default-features = false } 60heapless = { version = "0.7.5", default-features = false }
@@ -62,5 +63,4 @@ generic-array = { version = "0.14.4", default-features = false }
62stable_deref_trait = { version = "1.2.0", default-features = false } 63stable_deref_trait = { version = "1.2.0", default-features = false }
63futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } 64futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
64atomic-pool = "1.0" 65atomic-pool = "1.0"
65embedded-nal-async = { version = "0.5.0", optional = true } 66embedded-nal-async = { version = "0.6.0", optional = true }
66atomic-polyfill = { version = "1.0" }
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs
index 8c2b7d31a..54a0c47e8 100644
--- a/embassy-net/src/device.rs
+++ b/embassy-net/src/device.rs
@@ -1,7 +1,7 @@
1use core::task::Context; 1use core::task::Context;
2 2
3use embassy_net_driver::{Capabilities, Checksum, Driver, Medium, RxToken, TxToken}; 3use embassy_net_driver::{Capabilities, Checksum, Driver, RxToken, TxToken};
4use smoltcp::phy; 4use smoltcp::phy::{self, Medium};
5use smoltcp::time::Instant; 5use smoltcp::time::Instant;
6 6
7pub(crate) struct DriverAdapter<'d, 'c, T> 7pub(crate) struct DriverAdapter<'d, 'c, T>
@@ -11,6 +11,7 @@ where
11 // must be Some when actually using this to rx/tx 11 // must be Some when actually using this to rx/tx
12 pub cx: Option<&'d mut Context<'c>>, 12 pub cx: Option<&'d mut Context<'c>>,
13 pub inner: &'d mut T, 13 pub inner: &'d mut T,
14 pub medium: Medium,
14} 15}
15 16
16impl<'d, 'c, T> phy::Device for DriverAdapter<'d, 'c, T> 17impl<'d, 'c, T> phy::Device for DriverAdapter<'d, 'c, T>
@@ -46,19 +47,7 @@ where
46 47
47 smolcaps.max_transmission_unit = caps.max_transmission_unit; 48 smolcaps.max_transmission_unit = caps.max_transmission_unit;
48 smolcaps.max_burst_size = caps.max_burst_size; 49 smolcaps.max_burst_size = caps.max_burst_size;
49 smolcaps.medium = match caps.medium { 50 smolcaps.medium = self.medium;
50 #[cfg(feature = "medium-ethernet")]
51 Medium::Ethernet => phy::Medium::Ethernet,
52 #[cfg(feature = "medium-ip")]
53 Medium::Ip => phy::Medium::Ip,
54 #[cfg(feature = "medium-ieee802154")]
55 Medium::Ieee802154 => phy::Medium::Ieee802154,
56 #[allow(unreachable_patterns)]
57 _ => panic!(
58 "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
59 caps.medium
60 ),
61 };
62 smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4); 51 smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4);
63 smolcaps.checksum.tcp = convert(caps.checksum.tcp); 52 smolcaps.checksum.tcp = convert(caps.checksum.tcp);
64 smolcaps.checksum.udp = convert(caps.checksum.udp); 53 smolcaps.checksum.udp = convert(caps.checksum.udp);
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index 0d7ac47a2..c41faee2f 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -1,5 +1,5 @@
1#![cfg_attr(not(feature = "std"), no_std)] 1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4#![doc = include_str!("../README.md")] 4#![doc = include_str!("../README.md")]
5 5
@@ -33,13 +33,14 @@ use heapless::Vec;
33pub use smoltcp::iface::MulticastError; 33pub use smoltcp::iface::MulticastError;
34#[allow(unused_imports)] 34#[allow(unused_imports)]
35use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; 35use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
36use smoltcp::phy::Medium;
36#[cfg(feature = "dhcpv4")] 37#[cfg(feature = "dhcpv4")]
37use smoltcp::socket::dhcpv4::{self, RetryConfig}; 38use smoltcp::socket::dhcpv4::{self, RetryConfig};
38#[cfg(feature = "medium-ethernet")] 39#[cfg(feature = "medium-ethernet")]
39pub use smoltcp::wire::EthernetAddress; 40pub use smoltcp::wire::EthernetAddress;
40#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154", feature = "medium-ip"))] 41#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154", feature = "medium-ip"))]
41pub use smoltcp::wire::HardwareAddress; 42pub use smoltcp::wire::HardwareAddress;
42#[cfg(feature = "udp")] 43#[cfg(any(feature = "udp", feature = "tcp"))]
43pub use smoltcp::wire::IpListenEndpoint; 44pub use smoltcp::wire::IpListenEndpoint;
44#[cfg(feature = "medium-ieee802154")] 45#[cfg(feature = "medium-ieee802154")]
45pub use smoltcp::wire::{Ieee802154Address, Ieee802154Frame}; 46pub use smoltcp::wire::{Ieee802154Address, Ieee802154Frame};
@@ -56,12 +57,22 @@ const LOCAL_PORT_MIN: u16 = 1025;
56const LOCAL_PORT_MAX: u16 = 65535; 57const LOCAL_PORT_MAX: u16 = 65535;
57#[cfg(feature = "dns")] 58#[cfg(feature = "dns")]
58const MAX_QUERIES: usize = 4; 59const MAX_QUERIES: usize = 4;
60#[cfg(feature = "dhcpv4-hostname")]
61const MAX_HOSTNAME_LEN: usize = 32;
59 62
60/// Memory resources needed for a network stack. 63/// Memory resources needed for a network stack.
61pub struct StackResources<const SOCK: usize> { 64pub struct StackResources<const SOCK: usize> {
62 sockets: [SocketStorage<'static>; SOCK], 65 sockets: [SocketStorage<'static>; SOCK],
63 #[cfg(feature = "dns")] 66 #[cfg(feature = "dns")]
64 queries: [Option<dns::DnsQuery>; MAX_QUERIES], 67 queries: [Option<dns::DnsQuery>; MAX_QUERIES],
68 #[cfg(feature = "dhcpv4-hostname")]
69 hostname: core::cell::UnsafeCell<HostnameResources>,
70}
71
72#[cfg(feature = "dhcpv4-hostname")]
73struct HostnameResources {
74 option: smoltcp::wire::DhcpOption<'static>,
75 data: [u8; MAX_HOSTNAME_LEN],
65} 76}
66 77
67impl<const SOCK: usize> StackResources<SOCK> { 78impl<const SOCK: usize> StackResources<SOCK> {
@@ -73,6 +84,11 @@ impl<const SOCK: usize> StackResources<SOCK> {
73 sockets: [SocketStorage::EMPTY; SOCK], 84 sockets: [SocketStorage::EMPTY; SOCK],
74 #[cfg(feature = "dns")] 85 #[cfg(feature = "dns")]
75 queries: [INIT; MAX_QUERIES], 86 queries: [INIT; MAX_QUERIES],
87 #[cfg(feature = "dhcpv4-hostname")]
88 hostname: core::cell::UnsafeCell::new(HostnameResources {
89 option: smoltcp::wire::DhcpOption { kind: 0, data: &[] },
90 data: [0; MAX_HOSTNAME_LEN],
91 }),
76 } 92 }
77 } 93 }
78} 94}
@@ -104,6 +120,7 @@ pub struct StaticConfigV6 {
104/// DHCP configuration. 120/// DHCP configuration.
105#[cfg(feature = "dhcpv4")] 121#[cfg(feature = "dhcpv4")]
106#[derive(Debug, Clone, PartialEq, Eq)] 122#[derive(Debug, Clone, PartialEq, Eq)]
123#[non_exhaustive]
107pub struct DhcpConfig { 124pub struct DhcpConfig {
108 /// Maximum lease duration. 125 /// Maximum lease duration.
109 /// 126 ///
@@ -120,6 +137,9 @@ pub struct DhcpConfig {
120 pub server_port: u16, 137 pub server_port: u16,
121 /// Client port. This is almost always 68. Do not change unless you know what you're doing. 138 /// Client port. This is almost always 68. Do not change unless you know what you're doing.
122 pub client_port: u16, 139 pub client_port: u16,
140 /// Our hostname. This will be sent to the DHCP server as Option 12.
141 #[cfg(feature = "dhcpv4-hostname")]
142 pub hostname: Option<heapless::String<MAX_HOSTNAME_LEN>>,
123} 143}
124 144
125#[cfg(feature = "dhcpv4")] 145#[cfg(feature = "dhcpv4")]
@@ -131,6 +151,8 @@ impl Default for DhcpConfig {
131 ignore_naks: Default::default(), 151 ignore_naks: Default::default(),
132 server_port: smoltcp::wire::DHCP_SERVER_PORT, 152 server_port: smoltcp::wire::DHCP_SERVER_PORT,
133 client_port: smoltcp::wire::DHCP_CLIENT_PORT, 153 client_port: smoltcp::wire::DHCP_CLIENT_PORT,
154 #[cfg(feature = "dhcpv4-hostname")]
155 hostname: None,
134 } 156 }
135 } 157 }
136} 158}
@@ -232,6 +254,8 @@ struct Inner<D: Driver> {
232 dns_socket: SocketHandle, 254 dns_socket: SocketHandle,
233 #[cfg(feature = "dns")] 255 #[cfg(feature = "dns")]
234 dns_waker: WakerRegistration, 256 dns_waker: WakerRegistration,
257 #[cfg(feature = "dhcpv4-hostname")]
258 hostname: &'static mut core::cell::UnsafeCell<HostnameResources>,
235} 259}
236 260
237pub(crate) struct SocketStack { 261pub(crate) struct SocketStack {
@@ -241,14 +265,17 @@ pub(crate) struct SocketStack {
241 next_local_port: u16, 265 next_local_port: u16,
242} 266}
243 267
244fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> HardwareAddress { 268fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> (HardwareAddress, Medium) {
245 match addr { 269 match addr {
246 #[cfg(feature = "medium-ethernet")] 270 #[cfg(feature = "medium-ethernet")]
247 driver::HardwareAddress::Ethernet(eth) => HardwareAddress::Ethernet(EthernetAddress(eth)), 271 driver::HardwareAddress::Ethernet(eth) => (HardwareAddress::Ethernet(EthernetAddress(eth)), Medium::Ethernet),
248 #[cfg(feature = "medium-ieee802154")] 272 #[cfg(feature = "medium-ieee802154")]
249 driver::HardwareAddress::Ieee802154(ieee) => HardwareAddress::Ieee802154(Ieee802154Address::Extended(ieee)), 273 driver::HardwareAddress::Ieee802154(ieee) => (
274 HardwareAddress::Ieee802154(Ieee802154Address::Extended(ieee)),
275 Medium::Ieee802154,
276 ),
250 #[cfg(feature = "medium-ip")] 277 #[cfg(feature = "medium-ip")]
251 driver::HardwareAddress::Ip => HardwareAddress::Ip, 278 driver::HardwareAddress::Ip => (HardwareAddress::Ip, Medium::Ip),
252 279
253 #[allow(unreachable_patterns)] 280 #[allow(unreachable_patterns)]
254 _ => panic!( 281 _ => panic!(
@@ -266,7 +293,8 @@ impl<D: Driver> Stack<D> {
266 resources: &'static mut StackResources<SOCK>, 293 resources: &'static mut StackResources<SOCK>,
267 random_seed: u64, 294 random_seed: u64,
268 ) -> Self { 295 ) -> Self {
269 let mut iface_cfg = smoltcp::iface::Config::new(to_smoltcp_hardware_address(device.hardware_address())); 296 let (hardware_addr, medium) = to_smoltcp_hardware_address(device.hardware_address());
297 let mut iface_cfg = smoltcp::iface::Config::new(hardware_addr);
270 iface_cfg.random_seed = random_seed; 298 iface_cfg.random_seed = random_seed;
271 299
272 let iface = Interface::new( 300 let iface = Interface::new(
@@ -274,6 +302,7 @@ impl<D: Driver> Stack<D> {
274 &mut DriverAdapter { 302 &mut DriverAdapter {
275 inner: &mut device, 303 inner: &mut device,
276 cx: None, 304 cx: None,
305 medium,
277 }, 306 },
278 instant_to_smoltcp(Instant::now()), 307 instant_to_smoltcp(Instant::now()),
279 ); 308 );
@@ -307,6 +336,8 @@ impl<D: Driver> Stack<D> {
307 )), 336 )),
308 #[cfg(feature = "dns")] 337 #[cfg(feature = "dns")]
309 dns_waker: WakerRegistration::new(), 338 dns_waker: WakerRegistration::new(),
339 #[cfg(feature = "dhcpv4-hostname")]
340 hostname: &mut resources.hostname,
310 }; 341 };
311 342
312 #[cfg(feature = "proto-ipv4")] 343 #[cfg(feature = "proto-ipv4")]
@@ -331,7 +362,7 @@ impl<D: Driver> Stack<D> {
331 362
332 /// Get the hardware address of the network interface. 363 /// Get the hardware address of the network interface.
333 pub fn hardware_address(&self) -> HardwareAddress { 364 pub fn hardware_address(&self) -> HardwareAddress {
334 self.with(|_s, i| to_smoltcp_hardware_address(i.device.hardware_address())) 365 self.with(|_s, i| to_smoltcp_hardware_address(i.device.hardware_address()).0)
335 } 366 }
336 367
337 /// Get whether the link is up. 368 /// Get whether the link is up.
@@ -484,7 +515,10 @@ impl<D: Driver> Stack<D> {
484 self.with_mut(|s, i| { 515 self.with_mut(|s, i| {
485 let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket); 516 let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket);
486 match socket.start_query(s.iface.context(), name, qtype) { 517 match socket.start_query(s.iface.context(), name, qtype) {
487 Ok(handle) => Poll::Ready(Ok(handle)), 518 Ok(handle) => {
519 s.waker.wake();
520 Poll::Ready(Ok(handle))
521 }
488 Err(dns::StartQueryError::NoFreeSlot) => { 522 Err(dns::StartQueryError::NoFreeSlot) => {
489 i.dns_waker.register(cx.waker()); 523 i.dns_waker.register(cx.waker());
490 Poll::Pending 524 Poll::Pending
@@ -673,6 +707,25 @@ impl<D: Driver> Inner<D> {
673 socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); 707 socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp));
674 socket.set_ports(c.server_port, c.client_port); 708 socket.set_ports(c.server_port, c.client_port);
675 socket.set_retry_config(c.retry_config); 709 socket.set_retry_config(c.retry_config);
710
711 socket.set_outgoing_options(&[]);
712 #[cfg(feature = "dhcpv4-hostname")]
713 if let Some(h) = c.hostname {
714 // safety: we just did set_outgoing_options([]) so we know the socket is no longer holding a reference.
715 let hostname = unsafe { &mut *self.hostname.get() };
716
717 // create data
718 // safety: we know the buffer lives forever, new borrows the StackResources for 'static.
719 // also we won't modify it until next call to this function.
720 hostname.data[..h.len()].copy_from_slice(h.as_bytes());
721 let data: &[u8] = &hostname.data[..h.len()];
722 let data: &'static [u8] = unsafe { core::mem::transmute(data) };
723
724 // set the option.
725 hostname.option = smoltcp::wire::DhcpOption { data, kind: 12 };
726 socket.set_outgoing_options(core::slice::from_ref(&hostname.option));
727 }
728
676 socket.reset(); 729 socket.reset();
677 } 730 }
678 _ => { 731 _ => {
@@ -765,18 +818,28 @@ impl<D: Driver> Inner<D> {
765 fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { 818 fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) {
766 s.waker.register(cx.waker()); 819 s.waker.register(cx.waker());
767 820
821 let (_hardware_addr, medium) = to_smoltcp_hardware_address(self.device.hardware_address());
822
768 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] 823 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
769 if self.device.capabilities().medium == embassy_net_driver::Medium::Ethernet
770 || self.device.capabilities().medium == embassy_net_driver::Medium::Ieee802154
771 { 824 {
772 s.iface 825 let do_set = match medium {
773 .set_hardware_addr(to_smoltcp_hardware_address(self.device.hardware_address())); 826 #[cfg(feature = "medium-ethernet")]
827 Medium::Ethernet => true,
828 #[cfg(feature = "medium-ieee802154")]
829 Medium::Ieee802154 => true,
830 #[allow(unreachable_patterns)]
831 _ => false,
832 };
833 if do_set {
834 s.iface.set_hardware_addr(_hardware_addr);
835 }
774 } 836 }
775 837
776 let timestamp = instant_to_smoltcp(Instant::now()); 838 let timestamp = instant_to_smoltcp(Instant::now());
777 let mut smoldev = DriverAdapter { 839 let mut smoldev = DriverAdapter {
778 cx: Some(cx), 840 cx: Some(cx),
779 inner: &mut self.device, 841 inner: &mut self.device,
842 medium,
780 }; 843 };
781 s.iface.poll(timestamp, &mut smoldev, &mut s.sockets); 844 s.iface.poll(timestamp, &mut smoldev, &mut s.sockets);
782 845
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index a12fd382a..b5615cb66 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -579,11 +579,10 @@ mod embedded_io_impls {
579/// TCP client compatible with `embedded-nal-async` traits. 579/// TCP client compatible with `embedded-nal-async` traits.
580#[cfg(feature = "nightly")] 580#[cfg(feature = "nightly")]
581pub mod client { 581pub mod client {
582 use core::cell::UnsafeCell; 582 use core::cell::{Cell, UnsafeCell};
583 use core::mem::MaybeUninit; 583 use core::mem::MaybeUninit;
584 use core::ptr::NonNull; 584 use core::ptr::NonNull;
585 585
586 use atomic_polyfill::{AtomicBool, Ordering};
587 use embedded_nal_async::IpAddr; 586 use embedded_nal_async::IpAddr;
588 587
589 use super::*; 588 use super::*;
@@ -702,15 +701,13 @@ pub mod client {
702 } 701 }
703 } 702 }
704 703
705 unsafe impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> Sync for TcpClientState<N, TX_SZ, RX_SZ> {}
706
707 struct Pool<T, const N: usize> { 704 struct Pool<T, const N: usize> {
708 used: [AtomicBool; N], 705 used: [Cell<bool>; N],
709 data: [UnsafeCell<MaybeUninit<T>>; N], 706 data: [UnsafeCell<MaybeUninit<T>>; N],
710 } 707 }
711 708
712 impl<T, const N: usize> Pool<T, N> { 709 impl<T, const N: usize> Pool<T, N> {
713 const VALUE: AtomicBool = AtomicBool::new(false); 710 const VALUE: Cell<bool> = Cell::new(false);
714 const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit()); 711 const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
715 712
716 const fn new() -> Self { 713 const fn new() -> Self {
@@ -724,7 +721,9 @@ pub mod client {
724 impl<T, const N: usize> Pool<T, N> { 721 impl<T, const N: usize> Pool<T, N> {
725 fn alloc(&self) -> Option<NonNull<T>> { 722 fn alloc(&self) -> Option<NonNull<T>> {
726 for n in 0..N { 723 for n in 0..N {
727 if self.used[n].swap(true, Ordering::SeqCst) == false { 724 // this can't race because Pool is not Sync.
725 if !self.used[n].get() {
726 self.used[n].set(true);
728 let p = self.data[n].get() as *mut T; 727 let p = self.data[n].get() as *mut T;
729 return Some(unsafe { NonNull::new_unchecked(p) }); 728 return Some(unsafe { NonNull::new_unchecked(p) });
730 } 729 }
@@ -738,7 +737,7 @@ pub mod client {
738 let n = p.as_ptr().offset_from(origin); 737 let n = p.as_ptr().offset_from(origin);
739 assert!(n >= 0); 738 assert!(n >= 0);
740 assert!((n as usize) < N); 739 assert!((n as usize) < N);
741 self.used[n as usize].store(false, Ordering::SeqCst); 740 self.used[n as usize].set(false);
742 } 741 }
743 } 742 }
744} 743}
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 3c706b473..360f77c19 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -94,7 +94,7 @@ _gpio-p1 = []
94_nrf52832_anomaly_109 = [] 94_nrf52832_anomaly_109 = []
95 95
96[dependencies] 96[dependencies]
97embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 97embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
98embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 98embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
99embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } 99embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] }
100embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 100embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
@@ -103,8 +103,8 @@ embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optiona
103embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 103embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
104embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} 104embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true}
105embedded-hal-async = { version = "=1.0.0-rc.1", optional = true} 105embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
106embedded-io = { version = "0.5.0" } 106embedded-io = { version = "0.6.0" }
107embedded-io-async = { version = "0.5.0", optional = true } 107embedded-io-async = { version = "0.6.0", optional = true }
108 108
109defmt = { version = "0.3", optional = true } 109defmt = { version = "0.3", optional = true }
110log = { version = "0.4.14", optional = true } 110log = { version = "0.4.14", optional = true }
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index afc2c4a7e..5e9a8ed05 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -6,10 +6,13 @@ pub mod pac {
6 // To avoid cfg spam, we remove _ns or _s suffixes here. 6 // To avoid cfg spam, we remove _ns or _s suffixes here.
7 7
8 pub use nrf5340_app_pac::NVIC_PRIO_BITS; 8 pub use nrf5340_app_pac::NVIC_PRIO_BITS;
9 9
10 #[cfg(feature="rt")]
11 #[doc(no_inline)]
12 pub use nrf5340_app_pac::interrupt;
13
10 #[doc(no_inline)] 14 #[doc(no_inline)]
11 pub use nrf5340_app_pac::{ 15 pub use nrf5340_app_pac::{
12 interrupt,
13 Interrupt, 16 Interrupt,
14 Peripherals, 17 Peripherals,
15 18
@@ -60,156 +63,167 @@ pub mod pac {
60 wdt0_ns as wdt0, 63 wdt0_ns as wdt0,
61 }; 64 };
62 65
63 #[cfg(feature = "nrf5340-app-ns")] 66 /// Non-Secure mode (NS) peripherals
64 #[doc(no_inline)] 67 pub mod ns {
65 pub use nrf5340_app_pac::{ 68 #[cfg(feature = "nrf5340-app-ns")]
66 CLOCK_NS as CLOCK, 69 #[doc(no_inline)]
67 COMP_NS as COMP, 70 pub use nrf5340_app_pac::{
68 CTRLAP_NS as CTRLAP, 71 CLOCK_NS as CLOCK,
69 DCNF_NS as DCNF, 72 COMP_NS as COMP,
70 DPPIC_NS as DPPIC, 73 CTRLAP_NS as CTRLAP,
71 EGU0_NS as EGU0, 74 DCNF_NS as DCNF,
72 EGU1_NS as EGU1, 75 DPPIC_NS as DPPIC,
73 EGU2_NS as EGU2, 76 EGU0_NS as EGU0,
74 EGU3_NS as EGU3, 77 EGU1_NS as EGU1,
75 EGU4_NS as EGU4, 78 EGU2_NS as EGU2,
76 EGU5_NS as EGU5, 79 EGU3_NS as EGU3,
77 FPU_NS as FPU, 80 EGU4_NS as EGU4,
78 GPIOTE1_NS as GPIOTE1, 81 EGU5_NS as EGU5,
79 I2S0_NS as I2S0, 82 FPU_NS as FPU,
80 IPC_NS as IPC, 83 GPIOTE1_NS as GPIOTE1,
81 KMU_NS as KMU, 84 I2S0_NS as I2S0,
82 LPCOMP_NS as LPCOMP, 85 IPC_NS as IPC,
83 MUTEX_NS as MUTEX, 86 KMU_NS as KMU,
84 NFCT_NS as NFCT, 87 LPCOMP_NS as LPCOMP,
85 NVMC_NS as NVMC, 88 MUTEX_NS as MUTEX,
86 OSCILLATORS_NS as OSCILLATORS, 89 NFCT_NS as NFCT,
87 P0_NS as P0, 90 NVMC_NS as NVMC,
88 P1_NS as P1, 91 OSCILLATORS_NS as OSCILLATORS,
89 PDM0_NS as PDM0, 92 P0_NS as P0,
90 POWER_NS as POWER, 93 P1_NS as P1,
91 PWM0_NS as PWM0, 94 PDM0_NS as PDM0,
92 PWM1_NS as PWM1, 95 POWER_NS as POWER,
93 PWM2_NS as PWM2, 96 PWM0_NS as PWM0,
94 PWM3_NS as PWM3, 97 PWM1_NS as PWM1,
95 QDEC0_NS as QDEC0, 98 PWM2_NS as PWM2,
96 QDEC1_NS as QDEC1, 99 PWM3_NS as PWM3,
97 QSPI_NS as QSPI, 100 QDEC0_NS as QDEC0,
98 REGULATORS_NS as REGULATORS, 101 QDEC1_NS as QDEC1,
99 RESET_NS as RESET, 102 QSPI_NS as QSPI,
100 RTC0_NS as RTC0, 103 REGULATORS_NS as REGULATORS,
101 RTC1_NS as RTC1, 104 RESET_NS as RESET,
102 SAADC_NS as SAADC, 105 RTC0_NS as RTC0,
103 SPIM0_NS as SPIM0, 106 RTC1_NS as RTC1,
104 SPIM1_NS as SPIM1, 107 SAADC_NS as SAADC,
105 SPIM2_NS as SPIM2, 108 SPIM0_NS as SPIM0,
106 SPIM3_NS as SPIM3, 109 SPIM1_NS as SPIM1,
107 SPIM4_NS as SPIM4, 110 SPIM2_NS as SPIM2,
108 SPIS0_NS as SPIS0, 111 SPIM3_NS as SPIM3,
109 SPIS1_NS as SPIS1, 112 SPIM4_NS as SPIM4,
110 SPIS2_NS as SPIS2, 113 SPIS0_NS as SPIS0,
111 SPIS3_NS as SPIS3, 114 SPIS1_NS as SPIS1,
112 TIMER0_NS as TIMER0, 115 SPIS2_NS as SPIS2,
113 TIMER1_NS as TIMER1, 116 SPIS3_NS as SPIS3,
114 TIMER2_NS as TIMER2, 117 TIMER0_NS as TIMER0,
115 TWIM0_NS as TWIM0, 118 TIMER1_NS as TIMER1,
116 TWIM1_NS as TWIM1, 119 TIMER2_NS as TIMER2,
117 TWIM2_NS as TWIM2, 120 TWIM0_NS as TWIM0,
118 TWIM3_NS as TWIM3, 121 TWIM1_NS as TWIM1,
119 TWIS0_NS as TWIS0, 122 TWIM2_NS as TWIM2,
120 TWIS1_NS as TWIS1, 123 TWIM3_NS as TWIM3,
121 TWIS2_NS as TWIS2, 124 TWIS0_NS as TWIS0,
122 TWIS3_NS as TWIS3, 125 TWIS1_NS as TWIS1,
123 UARTE0_NS as UARTE0, 126 TWIS2_NS as TWIS2,
124 UARTE1_NS as UARTE1, 127 TWIS3_NS as TWIS3,
125 UARTE2_NS as UARTE2, 128 UARTE0_NS as UARTE0,
126 UARTE3_NS as UARTE3, 129 UARTE1_NS as UARTE1,
127 USBD_NS as USBD, 130 UARTE2_NS as UARTE2,
128 USBREGULATOR_NS as USBREGULATOR, 131 UARTE3_NS as UARTE3,
129 VMC_NS as VMC, 132 USBD_NS as USBD,
130 WDT0_NS as WDT0, 133 USBREGULATOR_NS as USBREGULATOR,
131 WDT1_NS as WDT1, 134 VMC_NS as VMC,
132 }; 135 WDT0_NS as WDT0,
133 136 WDT1_NS as WDT1,
134 #[cfg(feature = "nrf5340-app-s")] 137 };
135 #[doc(no_inline)] 138 }
136 pub use nrf5340_app_pac::{ 139
137 CACHEDATA_S as CACHEDATA, 140 /// Secure mode (S) peripherals
138 CACHEINFO_S as CACHEINFO, 141 pub mod s {
139 CACHE_S as CACHE, 142 #[cfg(feature = "nrf5340-app-s")]
140 CLOCK_S as CLOCK, 143 #[doc(no_inline)]
141 COMP_S as COMP, 144 pub use nrf5340_app_pac::{
142 CRYPTOCELL_S as CRYPTOCELL, 145 CACHEDATA_S as CACHEDATA,
143 CTI_S as CTI, 146 CACHEINFO_S as CACHEINFO,
144 CTRLAP_S as CTRLAP, 147 CACHE_S as CACHE,
145 DCNF_S as DCNF, 148 CLOCK_S as CLOCK,
146 DPPIC_S as DPPIC, 149 COMP_S as COMP,
147 EGU0_S as EGU0, 150 CRYPTOCELL_S as CRYPTOCELL,
148 EGU1_S as EGU1, 151 CTI_S as CTI,
149 EGU2_S as EGU2, 152 CTRLAP_S as CTRLAP,
150 EGU3_S as EGU3, 153 DCNF_S as DCNF,
151 EGU4_S as EGU4, 154 DPPIC_S as DPPIC,
152 EGU5_S as EGU5, 155 EGU0_S as EGU0,
153 FICR_S as FICR, 156 EGU1_S as EGU1,
154 FPU_S as FPU, 157 EGU2_S as EGU2,
155 GPIOTE0_S as GPIOTE0, 158 EGU3_S as EGU3,
156 I2S0_S as I2S0, 159 EGU4_S as EGU4,
157 IPC_S as IPC, 160 EGU5_S as EGU5,
158 KMU_S as KMU, 161 FICR_S as FICR,
159 LPCOMP_S as LPCOMP, 162 FPU_S as FPU,
160 MUTEX_S as MUTEX, 163 GPIOTE0_S as GPIOTE0,
161 NFCT_S as NFCT, 164 I2S0_S as I2S0,
162 NVMC_S as NVMC, 165 IPC_S as IPC,
163 OSCILLATORS_S as OSCILLATORS, 166 KMU_S as KMU,
164 P0_S as P0, 167 LPCOMP_S as LPCOMP,
165 P1_S as P1, 168 MUTEX_S as MUTEX,
166 PDM0_S as PDM0, 169 NFCT_S as NFCT,
167 POWER_S as POWER, 170 NVMC_S as NVMC,
168 PWM0_S as PWM0, 171 OSCILLATORS_S as OSCILLATORS,
169 PWM1_S as PWM1, 172 P0_S as P0,
170 PWM2_S as PWM2, 173 P1_S as P1,
171 PWM3_S as PWM3, 174 PDM0_S as PDM0,
172 QDEC0_S as QDEC0, 175 POWER_S as POWER,
173 QDEC1_S as QDEC1, 176 PWM0_S as PWM0,
174 QSPI_S as QSPI, 177 PWM1_S as PWM1,
175 REGULATORS_S as REGULATORS, 178 PWM2_S as PWM2,
176 RESET_S as RESET, 179 PWM3_S as PWM3,
177 RTC0_S as RTC0, 180 QDEC0_S as QDEC0,
178 RTC1_S as RTC1, 181 QDEC1_S as QDEC1,
179 SAADC_S as SAADC, 182 QSPI_S as QSPI,
180 SPIM0_S as SPIM0, 183 REGULATORS_S as REGULATORS,
181 SPIM1_S as SPIM1, 184 RESET_S as RESET,
182 SPIM2_S as SPIM2, 185 RTC0_S as RTC0,
183 SPIM3_S as SPIM3, 186 RTC1_S as RTC1,
184 SPIM4_S as SPIM4, 187 SAADC_S as SAADC,
185 SPIS0_S as SPIS0, 188 SPIM0_S as SPIM0,
186 SPIS1_S as SPIS1, 189 SPIM1_S as SPIM1,
187 SPIS2_S as SPIS2, 190 SPIM2_S as SPIM2,
188 SPIS3_S as SPIS3, 191 SPIM3_S as SPIM3,
189 SPU_S as SPU, 192 SPIM4_S as SPIM4,
190 TAD_S as TAD, 193 SPIS0_S as SPIS0,
191 TIMER0_S as TIMER0, 194 SPIS1_S as SPIS1,
192 TIMER1_S as TIMER1, 195 SPIS2_S as SPIS2,
193 TIMER2_S as TIMER2, 196 SPIS3_S as SPIS3,
194 TWIM0_S as TWIM0, 197 SPU_S as SPU,
195 TWIM1_S as TWIM1, 198 TAD_S as TAD,
196 TWIM2_S as TWIM2, 199 TIMER0_S as TIMER0,
197 TWIM3_S as TWIM3, 200 TIMER1_S as TIMER1,
198 TWIS0_S as TWIS0, 201 TIMER2_S as TIMER2,
199 TWIS1_S as TWIS1, 202 TWIM0_S as TWIM0,
200 TWIS2_S as TWIS2, 203 TWIM1_S as TWIM1,
201 TWIS3_S as TWIS3, 204 TWIM2_S as TWIM2,
202 UARTE0_S as UARTE0, 205 TWIM3_S as TWIM3,
203 UARTE1_S as UARTE1, 206 TWIS0_S as TWIS0,
204 UARTE2_S as UARTE2, 207 TWIS1_S as TWIS1,
205 UARTE3_S as UARTE3, 208 TWIS2_S as TWIS2,
206 UICR_S as UICR, 209 TWIS3_S as TWIS3,
207 USBD_S as USBD, 210 UARTE0_S as UARTE0,
208 USBREGULATOR_S as USBREGULATOR, 211 UARTE1_S as UARTE1,
209 VMC_S as VMC, 212 UARTE2_S as UARTE2,
210 WDT0_S as WDT0, 213 UARTE3_S as UARTE3,
211 WDT1_S as WDT1, 214 UICR_S as UICR,
212 }; 215 USBD_S as USBD,
216 USBREGULATOR_S as USBREGULATOR,
217 VMC_S as VMC,
218 WDT0_S as WDT0,
219 WDT1_S as WDT1,
220 };
221 }
222
223 #[cfg(feature = "_ns")]
224 pub use ns::*;
225 #[cfg(feature = "_s")]
226 pub use s::*;
213} 227}
214 228
215/// The maximum buffer size that the EasyDMA can send/recv in one operation. 229/// The maximum buffer size that the EasyDMA can send/recv in one operation.
diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs
index dee666a61..a7cf82872 100644
--- a/embassy-nrf/src/chips/nrf5340_net.rs
+++ b/embassy-nrf/src/chips/nrf5340_net.rs
@@ -7,9 +7,12 @@ pub mod pac {
7 7
8 pub use nrf5340_net_pac::NVIC_PRIO_BITS; 8 pub use nrf5340_net_pac::NVIC_PRIO_BITS;
9 9
10 #[cfg(feature="rt")]
11 #[doc(no_inline)]
12 pub use nrf5340_net_pac::interrupt;
13
10 #[doc(no_inline)] 14 #[doc(no_inline)]
11 pub use nrf5340_net_pac::{ 15 pub use nrf5340_net_pac::{
12 interrupt,
13 Interrupt, 16 Interrupt,
14 Peripherals, 17 Peripherals,
15 18
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 495285ba3..8b1356ef8 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -7,9 +7,12 @@ pub mod pac {
7 7
8 pub use nrf9160_pac::NVIC_PRIO_BITS; 8 pub use nrf9160_pac::NVIC_PRIO_BITS;
9 9
10 #[cfg(feature="rt")]
11 #[doc(no_inline)]
12 pub use nrf9160_pac::interrupt;
13
10 #[doc(no_inline)] 14 #[doc(no_inline)]
11 pub use nrf9160_pac::{ 15 pub use nrf9160_pac::{
12 interrupt,
13 Interrupt, 16 Interrupt,
14 17
15 cc_host_rgf_s as cc_host_rgf, 18 cc_host_rgf_s as cc_host_rgf,
@@ -45,122 +48,131 @@ pub mod pac {
45 wdt_ns as wdt, 48 wdt_ns as wdt,
46 }; 49 };
47 50
48 #[cfg(feature = "nrf9160-ns")] 51 /// Non-Secure mode (NS) peripherals
49 #[doc(no_inline)] 52 pub mod ns {
50 pub use nrf9160_pac::{ 53 #[doc(no_inline)]
51 CLOCK_NS as CLOCK, 54 pub use nrf9160_pac::{
52 DPPIC_NS as DPPIC, 55 CLOCK_NS as CLOCK,
53 EGU0_NS as EGU0, 56 DPPIC_NS as DPPIC,
54 EGU1_NS as EGU1, 57 EGU0_NS as EGU0,
55 EGU2_NS as EGU2, 58 EGU1_NS as EGU1,
56 EGU3_NS as EGU3, 59 EGU2_NS as EGU2,
57 EGU4_NS as EGU4, 60 EGU3_NS as EGU3,
58 EGU5_NS as EGU5, 61 EGU4_NS as EGU4,
59 FPU_NS as FPU, 62 EGU5_NS as EGU5,
60 GPIOTE1_NS as GPIOTE1, 63 FPU_NS as FPU,
61 I2S_NS as I2S, 64 GPIOTE1_NS as GPIOTE1,
62 IPC_NS as IPC, 65 I2S_NS as I2S,
63 KMU_NS as KMU, 66 IPC_NS as IPC,
64 NVMC_NS as NVMC, 67 KMU_NS as KMU,
65 P0_NS as P0, 68 NVMC_NS as NVMC,
66 PDM_NS as PDM, 69 P0_NS as P0,
67 POWER_NS as POWER, 70 PDM_NS as PDM,
68 PWM0_NS as PWM0, 71 POWER_NS as POWER,
69 PWM1_NS as PWM1, 72 PWM0_NS as PWM0,
70 PWM2_NS as PWM2, 73 PWM1_NS as PWM1,
71 PWM3_NS as PWM3, 74 PWM2_NS as PWM2,
72 REGULATORS_NS as REGULATORS, 75 PWM3_NS as PWM3,
73 RTC0_NS as RTC0, 76 REGULATORS_NS as REGULATORS,
74 RTC1_NS as RTC1, 77 RTC0_NS as RTC0,
75 SAADC_NS as SAADC, 78 RTC1_NS as RTC1,
76 SPIM0_NS as SPIM0, 79 SAADC_NS as SAADC,
77 SPIM1_NS as SPIM1, 80 SPIM0_NS as SPIM0,
78 SPIM2_NS as SPIM2, 81 SPIM1_NS as SPIM1,
79 SPIM3_NS as SPIM3, 82 SPIM2_NS as SPIM2,
80 SPIS0_NS as SPIS0, 83 SPIM3_NS as SPIM3,
81 SPIS1_NS as SPIS1, 84 SPIS0_NS as SPIS0,
82 SPIS2_NS as SPIS2, 85 SPIS1_NS as SPIS1,
83 SPIS3_NS as SPIS3, 86 SPIS2_NS as SPIS2,
84 TIMER0_NS as TIMER0, 87 SPIS3_NS as SPIS3,
85 TIMER1_NS as TIMER1, 88 TIMER0_NS as TIMER0,
86 TIMER2_NS as TIMER2, 89 TIMER1_NS as TIMER1,
87 TWIM0_NS as TWIM0, 90 TIMER2_NS as TIMER2,
88 TWIM1_NS as TWIM1, 91 TWIM0_NS as TWIM0,
89 TWIM2_NS as TWIM2, 92 TWIM1_NS as TWIM1,
90 TWIM3_NS as TWIM3, 93 TWIM2_NS as TWIM2,
91 TWIS0_NS as TWIS0, 94 TWIM3_NS as TWIM3,
92 TWIS1_NS as TWIS1, 95 TWIS0_NS as TWIS0,
93 TWIS2_NS as TWIS2, 96 TWIS1_NS as TWIS1,
94 TWIS3_NS as TWIS3, 97 TWIS2_NS as TWIS2,
95 UARTE0_NS as UARTE0, 98 TWIS3_NS as TWIS3,
96 UARTE1_NS as UARTE1, 99 UARTE0_NS as UARTE0,
97 UARTE2_NS as UARTE2, 100 UARTE1_NS as UARTE1,
98 UARTE3_NS as UARTE3, 101 UARTE2_NS as UARTE2,
99 VMC_NS as VMC, 102 UARTE3_NS as UARTE3,
100 WDT_NS as WDT, 103 VMC_NS as VMC,
101 }; 104 WDT_NS as WDT,
105 };
106 }
102 107
103 #[cfg(feature = "nrf9160-s")] 108 /// Secure mode (S) peripherals
104 #[doc(no_inline)] 109 pub mod s {
105 pub use nrf9160_pac::{ 110 #[doc(no_inline)]
106 CC_HOST_RGF_S as CC_HOST_RGF, 111 pub use nrf9160_pac::{
107 CLOCK_S as CLOCK, 112 CC_HOST_RGF_S as CC_HOST_RGF,
108 CRYPTOCELL_S as CRYPTOCELL, 113 CLOCK_S as CLOCK,
109 CTRL_AP_PERI_S as CTRL_AP_PERI, 114 CRYPTOCELL_S as CRYPTOCELL,
110 DPPIC_S as DPPIC, 115 CTRL_AP_PERI_S as CTRL_AP_PERI,
111 EGU0_S as EGU0, 116 DPPIC_S as DPPIC,
112 EGU1_S as EGU1, 117 EGU0_S as EGU0,
113 EGU2_S as EGU2, 118 EGU1_S as EGU1,
114 EGU3_S as EGU3, 119 EGU2_S as EGU2,
115 EGU4_S as EGU4, 120 EGU3_S as EGU3,
116 EGU5_S as EGU5, 121 EGU4_S as EGU4,
117 FICR_S as FICR, 122 EGU5_S as EGU5,
118 FPU_S as FPU, 123 FICR_S as FICR,
119 GPIOTE0_S as GPIOTE0, 124 FPU_S as FPU,
120 I2S_S as I2S, 125 GPIOTE0_S as GPIOTE0,
121 IPC_S as IPC, 126 I2S_S as I2S,
122 KMU_S as KMU, 127 IPC_S as IPC,
123 NVMC_S as NVMC, 128 KMU_S as KMU,
124 P0_S as P0, 129 NVMC_S as NVMC,
125 PDM_S as PDM, 130 P0_S as P0,
126 POWER_S as POWER, 131 PDM_S as PDM,
127 PWM0_S as PWM0, 132 POWER_S as POWER,
128 PWM1_S as PWM1, 133 PWM0_S as PWM0,
129 PWM2_S as PWM2, 134 PWM1_S as PWM1,
130 PWM3_S as PWM3, 135 PWM2_S as PWM2,
131 REGULATORS_S as REGULATORS, 136 PWM3_S as PWM3,
132 RTC0_S as RTC0, 137 REGULATORS_S as REGULATORS,
133 RTC1_S as RTC1, 138 RTC0_S as RTC0,
134 SAADC_S as SAADC, 139 RTC1_S as RTC1,
135 SPIM0_S as SPIM0, 140 SAADC_S as SAADC,
136 SPIM1_S as SPIM1, 141 SPIM0_S as SPIM0,
137 SPIM2_S as SPIM2, 142 SPIM1_S as SPIM1,
138 SPIM3_S as SPIM3, 143 SPIM2_S as SPIM2,
139 SPIS0_S as SPIS0, 144 SPIM3_S as SPIM3,
140 SPIS1_S as SPIS1, 145 SPIS0_S as SPIS0,
141 SPIS2_S as SPIS2, 146 SPIS1_S as SPIS1,
142 SPIS3_S as SPIS3, 147 SPIS2_S as SPIS2,
143 SPU_S as SPU, 148 SPIS3_S as SPIS3,
144 TAD_S as TAD, 149 SPU_S as SPU,
145 TIMER0_S as TIMER0, 150 TAD_S as TAD,
146 TIMER1_S as TIMER1, 151 TIMER0_S as TIMER0,
147 TIMER2_S as TIMER2, 152 TIMER1_S as TIMER1,
148 TWIM0_S as TWIM0, 153 TIMER2_S as TIMER2,
149 TWIM1_S as TWIM1, 154 TWIM0_S as TWIM0,
150 TWIM2_S as TWIM2, 155 TWIM1_S as TWIM1,
151 TWIM3_S as TWIM3, 156 TWIM2_S as TWIM2,
152 TWIS0_S as TWIS0, 157 TWIM3_S as TWIM3,
153 TWIS1_S as TWIS1, 158 TWIS0_S as TWIS0,
154 TWIS2_S as TWIS2, 159 TWIS1_S as TWIS1,
155 TWIS3_S as TWIS3, 160 TWIS2_S as TWIS2,
156 UARTE0_S as UARTE0, 161 TWIS3_S as TWIS3,
157 UARTE1_S as UARTE1, 162 UARTE0_S as UARTE0,
158 UARTE2_S as UARTE2, 163 UARTE1_S as UARTE1,
159 UARTE3_S as UARTE3, 164 UARTE2_S as UARTE2,
160 UICR_S as UICR, 165 UARTE3_S as UARTE3,
161 VMC_S as VMC, 166 UICR_S as UICR,
162 WDT_S as WDT, 167 VMC_S as VMC,
163 }; 168 WDT_S as WDT,
169 };
170 }
171
172 #[cfg(feature = "_ns")]
173 pub use ns::*;
174 #[cfg(feature = "_s")]
175 pub use s::*;
164} 176}
165 177
166/// The maximum buffer size that the EasyDMA can send/recv in one operation. 178/// The maximum buffer size that the EasyDMA can send/recv in one operation.
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 9c4b6569d..2cc83d745 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -1,5 +1,5 @@
1#![no_std] 1#![no_std]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
3#![doc = include_str!("../README.md")] 3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)] 4#![warn(missing_docs)]
5 5
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 4828af43e..caf681d99 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -176,7 +176,7 @@ impl<'d, T: Instance> Spim<'d, T> {
176 let mut spim = Self { _p: spim }; 176 let mut spim = Self { _p: spim };
177 177
178 // Apply runtime peripheral configuration 178 // Apply runtime peripheral configuration
179 Self::set_config(&mut spim, &config); 179 Self::set_config(&mut spim, &config).unwrap();
180 180
181 // Disable all events interrupts 181 // Disable all events interrupts
182 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 182 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -566,7 +566,8 @@ mod eha {
566 566
567impl<'d, T: Instance> SetConfig for Spim<'d, T> { 567impl<'d, T: Instance> SetConfig for Spim<'d, T> {
568 type Config = Config; 568 type Config = Config;
569 fn set_config(&mut self, config: &Self::Config) { 569 type ConfigError = ();
570 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
570 let r = T::regs(); 571 let r = T::regs();
571 // Configure mode. 572 // Configure mode.
572 let mode = config.mode; 573 let mode = config.mode;
@@ -604,5 +605,7 @@ impl<'d, T: Instance> SetConfig for Spim<'d, T> {
604 // Set over-read character 605 // Set over-read character
605 let orc = config.orc; 606 let orc = config.orc;
606 r.orc.write(|w| unsafe { w.orc().bits(orc) }); 607 r.orc.write(|w| unsafe { w.orc().bits(orc) });
608
609 Ok(())
607 } 610 }
608} 611}
diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs
index e695ba6b7..e202c6c27 100644
--- a/embassy-nrf/src/spis.rs
+++ b/embassy-nrf/src/spis.rs
@@ -172,7 +172,7 @@ impl<'d, T: Instance> Spis<'d, T> {
172 let mut spis = Self { _p: spis }; 172 let mut spis = Self { _p: spis };
173 173
174 // Apply runtime peripheral configuration 174 // Apply runtime peripheral configuration
175 Self::set_config(&mut spis, &config); 175 Self::set_config(&mut spis, &config).unwrap();
176 176
177 // Disable all events interrupts. 177 // Disable all events interrupts.
178 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 178 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -467,7 +467,8 @@ macro_rules! impl_spis {
467 467
468impl<'d, T: Instance> SetConfig for Spis<'d, T> { 468impl<'d, T: Instance> SetConfig for Spis<'d, T> {
469 type Config = Config; 469 type Config = Config;
470 fn set_config(&mut self, config: &Self::Config) { 470 type ConfigError = ();
471 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
471 let r = T::regs(); 472 let r = T::regs();
472 // Configure mode. 473 // Configure mode.
473 let mode = config.mode; 474 let mode = config.mode;
@@ -509,5 +510,7 @@ impl<'d, T: Instance> SetConfig for Spis<'d, T> {
509 // Configure auto-acquire on 'transfer end' event. 510 // Configure auto-acquire on 'transfer end' event.
510 let auto_acquire = config.auto_acquire; 511 let auto_acquire = config.auto_acquire;
511 r.shorts.write(|w| w.end_acquire().bit(auto_acquire)); 512 r.shorts.write(|w| w.end_acquire().bit(auto_acquire));
513
514 Ok(())
512 } 515 }
513} 516}
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index fe38fb102..919bb4ab2 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -170,7 +170,7 @@ impl<'d, T: Instance> Twim<'d, T> {
170 let mut twim = Self { _p: twim }; 170 let mut twim = Self { _p: twim };
171 171
172 // Apply runtime peripheral configuration 172 // Apply runtime peripheral configuration
173 Self::set_config(&mut twim, &config); 173 Self::set_config(&mut twim, &config).unwrap();
174 174
175 // Disable all events interrupts 175 // Disable all events interrupts
176 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); 176 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
@@ -890,9 +890,12 @@ mod eha {
890 890
891impl<'d, T: Instance> SetConfig for Twim<'d, T> { 891impl<'d, T: Instance> SetConfig for Twim<'d, T> {
892 type Config = Config; 892 type Config = Config;
893 fn set_config(&mut self, config: &Self::Config) { 893 type ConfigError = ();
894 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
894 let r = T::regs(); 895 let r = T::regs();
895 r.frequency 896 r.frequency
896 .write(|w| unsafe { w.frequency().bits(config.frequency as u32) }); 897 .write(|w| unsafe { w.frequency().bits(config.frequency as u32) });
898
899 Ok(())
897 } 900 }
898} 901}
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 1147286fc..903dc25a8 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -60,7 +60,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"]
60 60
61[dependencies] 61[dependencies]
62embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 62embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
63embassy-time = { version = "0.1.3", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } 63embassy-time = { version = "0.1.5", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] }
64embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 64embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
65embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } 65embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
66embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 66embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
@@ -75,8 +75,8 @@ cortex-m = "0.7.6"
75critical-section = "1.1" 75critical-section = "1.1"
76futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 76futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
77chrono = { version = "0.4", default-features = false, optional = true } 77chrono = { version = "0.4", default-features = false, optional = true }
78embedded-io = { version = "0.5.0" } 78embedded-io = { version = "0.6.0" }
79embedded-io-async = { version = "0.5.0", optional = true } 79embedded-io-async = { version = "0.6.0", optional = true }
80embedded-storage = { version = "0.3" } 80embedded-storage = { version = "0.3" }
81embedded-storage-async = { version = "0.4.0", optional = true } 81embedded-storage-async = { version = "0.4.0", optional = true }
82rand_core = "0.6.4" 82rand_core = "0.6.4"
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index bac455743..5b913f156 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -213,6 +213,7 @@ impl<'d> Adc<'d, Async> {
213 ch: &mut Channel<'_>, 213 ch: &mut Channel<'_>,
214 buf: &mut [W], 214 buf: &mut [W],
215 fcs_err: bool, 215 fcs_err: bool,
216 div: u16,
216 dma: impl Peripheral<P = impl dma::Channel>, 217 dma: impl Peripheral<P = impl dma::Channel>,
217 ) -> Result<(), Error> { 218 ) -> Result<(), Error> {
218 let r = Self::regs(); 219 let r = Self::regs();
@@ -258,6 +259,7 @@ impl<'d> Adc<'d, Async> {
258 // start conversions and wait for dma to finish. we can't report errors early 259 // start conversions and wait for dma to finish. we can't report errors early
259 // because there's no interrupt to signal them, and inspecting every element 260 // because there's no interrupt to signal them, and inspecting every element
260 // of the fifo is too costly to do here. 261 // of the fifo is too costly to do here.
262 r.div().write_set(|w| w.set_int(div));
261 r.cs().write_set(|w| w.set_start_many(true)); 263 r.cs().write_set(|w| w.set_start_many(true));
262 dma.await; 264 dma.await;
263 mem::drop(auto_reset); 265 mem::drop(auto_reset);
@@ -275,9 +277,10 @@ impl<'d> Adc<'d, Async> {
275 &mut self, 277 &mut self,
276 ch: &mut Channel<'_>, 278 ch: &mut Channel<'_>,
277 buf: &mut [S], 279 buf: &mut [S],
280 div: u16,
278 dma: impl Peripheral<P = impl dma::Channel>, 281 dma: impl Peripheral<P = impl dma::Channel>,
279 ) -> Result<(), Error> { 282 ) -> Result<(), Error> {
280 self.read_many_inner(ch, buf, false, dma).await 283 self.read_many_inner(ch, buf, false, div, dma).await
281 } 284 }
282 285
283 #[inline] 286 #[inline]
@@ -285,11 +288,12 @@ impl<'d> Adc<'d, Async> {
285 &mut self, 288 &mut self,
286 ch: &mut Channel<'_>, 289 ch: &mut Channel<'_>,
287 buf: &mut [Sample], 290 buf: &mut [Sample],
291 div: u16,
288 dma: impl Peripheral<P = impl dma::Channel>, 292 dma: impl Peripheral<P = impl dma::Channel>,
289 ) { 293 ) {
290 // errors are reported in individual samples 294 // errors are reported in individual samples
291 let _ = self 295 let _ = self
292 .read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, dma) 296 .read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, div, dma)
293 .await; 297 .await;
294 } 298 }
295} 299}
diff --git a/embassy-rp/src/bootsel.rs b/embassy-rp/src/bootsel.rs
new file mode 100644
index 000000000..540255ae3
--- /dev/null
+++ b/embassy-rp/src/bootsel.rs
@@ -0,0 +1,83 @@
1//! Boot Select button
2//!
3//! The RP2040 rom supports a BOOTSEL button that is used to enter the USB bootloader
4//! if held during reset. To avoid wasting GPIO pins, the button is multiplexed onto
5//! the CS pin of the QSPI flash, but that makes it somewhat expensive and complicated
6//! to utilize outside of the rom's bootloader.
7//!
8//! This module provides functionality to poll BOOTSEL from an embassy application.
9
10use crate::flash::in_ram;
11
12impl crate::peripherals::BOOTSEL {
13 /// Polls the BOOTSEL button. Returns true if the button is pressed.
14 ///
15 /// Polling isn't cheap, as this function waits for core 1 to finish it's current
16 /// task and for any DMAs from flash to complete
17 pub fn is_pressed(&mut self) -> bool {
18 let mut cs_status = Default::default();
19
20 unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0");
21
22 // bootsel is active low, so invert
23 !cs_status.infrompad()
24 }
25}
26
27mod ram_helpers {
28 use rp_pac::io::regs::GpioStatus;
29
30 /// Temporally reconfigures the CS gpio and returns the GpioStatus.
31
32 /// This function runs from RAM so it can disable flash XIP.
33 ///
34 /// # Safety
35 ///
36 /// The caller must ensure flash is idle and will remain idle.
37 /// This function must live in ram. It uses inline asm to avoid any
38 /// potential calls to ABI functions that might be in flash.
39 #[inline(never)]
40 #[link_section = ".data.ram_func"]
41 #[cfg(target_arch = "arm")]
42 pub unsafe fn read_cs_status() -> GpioStatus {
43 let result: u32;
44
45 // Magic value, used as both OEOVER::DISABLE and delay loop counter
46 let magic = 0x2000;
47
48 core::arch::asm!(
49 ".equiv GPIO_STATUS, 0x0",
50 ".equiv GPIO_CTRL, 0x4",
51
52 "ldr {orig_ctrl}, [{cs_gpio}, $GPIO_CTRL]",
53
54 // The BOOTSEL pulls the flash's CS line low though a 1K resistor.
55 // this is weak enough to avoid disrupting normal operation.
56 // But, if we disable CS's output drive and allow it to float...
57 "str {val}, [{cs_gpio}, $GPIO_CTRL]",
58
59 // ...then wait for the state to settle...
60 "1:", // ~4000 cycle delay loop
61 "subs {val}, #8",
62 "bne 1b",
63
64 // ...we can read the current state of bootsel
65 "ldr {val}, [{cs_gpio}, $GPIO_STATUS]",
66
67 // Finally, restore CS to normal operation so XIP can continue
68 "str {orig_ctrl}, [{cs_gpio}, $GPIO_CTRL]",
69
70 cs_gpio = in(reg) rp_pac::IO_QSPI.gpio(1).as_ptr(),
71 orig_ctrl = out(reg) _,
72 val = inout(reg) magic => result,
73 options(nostack),
74 );
75
76 core::mem::transmute(result)
77 }
78
79 #[cfg(not(target_arch = "arm"))]
80 pub unsafe fn read_cs_status() -> GpioStatus {
81 unimplemented!()
82 }
83}
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 1c1c2449e..8fb5542f1 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -131,7 +131,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
131 131
132 let len = to - from; 132 let len = to - from;
133 133
134 unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len))? }; 134 unsafe { in_ram(|| ram_helpers::flash_range_erase(from, len))? };
135 135
136 Ok(()) 136 Ok(())
137 } 137 }
@@ -156,7 +156,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
156 156
157 let unaligned_offset = offset as usize - start; 157 let unaligned_offset = offset as usize - start;
158 158
159 unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } 159 unsafe { in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? }
160 } 160 }
161 161
162 let remaining_len = bytes.len() - start_padding; 162 let remaining_len = bytes.len() - start_padding;
@@ -174,12 +174,12 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
174 if bytes.as_ptr() as usize >= 0x2000_0000 { 174 if bytes.as_ptr() as usize >= 0x2000_0000 {
175 let aligned_data = &bytes[start_padding..end_padding]; 175 let aligned_data = &bytes[start_padding..end_padding];
176 176
177 unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data))? } 177 unsafe { in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data))? }
178 } else { 178 } else {
179 for chunk in bytes[start_padding..end_padding].chunks_exact(PAGE_SIZE) { 179 for chunk in bytes[start_padding..end_padding].chunks_exact(PAGE_SIZE) {
180 let mut ram_buf = [0xFF_u8; PAGE_SIZE]; 180 let mut ram_buf = [0xFF_u8; PAGE_SIZE];
181 ram_buf.copy_from_slice(chunk); 181 ram_buf.copy_from_slice(chunk);
182 unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf))? } 182 unsafe { in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf))? }
183 aligned_offset += PAGE_SIZE; 183 aligned_offset += PAGE_SIZE;
184 } 184 }
185 } 185 }
@@ -194,47 +194,15 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
194 194
195 let unaligned_offset = end_offset - (PAGE_SIZE - rem_offset); 195 let unaligned_offset = end_offset - (PAGE_SIZE - rem_offset);
196 196
197 unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } 197 unsafe { in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? }
198 } 198 }
199 199
200 Ok(()) 200 Ok(())
201 } 201 }
202 202
203 /// Make sure to uphold the contract points with rp2040-flash.
204 /// - interrupts must be disabled
205 /// - DMA must not access flash memory
206 unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> {
207 // Make sure we're running on CORE0
208 let core_id: u32 = pac::SIO.cpuid().read();
209 if core_id != 0 {
210 return Err(Error::InvalidCore);
211 }
212
213 // Make sure CORE1 is paused during the entire duration of the RAM function
214 crate::multicore::pause_core1();
215
216 critical_section::with(|_| {
217 // Wait for all DMA channels in flash to finish before ram operation
218 const SRAM_LOWER: u32 = 0x2000_0000;
219 for n in 0..crate::dma::CHANNEL_COUNT {
220 let ch = crate::pac::DMA.ch(n);
221 while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {}
222 }
223 // Wait for completion of any background reads
224 while pac::XIP_CTRL.stream_ctr().read().0 > 0 {}
225
226 // Run our flash operation in RAM
227 operation();
228 });
229
230 // Resume CORE1 execution
231 crate::multicore::resume_core1();
232 Ok(())
233 }
234
235 /// Read SPI flash unique ID 203 /// Read SPI flash unique ID
236 pub fn blocking_unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> { 204 pub fn blocking_unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> {
237 unsafe { self.in_ram(|| ram_helpers::flash_unique_id(uid))? }; 205 unsafe { in_ram(|| ram_helpers::flash_unique_id(uid))? };
238 Ok(()) 206 Ok(())
239 } 207 }
240 208
@@ -242,7 +210,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
242 pub fn blocking_jedec_id(&mut self) -> Result<u32, Error> { 210 pub fn blocking_jedec_id(&mut self) -> Result<u32, Error> {
243 let mut jedec = None; 211 let mut jedec = None;
244 unsafe { 212 unsafe {
245 self.in_ram(|| { 213 in_ram(|| {
246 jedec.replace(ram_helpers::flash_jedec_id()); 214 jedec.replace(ram_helpers::flash_jedec_id());
247 })?; 215 })?;
248 }; 216 };
@@ -871,6 +839,38 @@ mod ram_helpers {
871 } 839 }
872} 840}
873 841
842/// Make sure to uphold the contract points with rp2040-flash.
843/// - interrupts must be disabled
844/// - DMA must not access flash memory
845pub(crate) unsafe fn in_ram(operation: impl FnOnce()) -> Result<(), Error> {
846 // Make sure we're running on CORE0
847 let core_id: u32 = pac::SIO.cpuid().read();
848 if core_id != 0 {
849 return Err(Error::InvalidCore);
850 }
851
852 // Make sure CORE1 is paused during the entire duration of the RAM function
853 crate::multicore::pause_core1();
854
855 critical_section::with(|_| {
856 // Wait for all DMA channels in flash to finish before ram operation
857 const SRAM_LOWER: u32 = 0x2000_0000;
858 for n in 0..crate::dma::CHANNEL_COUNT {
859 let ch = crate::pac::DMA.ch(n);
860 while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {}
861 }
862 // Wait for completion of any background reads
863 while pac::XIP_CTRL.stream_ctr().read().0 > 0 {}
864
865 // Run our flash operation in RAM
866 operation();
867 });
868
869 // Resume CORE1 execution
870 crate::multicore::resume_core1();
871 Ok(())
872}
873
874mod sealed { 874mod sealed {
875 pub trait Instance {} 875 pub trait Instance {}
876 pub trait Mode {} 876 pub trait Mode {}
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index ad9d4262d..ee7e03e95 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -97,6 +97,12 @@ impl<'d, T: Pin> Input<'d, T> {
97 Self { pin } 97 Self { pin }
98 } 98 }
99 99
100 /// Set the pin's Schmitt trigger.
101 #[inline]
102 pub fn set_schmitt(&mut self, enable: bool) {
103 self.pin.set_schmitt(enable)
104 }
105
100 #[inline] 106 #[inline]
101 pub fn is_high(&self) -> bool { 107 pub fn is_high(&self) -> bool {
102 self.pin.is_high() 108 self.pin.is_high()
@@ -216,7 +222,6 @@ fn IO_IRQ_QSPI() {
216#[must_use = "futures do nothing unless you `.await` or poll them"] 222#[must_use = "futures do nothing unless you `.await` or poll them"]
217struct InputFuture<'a, T: Pin> { 223struct InputFuture<'a, T: Pin> {
218 pin: PeripheralRef<'a, T>, 224 pin: PeripheralRef<'a, T>,
219 level: InterruptTrigger,
220} 225}
221 226
222impl<'d, T: Pin> InputFuture<'d, T> { 227impl<'d, T: Pin> InputFuture<'d, T> {
@@ -243,7 +248,6 @@ impl<'d, T: Pin> InputFuture<'d, T> {
243 .inte((pin.pin() / 8) as usize) 248 .inte((pin.pin() / 8) as usize)
244 .write_set(|w| match level { 249 .write_set(|w| match level {
245 InterruptTrigger::LevelHigh => { 250 InterruptTrigger::LevelHigh => {
246 trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin());
247 w.set_level_high(pin_group, true); 251 w.set_level_high(pin_group, true);
248 } 252 }
249 InterruptTrigger::LevelLow => { 253 InterruptTrigger::LevelLow => {
@@ -261,7 +265,7 @@ impl<'d, T: Pin> InputFuture<'d, T> {
261 } 265 }
262 }); 266 });
263 267
264 Self { pin, level } 268 Self { pin }
265 } 269 }
266} 270}
267 271
@@ -297,14 +301,8 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
297 && !inte.level_high(pin_group) 301 && !inte.level_high(pin_group)
298 && !inte.level_low(pin_group) 302 && !inte.level_low(pin_group)
299 { 303 {
300 trace!(
301 "{:?} for pin {} was cleared, return Poll::Ready",
302 self.level,
303 self.pin.pin()
304 );
305 return Poll::Ready(()); 304 return Poll::Ready(());
306 } 305 }
307 trace!("InputFuture::poll return Poll::Pending");
308 Poll::Pending 306 Poll::Pending
309 } 307 }
310} 308}
@@ -326,6 +324,18 @@ impl<'d, T: Pin> Output<'d, T> {
326 Self { pin } 324 Self { pin }
327 } 325 }
328 326
327 /// Set the pin's drive strength.
328 #[inline]
329 pub fn set_drive_strength(&mut self, strength: Drive) {
330 self.pin.set_drive_strength(strength)
331 }
332
333 // Set the pin's slew rate.
334 #[inline]
335 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
336 self.pin.set_slew_rate(slew_rate)
337 }
338
329 /// Set the output as high. 339 /// Set the output as high.
330 #[inline] 340 #[inline]
331 pub fn set_high(&mut self) { 341 pub fn set_high(&mut self) {
@@ -386,6 +396,18 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> {
386 Self { pin } 396 Self { pin }
387 } 397 }
388 398
399 /// Set the pin's drive strength.
400 #[inline]
401 pub fn set_drive_strength(&mut self, strength: Drive) {
402 self.pin.set_drive_strength(strength)
403 }
404
405 // Set the pin's slew rate.
406 #[inline]
407 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
408 self.pin.set_slew_rate(slew_rate)
409 }
410
389 /// Set the output as high. 411 /// Set the output as high.
390 #[inline] 412 #[inline]
391 pub fn set_high(&mut self) { 413 pub fn set_high(&mut self) {
@@ -541,6 +563,14 @@ impl<'d, T: Pin> Flex<'d, T> {
541 }); 563 });
542 } 564 }
543 565
566 /// Set the pin's Schmitt trigger.
567 #[inline]
568 pub fn set_schmitt(&mut self, enable: bool) {
569 self.pin.pad_ctrl().modify(|w| {
570 w.set_schmitt(enable);
571 });
572 }
573
544 /// Put the pin into input mode. 574 /// Put the pin into input mode.
545 /// 575 ///
546 /// The pull setting is left unchanged. 576 /// The pull setting is left unchanged.
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index c358682c5..4fe4b27eb 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -6,13 +6,12 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
6use embassy_sync::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7use pac::i2c; 7use pac::i2c;
8 8
9use crate::gpio::sealed::Pin;
10use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
11use crate::interrupt::typelevel::{Binding, Interrupt}; 10use crate::interrupt::typelevel::{Binding, Interrupt};
12use crate::{interrupt, pac, peripherals, Peripheral}; 11use crate::{interrupt, pac, peripherals, Peripheral};
13 12
14/// I2C error abort reason 13/// I2C error abort reason
15#[derive(Debug)] 14#[derive(Debug, PartialEq, Eq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))] 15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub enum AbortReason { 16pub enum AbortReason {
18 /// A bus operation was not acknowledged, e.g. due to the addressed device 17 /// A bus operation was not acknowledged, e.g. due to the addressed device
@@ -27,7 +26,7 @@ pub enum AbortReason {
27} 26}
28 27
29/// I2C error 28/// I2C error
30#[derive(Debug)] 29#[derive(Debug, PartialEq, Eq)]
31#[cfg_attr(feature = "defmt", derive(defmt::Format))] 30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
32pub enum Error { 31pub enum Error {
33 /// I2C abort with error 32 /// I2C abort with error
@@ -295,13 +294,24 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
295 294
296 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { 295 pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> {
297 Self::setup(addr)?; 296 Self::setup(addr)?;
298 self.read_async_internal(buffer, false, true).await 297 self.read_async_internal(buffer, true, true).await
299 } 298 }
300 299
301 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> { 300 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
302 Self::setup(addr)?; 301 Self::setup(addr)?;
303 self.write_async_internal(bytes, true).await 302 self.write_async_internal(bytes, true).await
304 } 303 }
304
305 pub async fn write_read_async(
306 &mut self,
307 addr: u16,
308 bytes: impl IntoIterator<Item = u8>,
309 buffer: &mut [u8],
310 ) -> Result<(), Error> {
311 Self::setup(addr)?;
312 self.write_async_internal(bytes, false).await?;
313 self.read_async_internal(buffer, true, true).await
314 }
305} 315}
306 316
307pub struct InterruptHandler<T: Instance> { 317pub struct InterruptHandler<T: Instance> {
@@ -318,6 +328,22 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
318 } 328 }
319} 329}
320 330
331pub(crate) fn set_up_i2c_pin<'d, P, T>(pin: &P)
332where
333 P: core::ops::Deref<Target = T>,
334 T: crate::gpio::Pin,
335{
336 pin.gpio().ctrl().write(|w| w.set_funcsel(3));
337 pin.pad_ctrl().write(|w| {
338 w.set_schmitt(true);
339 w.set_slewfast(false);
340 w.set_ie(true);
341 w.set_od(false);
342 w.set_pue(true);
343 w.set_pde(false);
344 });
345}
346
321impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { 347impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
322 fn new_inner( 348 fn new_inner(
323 _peri: impl Peripheral<P = T> + 'd, 349 _peri: impl Peripheral<P = T> + 'd,
@@ -355,23 +381,8 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
355 p.ic_rx_tl().write(|w| w.set_rx_tl(0)); 381 p.ic_rx_tl().write(|w| w.set_rx_tl(0));
356 382
357 // Configure SCL & SDA pins 383 // Configure SCL & SDA pins
358 scl.gpio().ctrl().write(|w| w.set_funcsel(3)); 384 set_up_i2c_pin(&scl);
359 sda.gpio().ctrl().write(|w| w.set_funcsel(3)); 385 set_up_i2c_pin(&sda);
360
361 scl.pad_ctrl().write(|w| {
362 w.set_schmitt(true);
363 w.set_ie(true);
364 w.set_od(false);
365 w.set_pue(true);
366 w.set_pde(false);
367 });
368 sda.pad_ctrl().write(|w| {
369 w.set_schmitt(true);
370 w.set_ie(true);
371 w.set_od(false);
372 w.set_pue(true);
373 w.set_pde(false);
374 });
375 386
376 // Configure baudrate 387 // Configure baudrate
377 388
@@ -713,7 +724,7 @@ mod nightly {
713 724
714 Self::setup(addr)?; 725 Self::setup(addr)?;
715 self.write_async_internal(write.iter().cloned(), false).await?; 726 self.write_async_internal(write.iter().cloned(), false).await?;
716 self.read_async_internal(read, false, true).await 727 self.read_async_internal(read, true, true).await
717 } 728 }
718 729
719 async fn transaction(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { 730 async fn transaction(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs
index 6136d69c6..9271ede3a 100644
--- a/embassy-rp/src/i2c_slave.rs
+++ b/embassy-rp/src/i2c_slave.rs
@@ -5,12 +5,14 @@ use core::task::Poll;
5use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
6use pac::i2c; 6use pac::i2c;
7 7
8use crate::i2c::{i2c_reserved_addr, AbortReason, Instance, InterruptHandler, SclPin, SdaPin, FIFO_SIZE}; 8use crate::i2c::{
9 i2c_reserved_addr, set_up_i2c_pin, AbortReason, Instance, InterruptHandler, SclPin, SdaPin, FIFO_SIZE,
10};
9use crate::interrupt::typelevel::{Binding, Interrupt}; 11use crate::interrupt::typelevel::{Binding, Interrupt};
10use crate::{pac, Peripheral}; 12use crate::{pac, Peripheral};
11 13
12/// I2C error 14/// I2C error
13#[derive(Debug)] 15#[derive(Debug, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))] 16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[non_exhaustive] 17#[non_exhaustive]
16pub enum Error { 18pub enum Error {
@@ -100,23 +102,8 @@ impl<'d, T: Instance> I2cSlave<'d, T> {
100 p.ic_rx_tl().write(|w| w.set_rx_tl(0)); 102 p.ic_rx_tl().write(|w| w.set_rx_tl(0));
101 103
102 // Configure SCL & SDA pins 104 // Configure SCL & SDA pins
103 scl.gpio().ctrl().write(|w| w.set_funcsel(3)); 105 set_up_i2c_pin(&scl);
104 sda.gpio().ctrl().write(|w| w.set_funcsel(3)); 106 set_up_i2c_pin(&sda);
105
106 scl.pad_ctrl().write(|w| {
107 w.set_schmitt(true);
108 w.set_ie(true);
109 w.set_od(false);
110 w.set_pue(true);
111 w.set_pde(false);
112 });
113 sda.pad_ctrl().write(|w| {
114 w.set_schmitt(true);
115 w.set_ie(true);
116 w.set_od(false);
117 w.set_pue(true);
118 w.set_pde(false);
119 });
120 107
121 // Clear interrupts 108 // Clear interrupts
122 p.ic_clr_intr().read(); 109 p.ic_clr_intr().read();
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index c3561bbe4..2728395b2 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -1,5 +1,5 @@
1#![no_std] 1#![no_std]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
3 3
4// This mod MUST go first, so that the others see its macros. 4// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt; 5pub(crate) mod fmt;
@@ -10,6 +10,7 @@ mod critical_section_impl;
10mod intrinsics; 10mod intrinsics;
11 11
12pub mod adc; 12pub mod adc;
13pub mod bootsel;
13pub mod clocks; 14pub mod clocks;
14pub mod dma; 15pub mod dma;
15pub mod flash; 16pub mod flash;
@@ -193,6 +194,7 @@ embassy_hal_internal::peripherals! {
193 PIO1, 194 PIO1,
194 195
195 WATCHDOG, 196 WATCHDOG,
197 BOOTSEL,
196} 198}
197 199
198macro_rules! select_bootloader { 200macro_rules! select_bootloader {
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index c297d69a2..516b8254b 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -10,16 +10,39 @@ use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Pin as GpioPin}; 10use crate::gpio::{AnyPin, Pin as GpioPin};
11use crate::{pac, peripherals, RegExt}; 11use crate::{pac, peripherals, RegExt};
12 12
13/// The configuration of a PWM slice.
14/// Note the period in clock cycles of a slice can be computed as:
15/// `(top + 1) * (phase_correct ? 1 : 2) * divider`
13#[non_exhaustive] 16#[non_exhaustive]
14#[derive(Clone)] 17#[derive(Clone)]
15pub struct Config { 18pub struct Config {
19 /// Inverts the PWM output signal on channel A.
16 pub invert_a: bool, 20 pub invert_a: bool,
21 /// Inverts the PWM output signal on channel B.
17 pub invert_b: bool, 22 pub invert_b: bool,
23 /// Enables phase-correct mode for PWM operation.
24 /// In phase-correct mode, the PWM signal is generated in such a way that
25 /// the pulse is always centered regardless of the duty cycle.
26 /// The output frequency is halved when phase-correct mode is enabled.
18 pub phase_correct: bool, 27 pub phase_correct: bool,
28 /// Enables the PWM slice, allowing it to generate an output.
19 pub enable: bool, 29 pub enable: bool,
30 /// A fractional clock divider, represented as a fixed-point number with
31 /// 8 integer bits and 4 fractional bits. It allows precise control over
32 /// the PWM output frequency by gating the PWM counter increment.
33 /// A higher value will result in a slower output frequency.
20 pub divider: fixed::FixedU16<fixed::types::extra::U4>, 34 pub divider: fixed::FixedU16<fixed::types::extra::U4>,
35 /// The output on channel A goes high when `compare_a` is higher than the
36 /// counter. A compare of 0 will produce an always low output, while a
37 /// compare of `top + 1` will produce an always high output.
21 pub compare_a: u16, 38 pub compare_a: u16,
39 /// The output on channel B goes high when `compare_b` is higher than the
40 /// counter. A compare of 0 will produce an always low output, while a
41 /// compare of `top + 1` will produce an always high output.
22 pub compare_b: u16, 42 pub compare_b: u16,
43 /// The point at which the counter wraps, representing the maximum possible
44 /// period. The counter will either wrap to 0 or reverse depending on the
45 /// setting of `phase_correct`.
23 pub top: u16, 46 pub top: u16,
24} 47}
25 48
@@ -173,6 +196,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
173 }); 196 });
174 } 197 }
175 198
199 /// Advances a slice’s output phase by one count while it is running
200 /// by inserting a pulse into the clock enable. The counter
201 /// will not count faster than once per cycle.
176 #[inline] 202 #[inline]
177 pub fn phase_advance(&mut self) { 203 pub fn phase_advance(&mut self) {
178 let p = self.inner.regs(); 204 let p = self.inner.regs();
@@ -180,6 +206,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
180 while p.csr().read().ph_adv() {} 206 while p.csr().read().ph_adv() {}
181 } 207 }
182 208
209 /// Retards a slice’s output phase by one count while it is running
210 /// by deleting a pulse from the clock enable. The counter will not
211 /// count backward when clock enable is permenantly low.
183 #[inline] 212 #[inline]
184 pub fn phase_retard(&mut self) { 213 pub fn phase_retard(&mut self) {
185 let p = self.inner.regs(); 214 let p = self.inner.regs();
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 46c440b84..a59ce8419 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -597,7 +597,8 @@ mod eha {
597 597
598impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> { 598impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> {
599 type Config = Config; 599 type Config = Config;
600 fn set_config(&mut self, config: &Self::Config) { 600 type ConfigError = ();
601 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
601 let p = self.inner.regs(); 602 let p = self.inner.regs();
602 let (presc, postdiv) = calc_prescs(config.frequency); 603 let (presc, postdiv) = calc_prescs(config.frequency);
603 p.cpsr().write(|w| w.set_cpsdvsr(presc)); 604 p.cpsr().write(|w| w.set_cpsdvsr(presc));
@@ -607,5 +608,7 @@ impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> {
607 w.set_sph(config.phase == Phase::CaptureOnSecondTransition); 608 w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
608 w.set_scr(postdiv); 609 w.set_scr(postdiv);
609 }); 610 });
611
612 Ok(())
610 } 613 }
611} 614}
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index e57b72599..9f638761d 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -5,7 +5,7 @@ use core::task::Poll;
5use atomic_polyfill::{AtomicU8, Ordering}; 5use atomic_polyfill::{AtomicU8, Ordering};
6use embassy_hal_internal::atomic_ring_buffer::RingBuffer; 6use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9 9
10use super::*; 10use super::*;
11use crate::clocks::clk_peri_freq; 11use crate::clocks::clk_peri_freq;
@@ -435,7 +435,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
435 Self::flush().await.unwrap(); 435 Self::flush().await.unwrap();
436 while self.busy() {} 436 while self.busy() {}
437 regs.uartlcr_h().write_set(|w| w.set_brk(true)); 437 regs.uartlcr_h().write_set(|w| w.set_brk(true));
438 Timer::after(Duration::from_micros(wait_usecs)).await; 438 Timer::after_micros(wait_usecs).await;
439 regs.uartlcr_h().write_clear(|w| w.set_brk(true)); 439 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
440 } 440 }
441} 441}
@@ -490,8 +490,6 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterr
490 w.set_oeic(ris.oeris()); 490 w.set_oeic(ris.oeris());
491 }); 491 });
492 492
493 trace!("on_interrupt ris={:#X}", ris.0);
494
495 // Errors 493 // Errors
496 if ris.feris() { 494 if ris.feris() {
497 warn!("Framing error"); 495 warn!("Framing error");
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 202b0883e..461986c81 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -6,7 +6,7 @@ use atomic_polyfill::{AtomicU16, Ordering};
6use embassy_futures::select::{select, Either}; 6use embassy_futures::select::{select, Either};
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use pac::uart::regs::Uartris; 10use pac::uart::regs::Uartris;
11 11
12use crate::clocks::clk_peri_freq; 12use crate::clocks::clk_peri_freq;
@@ -187,7 +187,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
187 self.blocking_flush().unwrap(); 187 self.blocking_flush().unwrap();
188 while self.busy() {} 188 while self.busy() {}
189 regs.uartlcr_h().write_set(|w| w.set_brk(true)); 189 regs.uartlcr_h().write_set(|w| w.set_brk(true));
190 Timer::after(Duration::from_micros(wait_usecs)).await; 190 Timer::after_micros(wait_usecs).await;
191 regs.uartlcr_h().write_clear(|w| w.set_brk(true)); 191 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
192 } 192 }
193} 193}
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index 3b10b7c52..52ecf15d1 100644
--- a/embassy-stm32-wpan/Cargo.toml
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -13,11 +13,11 @@ features = ["stm32wb55rg"]
13[dependencies] 13[dependencies]
14embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } 14embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" }
15embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 15embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
16embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 16embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
17embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
18embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" } 18embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" }
19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } 19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
20embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } 20embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true }
21 21
22defmt = { version = "0.3", optional = true } 22defmt = { version = "0.3", optional = true }
23cortex-m = "0.7.6" 23cortex-m = "0.7.6"
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs
index bfc4f1ee8..ffba6e5e8 100644
--- a/embassy-stm32-wpan/src/mac/driver.rs
+++ b/embassy-stm32-wpan/src/mac/driver.rs
@@ -3,7 +3,7 @@
3 3
4use core::task::Context; 4use core::task::Context;
5 5
6use embassy_net_driver::{Capabilities, HardwareAddress, LinkState, Medium}; 6use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel; 8use embassy_sync::channel::Channel;
9 9
@@ -60,24 +60,15 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
60 let mut caps = Capabilities::default(); 60 let mut caps = Capabilities::default();
61 caps.max_transmission_unit = MTU; 61 caps.max_transmission_unit = MTU;
62 // caps.max_burst_size = Some(self.tx.len()); 62 // caps.max_burst_size = Some(self.tx.len());
63
64 caps.medium = Medium::Ieee802154;
65 caps 63 caps
66 } 64 }
67 65
68 fn link_state(&mut self, _cx: &mut Context) -> LinkState { 66 fn link_state(&mut self, _cx: &mut Context) -> LinkState {
69 // if self.phy.poll_link(&mut self.station_management, cx) {
70 // LinkState::Up
71 // } else {
72 // LinkState::Down
73 // }
74
75 LinkState::Down 67 LinkState::Down
76 } 68 }
77 69
78 fn hardware_address(&self) -> HardwareAddress { 70 fn hardware_address(&self) -> HardwareAddress {
79 // self.mac_addr 71 // self.mac_addr
80
81 HardwareAddress::Ieee802154([0; 8]) 72 HardwareAddress::Ieee802154([0; 8])
82 } 73 }
83} 74}
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 87f9083b3..3b9220bc7 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -33,11 +33,11 @@ flavors = [
33 33
34[dependencies] 34[dependencies]
35embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 35embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
36embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 36embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
37embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 37embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
38embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } 38embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
39embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 39embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
40embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } 40embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
41embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } 41embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
42embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true } 42embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true }
43 43
@@ -58,16 +58,14 @@ rand_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 } 59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
60critical-section = "1.1" 60critical-section = "1.1"
61atomic-polyfill = "1.0.1" 61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5b04234fbe61ea875f1a904cd5f68795daaeb526" }
62stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840" }
63vcell = "0.1.3" 62vcell = "0.1.3"
64bxcan = "0.7.0" 63bxcan = "0.7.0"
65nb = "1.0.0" 64nb = "1.0.0"
66stm32-fmc = "0.3.0" 65stm32-fmc = "0.3.0"
67seq-macro = "0.3.0"
68cfg-if = "1.0.0" 66cfg-if = "1.0.0"
69embedded-io = { version = "0.5.0" } 67embedded-io = { version = "0.6.0" }
70embedded-io-async = { version = "0.5.0", optional = true } 68embedded-io-async = { version = "0.6.0", optional = true }
71chrono = { version = "^0.4", default-features = false, optional = true} 69chrono = { version = "^0.4", default-features = false, optional = true}
72bit_field = "0.10.2" 70bit_field = "0.10.2"
73document-features = "0.2.7" 71document-features = "0.2.7"
@@ -78,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
78[build-dependencies] 76[build-dependencies]
79proc-macro2 = "1.0.36" 77proc-macro2 = "1.0.36"
80quote = "1.0.15" 78quote = "1.0.15"
81stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840", default-features = false, features = ["metadata"]} 79stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5b04234fbe61ea875f1a904cd5f68795daaeb526", default-features = false, features = ["metadata"]}
82 80
83 81
84[features] 82[features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 2c349e55e..f8908756d 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -5,9 +5,36 @@ use std::{env, fs};
5 5
6use proc_macro2::{Ident, TokenStream}; 6use proc_macro2::{Ident, TokenStream};
7use quote::{format_ident, quote}; 7use quote::{format_ident, quote};
8use stm32_metapac::metadata::{MemoryRegionKind, METADATA}; 8use stm32_metapac::metadata::ir::{BlockItemInner, Enum, FieldSet};
9use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA};
9 10
10fn main() { 11fn main() {
12 let target = env::var("TARGET").unwrap();
13
14 if target.starts_with("thumbv6m-") {
15 println!("cargo:rustc-cfg=cortex_m");
16 println!("cargo:rustc-cfg=armv6m");
17 } else if target.starts_with("thumbv7m-") {
18 println!("cargo:rustc-cfg=cortex_m");
19 println!("cargo:rustc-cfg=armv7m");
20 } else if target.starts_with("thumbv7em-") {
21 println!("cargo:rustc-cfg=cortex_m");
22 println!("cargo:rustc-cfg=armv7m");
23 println!("cargo:rustc-cfg=armv7em"); // (not currently used)
24 } else if target.starts_with("thumbv8m.base") {
25 println!("cargo:rustc-cfg=cortex_m");
26 println!("cargo:rustc-cfg=armv8m");
27 println!("cargo:rustc-cfg=armv8m_base");
28 } else if target.starts_with("thumbv8m.main") {
29 println!("cargo:rustc-cfg=cortex_m");
30 println!("cargo:rustc-cfg=armv8m");
31 println!("cargo:rustc-cfg=armv8m_main");
32 }
33
34 if target.ends_with("-eabihf") {
35 println!("cargo:rustc-cfg=has_fpu");
36 }
37
11 let chip_name = match env::vars() 38 let chip_name = match env::vars()
12 .map(|(a, _)| a) 39 .map(|(a, _)| a)
13 .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) 40 .filter(|x| x.starts_with("CARGO_FEATURE_STM32"))
@@ -50,12 +77,14 @@ fn main() {
50 // We *shouldn't* have singletons for these, but the HAL currently requires 77 // We *shouldn't* have singletons for these, but the HAL currently requires
51 // singletons, for using with RccPeripheral to enable/disable clocks to them. 78 // singletons, for using with RccPeripheral to enable/disable clocks to them.
52 "rcc" => { 79 "rcc" => {
53 if r.version.starts_with("h5") || r.version.starts_with("h7") || r.version.starts_with("f4") { 80 for pin in p.pins {
54 singletons.push("MCO1".to_string()); 81 if pin.signal.starts_with("MCO") {
55 singletons.push("MCO2".to_string()); 82 let name = pin.signal.replace('_', "").to_string();
56 } 83 if !singletons.contains(&name) {
57 if r.version.starts_with("l4") { 84 println!("cargo:rustc-cfg={}", name.to_ascii_lowercase());
58 singletons.push("MCO".to_string()); 85 singletons.push(name);
86 }
87 }
59 } 88 }
60 singletons.push(p.name.to_string()); 89 singletons.push(p.name.to_string());
61 } 90 }
@@ -91,6 +120,7 @@ fn main() {
91 struct SplitFeature { 120 struct SplitFeature {
92 feature_name: String, 121 feature_name: String,
93 pin_name_with_c: String, 122 pin_name_with_c: String,
123 #[cfg(feature = "_split-pins-enabled")]
94 pin_name_without_c: String, 124 pin_name_without_c: String,
95 } 125 }
96 126
@@ -359,6 +389,47 @@ fn main() {
359 } 389 }
360 390
361 // ======== 391 // ========
392 // Extract the rcc registers
393 let rcc_registers = METADATA
394 .peripherals
395 .iter()
396 .filter_map(|p| p.registers.as_ref())
397 .find(|r| r.kind == "rcc")
398 .unwrap();
399
400 // ========
401 // Generate rcc fieldset and enum maps
402 let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = {
403 let rcc_blocks = rcc_registers.ir.blocks.iter().find(|b| b.name == "Rcc").unwrap().items;
404 let rcc_fieldsets: HashMap<&str, &FieldSet> = rcc_registers.ir.fieldsets.iter().map(|f| (f.name, f)).collect();
405 let rcc_enums: HashMap<&str, &Enum> = rcc_registers.ir.enums.iter().map(|e| (e.name, e)).collect();
406
407 rcc_blocks
408 .iter()
409 .filter_map(|b| match &b.inner {
410 BlockItemInner::Register(register) => register.fieldset.map(|f| (b.name, f)),
411 _ => None,
412 })
413 .filter_map(|(b, f)| {
414 rcc_fieldsets.get(f).map(|f| {
415 (
416 b,
417 f.fields
418 .iter()
419 .filter_map(|f| {
420 let enumm = f.enumm?;
421 let enumm = rcc_enums.get(enumm)?;
422
423 Some((f.name, *enumm))
424 })
425 .collect(),
426 )
427 })
428 })
429 .collect()
430 };
431
432 // ========
362 // Generate RccPeripheral impls 433 // Generate RccPeripheral impls
363 434
364 let refcounted_peripherals = HashSet::from(["usart", "adc"]); 435 let refcounted_peripherals = HashSet::from(["usart", "adc"]);
@@ -377,10 +448,8 @@ fn main() {
377 let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); 448 let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase());
378 let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); 449 let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase());
379 quote! { 450 quote! {
380 critical_section::with(|_| { 451 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true));
381 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); 452 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false));
382 crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false));
383 });
384 } 453 }
385 } 454 }
386 None => TokenStream::new(), 455 None => TokenStream::new(),
@@ -397,9 +466,9 @@ fn main() {
397 466
398 let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" }; 467 let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
399 let pname = format_ident!("{}", p.name); 468 let pname = format_ident!("{}", p.name);
400 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); 469 let clk = format_ident!("{}", rcc.clock);
401 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); 470 let en_reg = format_ident!("{}", en.register);
402 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); 471 let set_en_field = format_ident!("set_{}", en.field);
403 472
404 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype) { 473 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype) {
405 let refcount_static = 474 let refcount_static =
@@ -425,31 +494,82 @@ fn main() {
425 (TokenStream::new(), TokenStream::new()) 494 (TokenStream::new(), TokenStream::new())
426 }; 495 };
427 496
497 let mux_supported = HashSet::from(["c0", "h5", "h50", "h7", "h7ab", "h7rm0433", "g4", "l4"])
498 .contains(rcc_registers.version);
499 let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
500 // restrict mux implementation to supported versions
501 if !mux_supported {
502 return None;
503 }
504
505 let mux = mux?;
506 let fieldset = rcc_enum_map.get(mux.register)?;
507 let enumm = fieldset.get(mux.field)?;
508
509 Some((mux, *enumm))
510 };
511
512 let clock_frequency = match mux_for(rcc.mux.as_ref()) {
513 Some((mux, rcc_enumm)) => {
514 let fieldset_name = format_ident!("{}", mux.register);
515 let field_name = format_ident!("{}", mux.field);
516 let enum_name = format_ident!("{}", rcc_enumm.name);
517
518 let match_arms: TokenStream = rcc_enumm
519 .variants
520 .iter()
521 .filter(|v| v.name != "DISABLE")
522 .map(|v| {
523 let variant_name = format_ident!("{}", v.name);
524 let clock_name = format_ident!("{}", v.name.to_ascii_lowercase());
525
526 if v.name.starts_with("HCLK") || v.name.starts_with("PCLK") || v.name == "SYS" {
527 quote! {
528 #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name },
529 }
530 } else {
531 quote! {
532 #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
533 }
534 }
535 })
536 .collect();
537
538 quote! {
539 use crate::pac::rcc::vals::#enum_name;
540
541 #[allow(unreachable_patterns)]
542 match crate::pac::RCC.#fieldset_name().read().#field_name() {
543 #match_arms
544
545 _ => unreachable!(),
546 }
547 }
548 }
549 None => quote! {
550 unsafe { crate::rcc::get_freqs().#clk }
551 },
552 };
553
428 g.extend(quote! { 554 g.extend(quote! {
429 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { 555 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
430 fn frequency() -> crate::time::Hertz { 556 fn frequency() -> crate::time::Hertz {
431 unsafe { crate::rcc::get_freqs().#clk } 557 #clock_frequency
432 } 558 }
433 fn enable() { 559 fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
434 critical_section::with(|_| { 560 #before_enable
435 #before_enable 561 #[cfg(feature = "low-power")]
436 #[cfg(feature = "low-power")] 562 crate::rcc::clock_refcount_add(_cs);
437 crate::rcc::clock_refcount_add(); 563 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
438 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); 564 #after_enable
439 #after_enable
440 })
441 }
442 fn disable() {
443 critical_section::with(|_| {
444 #before_disable
445 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
446 #[cfg(feature = "low-power")]
447 crate::rcc::clock_refcount_sub();
448 })
449 }
450 fn reset() {
451 #rst 565 #rst
452 } 566 }
567 fn disable_with_cs(_cs: critical_section::CriticalSection) {
568 #before_disable
569 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
570 #[cfg(feature = "low-power")]
571 crate::rcc::clock_refcount_sub(_cs);
572 }
453 } 573 }
454 574
455 impl crate::rcc::RccPeripheral for peripherals::#pname {} 575 impl crate::rcc::RccPeripheral for peripherals::#pname {}
@@ -457,12 +577,14 @@ fn main() {
457 } 577 }
458 } 578 }
459 579
460 let mut refcount_mod = TokenStream::new(); 580 let refcount_mod: TokenStream = refcount_statics
461 for refcount_static in refcount_statics { 581 .iter()
462 refcount_mod.extend(quote! { 582 .map(|refcount_static| {
463 pub(crate) static mut #refcount_static: u8 = 0; 583 quote! {
464 }); 584 pub(crate) static mut #refcount_static: u8 = 0;
465 } 585 }
586 })
587 .collect();
466 588
467 g.extend(quote! { 589 g.extend(quote! {
468 mod refcount_statics { 590 mod refcount_statics {
@@ -718,12 +840,17 @@ fn main() {
718 (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), 840 (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)),
719 (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), 841 (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)),
720 (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), 842 (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)),
721 (("quadspi", "BK1_IO0"), quote!(crate::qspi::D0Pin)), 843 (("quadspi", "BK1_IO0"), quote!(crate::qspi::BK1D0Pin)),
722 (("quadspi", "BK1_IO1"), quote!(crate::qspi::D1Pin)), 844 (("quadspi", "BK1_IO1"), quote!(crate::qspi::BK1D1Pin)),
723 (("quadspi", "BK1_IO2"), quote!(crate::qspi::D2Pin)), 845 (("quadspi", "BK1_IO2"), quote!(crate::qspi::BK1D2Pin)),
724 (("quadspi", "BK1_IO3"), quote!(crate::qspi::D3Pin)), 846 (("quadspi", "BK1_IO3"), quote!(crate::qspi::BK1D3Pin)),
847 (("quadspi", "BK1_NCS"), quote!(crate::qspi::BK1NSSPin)),
848 (("quadspi", "BK2_IO0"), quote!(crate::qspi::BK2D0Pin)),
849 (("quadspi", "BK2_IO1"), quote!(crate::qspi::BK2D1Pin)),
850 (("quadspi", "BK2_IO2"), quote!(crate::qspi::BK2D2Pin)),
851 (("quadspi", "BK2_IO3"), quote!(crate::qspi::BK2D3Pin)),
852 (("quadspi", "BK2_NCS"), quote!(crate::qspi::BK2NSSPin)),
725 (("quadspi", "CLK"), quote!(crate::qspi::SckPin)), 853 (("quadspi", "CLK"), quote!(crate::qspi::SckPin)),
726 (("quadspi", "BK1_NCS"), quote!(crate::qspi::NSSPin)),
727 ].into(); 854 ].into();
728 855
729 for p in METADATA.peripherals { 856 for p in METADATA.peripherals {
@@ -745,25 +872,8 @@ fn main() {
745 let af = pin.af.unwrap_or(0); 872 let af = pin.af.unwrap_or(0);
746 873
747 // MCO is special 874 // MCO is special
748 if pin.signal.starts_with("MCO_") { 875 if pin.signal.starts_with("MCO") {
749 // Supported in H7 only for now 876 peri = format_ident!("{}", pin.signal.replace('_', ""));
750 if regs.version.starts_with("h5")
751 || regs.version.starts_with("h7")
752 || regs.version.starts_with("f4")
753 {
754 peri = format_ident!("{}", pin.signal.replace('_', ""));
755 } else {
756 continue;
757 }
758 }
759
760 if pin.signal == "MCO" {
761 // Supported in H7 only for now
762 if regs.version.starts_with("l4") {
763 peri = format_ident!("MCO");
764 } else {
765 continue;
766 }
767 } 877 }
768 878
769 g.extend(quote! { 879 g.extend(quote! {
@@ -804,6 +914,20 @@ fn main() {
804 } 914 }
805 } 915 }
806 916
917 if regs.kind == "opamp" {
918 if !pin.signal.starts_with("VP") {
919 continue;
920 }
921
922 let peri = format_ident!("{}", p.name);
923 let pin_name = format_ident!("{}", pin.pin);
924 let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap();
925
926 g.extend(quote! {
927 impl_opamp_pin!( #peri, #pin_name, #ch);
928 })
929 }
930
807 // DAC is special 931 // DAC is special
808 if regs.kind == "dac" { 932 if regs.kind == "dac" {
809 let peri = format_ident!("{}", p.name); 933 let peri = format_ident!("{}", p.name);
@@ -889,6 +1013,97 @@ fn main() {
889 } 1013 }
890 1014
891 // ======== 1015 // ========
1016 // Generate Div/Mul impls for RCC prescalers/dividers/multipliers.
1017 for e in rcc_registers.ir.enums {
1018 fn is_rcc_name(e: &str) -> bool {
1019 match e {
1020 "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true,
1021 "Timpre" | "Pllrclkpre" => false,
1022 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
1023 _ => false,
1024 }
1025 }
1026
1027 #[derive(Copy, Clone, Debug)]
1028 struct Frac {
1029 num: u32,
1030 denom: u32,
1031 }
1032
1033 impl Frac {
1034 fn simplify(self) -> Self {
1035 let d = gcd(self.num, self.denom);
1036 Self {
1037 num: self.num / d,
1038 denom: self.denom / d,
1039 }
1040 }
1041 }
1042
1043 fn gcd(a: u32, b: u32) -> u32 {
1044 if b == 0 {
1045 return a;
1046 }
1047 gcd(b, a % b)
1048 }
1049
1050 fn parse_num(n: &str) -> Result<Frac, ()> {
1051 for prefix in ["DIV", "MUL"] {
1052 if let Some(n) = n.strip_prefix(prefix) {
1053 let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32;
1054 let mantissa = n.replace('_', "").parse().map_err(|_| ())?;
1055 let f = Frac {
1056 num: mantissa,
1057 denom: 10u32.pow(exponent),
1058 };
1059 return Ok(f.simplify());
1060 }
1061 }
1062 Err(())
1063 }
1064
1065 if is_rcc_name(e.name) {
1066 let enum_name = format_ident!("{}", e.name);
1067 let mut muls = Vec::new();
1068 let mut divs = Vec::new();
1069 for v in e.variants {
1070 let Ok(val) = parse_num(v.name) else {
1071 panic!("could not parse mul/div. enum={} variant={}", e.name, v.name)
1072 };
1073 let variant_name = format_ident!("{}", v.name);
1074 let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name);
1075 let num = val.num;
1076 let denom = val.denom;
1077 muls.push(quote!(#variant => self * #num / #denom,));
1078 divs.push(quote!(#variant => self * #denom / #num,));
1079 }
1080
1081 g.extend(quote! {
1082 impl core::ops::Div<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz {
1083 type Output = crate::time::Hertz;
1084 fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output {
1085 match rhs {
1086 #(#divs)*
1087 #[allow(unreachable_patterns)]
1088 _ => unreachable!(),
1089 }
1090 }
1091 }
1092 impl core::ops::Mul<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz {
1093 type Output = crate::time::Hertz;
1094 fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output {
1095 match rhs {
1096 #(#muls)*
1097 #[allow(unreachable_patterns)]
1098 _ => unreachable!(),
1099 }
1100 }
1101 }
1102 });
1103 }
1104 }
1105
1106 // ========
892 // Write foreach_foo! macrotables 1107 // Write foreach_foo! macrotables
893 1108
894 let mut flash_regions_table: Vec<Vec<String>> = Vec::new(); 1109 let mut flash_regions_table: Vec<Vec<String>> = Vec::new();
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index c13264819..ad0f13826 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -51,8 +51,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
51impl<'d, T: Instance> Adc<'d, T> { 51impl<'d, T: Instance> Adc<'d, T> {
52 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 52 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
53 into_ref!(adc); 53 into_ref!(adc);
54 T::enable(); 54 T::enable_and_reset();
55 T::reset();
56 T::regs().cr2().modify(|reg| reg.set_adon(true)); 55 T::regs().cr2().modify(|reg| reg.set_adon(true));
57 56
58 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) 57 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index 7c13f8106..6f59c230f 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -64,8 +64,7 @@ impl<'d, T: Instance> Adc<'d, T> {
64 64
65 into_ref!(adc); 65 into_ref!(adc);
66 66
67 T::enable(); 67 T::enable_and_reset();
68 T::reset();
69 68
70 // Enable the adc regulator 69 // Enable the adc regulator
71 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE)); 70 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE));
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 365738a31..3e2980bf4 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -74,9 +74,9 @@ pub(crate) mod sealed {
74 } 74 }
75} 75}
76 76
77#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3)))] 77#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0)))]
78pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 78pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
79#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3))] 79#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0))]
80pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 80pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
81 81
82pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 82pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index fded26e40..852b027df 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -61,8 +61,7 @@ impl<'d, T: Instance> Adc<'d, T> {
61 delay: &mut impl DelayUs<u32>, 61 delay: &mut impl DelayUs<u32>,
62 ) -> Self { 62 ) -> Self {
63 into_ref!(adc); 63 into_ref!(adc);
64 T::enable(); 64 T::enable_and_reset();
65 T::reset();
66 65
67 // Delay 1μs when using HSI14 as the ADC clock. 66 // Delay 1μs when using HSI14 as the ADC clock.
68 // 67 //
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index a669013c9..eda1324de 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -95,8 +95,7 @@ where
95{ 95{
96 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 96 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
97 into_ref!(adc); 97 into_ref!(adc);
98 T::enable(); 98 T::enable_and_reset();
99 T::reset();
100 99
101 let presc = Prescaler::from_pclk2(T::frequency()); 100 let presc = Prescaler::from_pclk2(T::frequency());
102 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); 101 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 011ecc281..281a99f72 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -9,19 +9,6 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
9/// VREF voltage used for factory calibration of VREFINTCAL register. 9/// VREF voltage used for factory calibration of VREFINTCAL register.
10pub const VREF_CALIB_MV: u32 = 3000; 10pub const VREF_CALIB_MV: u32 = 3000;
11 11
12/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock
13/// configuration.
14fn enable() {
15 critical_section::with(|_| {
16 #[cfg(any(stm32h7, stm32wl))]
17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
18 #[cfg(stm32g0)]
19 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true));
20 #[cfg(any(stm32l4, stm32l5, stm32wb))]
21 crate::pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
22 });
23}
24
25pub struct VrefInt; 12pub struct VrefInt;
26impl<T: Instance> AdcPin<T> for VrefInt {} 13impl<T: Instance> AdcPin<T> for VrefInt {}
27impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { 14impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
@@ -61,7 +48,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
61impl<'d, T: Instance> Adc<'d, T> { 48impl<'d, T: Instance> Adc<'d, T> {
62 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 49 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
63 into_ref!(adc); 50 into_ref!(adc);
64 enable(); 51 T::enable_and_reset();
65 T::regs().cr().modify(|reg| { 52 T::regs().cr().modify(|reg| {
66 #[cfg(not(adc_g0))] 53 #[cfg(not(adc_g0))]
67 reg.set_deeppwd(false); 54 reg.set_deeppwd(false);
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 655c0cb6a..d74617cb3 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -127,8 +127,7 @@ impl Prescaler {
127impl<'d, T: Instance> Adc<'d, T> { 127impl<'d, T: Instance> Adc<'d, T> {
128 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { 128 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
129 embassy_hal_internal::into_ref!(adc); 129 embassy_hal_internal::into_ref!(adc);
130 T::enable(); 130 T::enable_and_reset();
131 T::reset();
132 131
133 let prescaler = Prescaler::from_ker_ck(T::frequency()); 132 let prescaler = Prescaler::from_ker_ck(T::frequency());
134 133
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 7ad13cece..0d4bf692d 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -136,8 +136,7 @@ impl<'d, T: Instance> Can<'d, T> {
136 rx.set_as_af(rx.af_num(), AFType::Input); 136 rx.set_as_af(rx.af_num(), AFType::Input);
137 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 137 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
138 138
139 T::enable(); 139 T::enable_and_reset();
140 T::reset();
141 140
142 { 141 {
143 use crate::pac::can::vals::{Errie, Fmpie, Tmeie}; 142 use crate::pac::can::vals::{Errie, Fmpie, Tmeie};
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index 154f2eb91..c0f580830 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -16,9 +16,7 @@ impl<'d> Crc<'d> {
16 16
17 // Note: enable and reset come from RccPeripheral. 17 // Note: enable and reset come from RccPeripheral.
18 // enable CRC clock in RCC. 18 // enable CRC clock in RCC.
19 CRC::enable(); 19 CRC::enable_and_reset();
20 // Reset CRC to default values.
21 CRC::reset();
22 // Peripheral the peripheral 20 // Peripheral the peripheral
23 let mut instance = Self { _peri: peripheral }; 21 let mut instance = Self { _peri: peripheral };
24 instance.reset(); 22 instance.reset();
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index de0c08755..b36f6018c 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -69,16 +69,13 @@ impl<'d> Crc<'d> {
69 /// Instantiates the CRC32 peripheral and initializes it to default values. 69 /// Instantiates the CRC32 peripheral and initializes it to default values.
70 pub fn new(peripheral: impl Peripheral<P = CRC> + 'd, config: Config) -> Self { 70 pub fn new(peripheral: impl Peripheral<P = CRC> + 'd, config: Config) -> Self {
71 // Note: enable and reset come from RccPeripheral. 71 // Note: enable and reset come from RccPeripheral.
72 // enable CRC clock in RCC. 72 // reset to default values and enable CRC clock in RCC.
73 CRC::enable(); 73 CRC::enable_and_reset();
74 // Reset CRC to default values.
75 CRC::reset();
76 into_ref!(peripheral); 74 into_ref!(peripheral);
77 let mut instance = Self { 75 let mut instance = Self {
78 _peripheral: peripheral, 76 _peripheral: peripheral,
79 _config: config, 77 _config: config,
80 }; 78 };
81 CRC::reset();
82 instance.reconfigure(); 79 instance.reconfigure();
83 instance.reset(); 80 instance.reset();
84 instance 81 instance
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index a2040b857..3d1a820ed 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -11,7 +11,7 @@ use crate::{peripherals, Peripheral};
11 11
12#[derive(Debug, Copy, Clone, Eq, PartialEq)] 12#[derive(Debug, Copy, Clone, Eq, PartialEq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))] 13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14/// Curstom Errors 14/// Custom Errors
15pub enum Error { 15pub enum Error {
16 UnconfiguredChannel, 16 UnconfiguredChannel,
17 InvalidValue, 17 InvalidValue,
@@ -255,8 +255,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
255 ) -> Self { 255 ) -> Self {
256 pin.set_as_analog(); 256 pin.set_as_analog();
257 into_ref!(peri, dma); 257 into_ref!(peri, dma);
258 T::enable(); 258 T::enable_and_reset();
259 T::reset();
260 259
261 let mut dac = Self { _peri: peri, dma }; 260 let mut dac = Self { _peri: peri, dma };
262 261
@@ -366,8 +365,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
366 ) -> Self { 365 ) -> Self {
367 pin.set_as_analog(); 366 pin.set_as_analog();
368 into_ref!(_peri, dma); 367 into_ref!(_peri, dma);
369 T::enable(); 368 T::enable_and_reset();
370 T::reset();
371 369
372 let mut dac = Self { 370 let mut dac = Self {
373 phantom: PhantomData, 371 phantom: PhantomData,
@@ -483,8 +481,7 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
483 pin_ch1.set_as_analog(); 481 pin_ch1.set_as_analog();
484 pin_ch2.set_as_analog(); 482 pin_ch2.set_as_analog();
485 into_ref!(peri, dma_ch1, dma_ch2); 483 into_ref!(peri, dma_ch1, dma_ch2);
486 T::enable(); 484 T::enable_and_reset();
487 T::reset();
488 485
489 let mut dac_ch1 = DacCh1 { 486 let mut dac_ch1 = DacCh1 {
490 _peri: peri, 487 _peri: peri,
@@ -563,35 +560,26 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
563 560
564foreach_peripheral!( 561foreach_peripheral!(
565 (dac, $inst:ident) => { 562 (dac, $inst:ident) => {
566 // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented 563 // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented
567 #[cfg(rcc_h7)] 564 #[cfg(any(rcc_h7, rcc_h7rm0433))]
568 impl crate::rcc::sealed::RccPeripheral for peripherals::$inst { 565 impl crate::rcc::sealed::RccPeripheral for peripherals::$inst {
569 fn frequency() -> crate::time::Hertz { 566 fn frequency() -> crate::time::Hertz {
570 critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) 567 critical_section::with(|_| unsafe { crate::rcc::get_freqs().pclk1 })
571 } 568 }
572 569
573 fn reset() { 570 fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
574 critical_section::with(|_| { 571 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true));
575 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); 572 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false));
576 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); 573 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
577 }) 574 }
578 } 575
579 576 fn disable_with_cs(_cs: critical_section::CriticalSection) {
580 fn enable() { 577 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false))
581 critical_section::with(|_| { 578 }
582 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); 579 }
583 }) 580
584 } 581 #[cfg(any(rcc_h7, rcc_h7rm0433))]
585 582 impl crate::rcc::RccPeripheral for peripherals::$inst {}
586 fn disable() {
587 critical_section::with(|_| {
588 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false))
589 })
590 }
591 }
592
593 #[cfg(rcc_h7)]
594 impl crate::rcc::RccPeripheral for peripherals::$inst {}
595 583
596 impl crate::dac::sealed::Instance for peripherals::$inst { 584 impl crate::dac::sealed::Instance for peripherals::$inst {
597 fn regs() -> &'static crate::pac::dac::Dac { 585 fn regs() -> &'static crate::pac::dac::Dac {
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 7497f4aaa..b12230794 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -330,8 +330,7 @@ where
330 use_embedded_synchronization: bool, 330 use_embedded_synchronization: bool,
331 edm: u8, 331 edm: u8,
332 ) -> Self { 332 ) -> Self {
333 T::reset(); 333 T::enable_and_reset();
334 T::enable();
335 334
336 peri.regs().cr().modify(|r| { 335 peri.regs().cr().modify(|r| {
337 r.set_cm(true); // disable continuous mode (snapshot mode) 336 r.set_cm(true); // disable continuous mode (snapshot mode)
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 20ff29bef..a7422f66b 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -2,10 +2,9 @@
2 2
3use core::future::Future; 3use core::future::Future;
4use core::pin::Pin; 4use core::pin::Pin;
5use core::sync::atomic::{fence, Ordering}; 5use core::sync::atomic::{fence, AtomicUsize, Ordering};
6use core::task::{Context, Poll, Waker}; 6use core::task::{Context, Poll, Waker};
7 7
8use atomic_polyfill::AtomicUsize;
9use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 8use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
11 10
@@ -78,10 +77,10 @@ impl State {
78static STATE: State = State::new(); 77static STATE: State = State::new();
79 78
80/// safety: must be called only once 79/// safety: must be called only once
81pub(crate) unsafe fn init(irq_priority: Priority) { 80pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) {
82 foreach_interrupt! { 81 foreach_interrupt! {
83 ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { 82 ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => {
84 crate::interrupt::typelevel::$irq::set_priority(irq_priority); 83 crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority);
85 crate::interrupt::typelevel::$irq::enable(); 84 crate::interrupt::typelevel::$irq::enable();
86 }; 85 };
87 } 86 }
@@ -127,7 +126,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index
127 } else if isr.tcif(channel_num) && cr.read().tcie() { 126 } else if isr.tcif(channel_num) && cr.read().tcie() {
128 // Acknowledge transfer complete interrupt 127 // Acknowledge transfer complete interrupt
129 dma.ifcr().write(|w| w.set_tcif(channel_num, true)); 128 dma.ifcr().write(|w| w.set_tcif(channel_num, true));
129 #[cfg(not(armv6m))]
130 STATE.complete_count[index].fetch_add(1, Ordering::Release); 130 STATE.complete_count[index].fetch_add(1, Ordering::Release);
131 #[cfg(armv6m)]
132 critical_section::with(|_| {
133 let x = STATE.complete_count[index].load(Ordering::Relaxed);
134 STATE.complete_count[index].store(x + 1, Ordering::Release);
135 })
131 } else { 136 } else {
132 return; 137 return;
133 } 138 }
@@ -391,7 +396,14 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
391 } 396 }
392 397
393 fn reset_complete_count(&mut self) -> usize { 398 fn reset_complete_count(&mut self) -> usize {
394 STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel) 399 #[cfg(not(armv6m))]
400 return STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel);
401 #[cfg(armv6m)]
402 return critical_section::with(|_| {
403 let x = STATE.complete_count[self.0.index()].load(Ordering::Acquire);
404 STATE.complete_count[self.0.index()].store(0, Ordering::Release);
405 x
406 });
395 } 407 }
396 408
397 fn set_waker(&mut self, waker: &Waker) { 409 fn set_waker(&mut self, waker: &Waker) {
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 5033ae477..cce0407c1 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -154,10 +154,10 @@ impl State {
154static STATE: State = State::new(); 154static STATE: State = State::new();
155 155
156/// safety: must be called only once 156/// safety: must be called only once
157pub(crate) unsafe fn init(irq_priority: Priority) { 157pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) {
158 foreach_interrupt! { 158 foreach_interrupt! {
159 ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { 159 ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => {
160 interrupt::typelevel::$irq::set_priority(irq_priority); 160 interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority);
161 interrupt::typelevel::$irq::enable(); 161 interrupt::typelevel::$irq::enable();
162 }; 162 };
163 } 163 }
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
index 36fc03403..20601dc86 100644
--- a/embassy-stm32/src/dma/dmamux.rs
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -47,6 +47,6 @@ foreach_dma_channel! {
47} 47}
48 48
49/// safety: must be called only once 49/// safety: must be called only once
50pub(crate) unsafe fn init() { 50pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) {
51 crate::_generated::init_dmamux(); 51 crate::_generated::init_dmamux();
52} 52}
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index 97cc200d7..b811da1fb 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -53,10 +53,10 @@ impl State {
53static STATE: State = State::new(); 53static STATE: State = State::new();
54 54
55/// safety: must be called only once 55/// safety: must be called only once
56pub(crate) unsafe fn init(irq_priority: Priority) { 56pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) {
57 foreach_interrupt! { 57 foreach_interrupt! {
58 ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { 58 ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => {
59 crate::interrupt::typelevel::$irq::set_priority(irq_priority); 59 crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority);
60 crate::interrupt::typelevel::$irq::enable(); 60 crate::interrupt::typelevel::$irq::enable();
61 }; 61 };
62 } 62 }
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 4f1a58ae2..29fced8fc 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -56,16 +56,17 @@ pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) {
56 56
57// safety: must be called only once at startup 57// safety: must be called only once at startup
58pub(crate) unsafe fn init( 58pub(crate) unsafe fn init(
59 cs: critical_section::CriticalSection,
59 #[cfg(bdma)] bdma_priority: Priority, 60 #[cfg(bdma)] bdma_priority: Priority,
60 #[cfg(dma)] dma_priority: Priority, 61 #[cfg(dma)] dma_priority: Priority,
61 #[cfg(gpdma)] gpdma_priority: Priority, 62 #[cfg(gpdma)] gpdma_priority: Priority,
62) { 63) {
63 #[cfg(bdma)] 64 #[cfg(bdma)]
64 bdma::init(bdma_priority); 65 bdma::init(cs, bdma_priority);
65 #[cfg(dma)] 66 #[cfg(dma)]
66 dma::init(dma_priority); 67 dma::init(cs, dma_priority);
67 #[cfg(gpdma)] 68 #[cfg(gpdma)]
68 gpdma::init(gpdma_priority); 69 gpdma::init(cs, gpdma_priority);
69 #[cfg(dmamux)] 70 #[cfg(dmamux)]
70 dmamux::init(); 71 dmamux::init(cs);
71} 72}
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs
index 2ed46ca2c..1e1094a1c 100644
--- a/embassy-stm32/src/eth/generic_smi.rs
+++ b/embassy-stm32/src/eth/generic_smi.rs
@@ -41,39 +41,40 @@ mod phy_consts {
41} 41}
42use self::phy_consts::*; 42use self::phy_consts::*;
43 43
44/// Generic SMI Ethernet PHY 44/// Generic SMI Ethernet PHY implementation
45pub struct GenericSMI { 45pub struct GenericSMI {
46 phy_addr: u8,
46 #[cfg(feature = "time")] 47 #[cfg(feature = "time")]
47 poll_interval: Duration, 48 poll_interval: Duration,
48 #[cfg(not(feature = "time"))]
49 _private: (),
50} 49}
51 50
52impl GenericSMI { 51impl GenericSMI {
53 pub fn new() -> Self { 52 /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication
53 pub fn new(phy_addr: u8) -> Self {
54 Self { 54 Self {
55 phy_addr,
55 #[cfg(feature = "time")] 56 #[cfg(feature = "time")]
56 poll_interval: Duration::from_millis(500), 57 poll_interval: Duration::from_millis(500),
57 #[cfg(not(feature = "time"))]
58 _private: (),
59 } 58 }
60 } 59 }
61} 60}
62 61
63unsafe impl PHY for GenericSMI { 62unsafe impl PHY for GenericSMI {
64 /// Reset PHY and wait for it to come out of reset.
65 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { 63 fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) {
66 sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); 64 sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);
67 while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} 65 while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {}
68 } 66 }
69 67
70 /// PHY initialisation.
71 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) { 68 fn phy_init<S: StationManagement>(&mut self, sm: &mut S) {
72 // Clear WU CSR 69 // Clear WU CSR
73 self.smi_write_ext(sm, PHY_REG_WUCSR, 0); 70 self.smi_write_ext(sm, PHY_REG_WUCSR, 0);
74 71
75 // Enable auto-negotiation 72 // Enable auto-negotiation
76 sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); 73 sm.smi_write(
74 self.phy_addr,
75 PHY_REG_BCR,
76 PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M,
77 );
77 } 78 }
78 79
79 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool { 80 fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool {
@@ -83,7 +84,7 @@ unsafe impl PHY for GenericSMI {
83 #[cfg(feature = "time")] 84 #[cfg(feature = "time")]
84 let _ = Timer::after(self.poll_interval).poll_unpin(cx); 85 let _ = Timer::after(self.poll_interval).poll_unpin(cx);
85 86
86 let bsr = sm.smi_read(PHY_REG_BSR); 87 let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR);
87 88
88 // No link without autonegotiate 89 // No link without autonegotiate
89 if bsr & PHY_REG_BSR_ANDONE == 0 { 90 if bsr & PHY_REG_BSR_ANDONE == 0 {
@@ -108,9 +109,9 @@ impl GenericSMI {
108 109
109 // Writes a value to an extended PHY register in MMD address space 110 // Writes a value to an extended PHY register in MMD address space
110 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { 111 fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) {
111 sm.smi_write(PHY_REG_CTL, 0x0003); // set address 112 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address
112 sm.smi_write(PHY_REG_ADDAR, reg_addr); 113 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr);
113 sm.smi_write(PHY_REG_CTL, 0x4003); // set data 114 sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data
114 sm.smi_write(PHY_REG_ADDAR, reg_data); 115 sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data);
115 } 116 }
116} 117}
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index 1e057235a..556aadd73 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -134,9 +134,9 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> {
134/// The methods cannot move out of self 134/// The methods cannot move out of self
135pub unsafe trait StationManagement { 135pub unsafe trait StationManagement {
136 /// Read a register over SMI. 136 /// Read a register over SMI.
137 fn smi_read(&mut self, reg: u8) -> u16; 137 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16;
138 /// Write a register over SMI. 138 /// Write a register over SMI.
139 fn smi_write(&mut self, reg: u8, val: u16); 139 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16);
140} 140}
141 141
142/// Traits for an Ethernet PHY 142/// Traits for an Ethernet PHY
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 4d19103dd..13e53f687 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -107,7 +107,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
107 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd, 107 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
108 phy: P, 108 phy: P,
109 mac_addr: [u8; 6], 109 mac_addr: [u8; 6],
110 phy_addr: u8,
111 ) -> Self { 110 ) -> Self {
112 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 111 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
113 112
@@ -192,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
192 // TODO MTU size setting not found for v1 ethernet, check if correct 191 // TODO MTU size setting not found for v1 ethernet, check if correct
193 192
194 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called 193 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
195 let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; 194 let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
196 let hclk_mhz = hclk.0 / 1_000_000; 195 let hclk_mhz = hclk.0 / 1_000_000;
197 196
198 // Set the MDC clock frequency in the range 1MHz - 2.5MHz 197 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
@@ -227,7 +226,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
227 station_management: EthernetStationManagement { 226 station_management: EthernetStationManagement {
228 peri: PhantomData, 227 peri: PhantomData,
229 clock_range: clock_range, 228 clock_range: clock_range,
230 phy_addr: phy_addr,
231 }, 229 },
232 mac_addr, 230 mac_addr,
233 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), 231 tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf),
@@ -271,15 +269,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
271pub struct EthernetStationManagement<T: Instance> { 269pub struct EthernetStationManagement<T: Instance> {
272 peri: PhantomData<T>, 270 peri: PhantomData<T>,
273 clock_range: Cr, 271 clock_range: Cr,
274 phy_addr: u8,
275} 272}
276 273
277unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 274unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
278 fn smi_read(&mut self, reg: u8) -> u16 { 275 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
279 let mac = ETH.ethernet_mac(); 276 let mac = ETH.ethernet_mac();
280 277
281 mac.macmiiar().modify(|w| { 278 mac.macmiiar().modify(|w| {
282 w.set_pa(self.phy_addr); 279 w.set_pa(phy_addr);
283 w.set_mr(reg); 280 w.set_mr(reg);
284 w.set_mw(Mw::READ); // read operation 281 w.set_mw(Mw::READ); // read operation
285 w.set_cr(self.clock_range); 282 w.set_cr(self.clock_range);
@@ -289,12 +286,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
289 mac.macmiidr().read().md() 286 mac.macmiidr().read().md()
290 } 287 }
291 288
292 fn smi_write(&mut self, reg: u8, val: u16) { 289 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
293 let mac = ETH.ethernet_mac(); 290 let mac = ETH.ethernet_mac();
294 291
295 mac.macmiidr().write(|w| w.set_md(val)); 292 mac.macmiidr().write(|w| w.set_md(val));
296 mac.macmiiar().modify(|w| { 293 mac.macmiiar().modify(|w| {
297 w.set_pa(self.phy_addr); 294 w.set_pa(phy_addr);
298 w.set_mr(reg); 295 w.set_mr(reg);
299 w.set_mw(Mw::WRITE); // write 296 w.set_mw(Mw::WRITE); // write
300 w.set_cr(self.clock_range); 297 w.set_cr(self.clock_range);
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 6efd40e3e..c77155fea 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -71,7 +71,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
71 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd, 71 tx_en: impl Peripheral<P = impl TXEnPin<T>> + 'd,
72 phy: P, 72 phy: P,
73 mac_addr: [u8; 6], 73 mac_addr: [u8; 6],
74 phy_addr: u8,
75 ) -> Self { 74 ) -> Self {
76 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 75 into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
77 76
@@ -165,7 +164,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
165 }); 164 });
166 165
167 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called 166 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
168 let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; 167 let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
169 let hclk_mhz = hclk.0 / 1_000_000; 168 let hclk_mhz = hclk.0 / 1_000_000;
170 169
171 // Set the MDC clock frequency in the range 1MHz - 2.5MHz 170 // Set the MDC clock frequency in the range 1MHz - 2.5MHz
@@ -202,7 +201,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
202 station_management: EthernetStationManagement { 201 station_management: EthernetStationManagement {
203 peri: PhantomData, 202 peri: PhantomData,
204 clock_range: clock_range, 203 clock_range: clock_range,
205 phy_addr: phy_addr,
206 }, 204 },
207 mac_addr, 205 mac_addr,
208 }; 206 };
@@ -242,15 +240,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
242pub struct EthernetStationManagement<T: Instance> { 240pub struct EthernetStationManagement<T: Instance> {
243 peri: PhantomData<T>, 241 peri: PhantomData<T>,
244 clock_range: u8, 242 clock_range: u8,
245 phy_addr: u8,
246} 243}
247 244
248unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { 245unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
249 fn smi_read(&mut self, reg: u8) -> u16 { 246 fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 {
250 let mac = ETH.ethernet_mac(); 247 let mac = ETH.ethernet_mac();
251 248
252 mac.macmdioar().modify(|w| { 249 mac.macmdioar().modify(|w| {
253 w.set_pa(self.phy_addr); 250 w.set_pa(phy_addr);
254 w.set_rda(reg); 251 w.set_rda(reg);
255 w.set_goc(0b11); // read 252 w.set_goc(0b11); // read
256 w.set_cr(self.clock_range); 253 w.set_cr(self.clock_range);
@@ -260,12 +257,12 @@ unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
260 mac.macmdiodr().read().md() 257 mac.macmdiodr().read().md()
261 } 258 }
262 259
263 fn smi_write(&mut self, reg: u8, val: u16) { 260 fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) {
264 let mac = ETH.ethernet_mac(); 261 let mac = ETH.ethernet_mac();
265 262
266 mac.macmdiodr().write(|w| w.set_md(val)); 263 mac.macmdiodr().write(|w| w.set_md(val));
267 mac.macmdioar().modify(|w| { 264 mac.macmdioar().modify(|w| {
268 w.set_pa(self.phy_addr); 265 w.set_pa(phy_addr);
269 w.set_rda(reg); 266 w.set_rda(reg);
270 w.set_goc(0b01); // write 267 w.set_goc(0b01); // write
271 w.set_cr(self.clock_range); 268 w.set_cr(self.clock_range);
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 62f321709..538791a51 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -367,7 +367,7 @@ macro_rules! enable_irq {
367} 367}
368 368
369/// safety: must be called only once 369/// safety: must be called only once
370pub(crate) unsafe fn init() { 370pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) {
371 use crate::interrupt::typelevel::Interrupt; 371 use crate::interrupt::typelevel::Interrupt;
372 372
373 foreach_exti_irq!(enable_irq); 373 foreach_exti_irq!(enable_irq);
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs
index d011522be..1ab8435a0 100644
--- a/embassy-stm32/src/flash/f0.rs
+++ b/embassy-stm32/src/flash/f0.rs
@@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() {
19} 19}
20 20
21pub(crate) unsafe fn unlock() { 21pub(crate) unsafe fn unlock() {
22 pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); 22 if pac::FLASH.cr().read().lock() {
23 pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); 23 pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123));
24 pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB));
25 }
24} 26}
25 27
26pub(crate) unsafe fn enable_blocking_write() { 28pub(crate) unsafe fn enable_blocking_write() {
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs
index 065369f64..7e6d7ca26 100644
--- a/embassy-stm32/src/flash/f3.rs
+++ b/embassy-stm32/src/flash/f3.rs
@@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() {
19} 19}
20 20
21pub(crate) unsafe fn unlock() { 21pub(crate) unsafe fn unlock() {
22 pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); 22 if pac::FLASH.cr().read().lock() {
23 pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); 23 pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123));
24 pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB));
25 }
24} 26}
25 27
26pub(crate) unsafe fn enable_blocking_write() { 28pub(crate) unsafe fn enable_blocking_write() {
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 913950fe5..81deaa179 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -228,8 +228,10 @@ pub(crate) unsafe fn lock() {
228} 228}
229 229
230pub(crate) unsafe fn unlock() { 230pub(crate) unsafe fn unlock() {
231 pac::FLASH.keyr().write(|w| w.set_key(0x45670123)); 231 if pac::FLASH.cr().read().lock() {
232 pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); 232 pac::FLASH.keyr().write(|w| w.set_key(0x45670123));
233 pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB));
234 }
233} 235}
234 236
235pub(crate) unsafe fn enable_write() { 237pub(crate) unsafe fn enable_write() {
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs
index 3a5bdf9c5..b52231ca8 100644
--- a/embassy-stm32/src/flash/f7.rs
+++ b/embassy-stm32/src/flash/f7.rs
@@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() {
19} 19}
20 20
21pub(crate) unsafe fn unlock() { 21pub(crate) unsafe fn unlock() {
22 pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123)); 22 if pac::FLASH.cr().read().lock() {
23 pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); 23 pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123));
24 pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB));
25 }
24} 26}
25 27
26pub(crate) unsafe fn enable_blocking_write() { 28pub(crate) unsafe fn enable_blocking_write() {
diff --git a/embassy-stm32/src/flash/g0.rs b/embassy-stm32/src/flash/g0.rs
index 3a4576016..19a388970 100644
--- a/embassy-stm32/src/flash/g0.rs
+++ b/embassy-stm32/src/flash/g0.rs
@@ -24,8 +24,10 @@ pub(crate) unsafe fn unlock() {
24 while pac::FLASH.sr().read().bsy() {} 24 while pac::FLASH.sr().read().bsy() {}
25 25
26 // Unlock flash 26 // Unlock flash
27 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); 27 if pac::FLASH.cr().read().lock() {
28 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); 28 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123));
29 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB));
30 }
29} 31}
30 32
31pub(crate) unsafe fn enable_blocking_write() { 33pub(crate) unsafe fn enable_blocking_write() {
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs
index 625bf13fc..b064fd6ea 100644
--- a/embassy-stm32/src/flash/h7.rs
+++ b/embassy-stm32/src/flash/h7.rs
@@ -26,11 +26,15 @@ pub(crate) unsafe fn lock() {
26} 26}
27 27
28pub(crate) unsafe fn unlock() { 28pub(crate) unsafe fn unlock() {
29 pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0x4567_0123)); 29 if pac::FLASH.bank(0).cr().read().lock() {
30 pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); 30 pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0x4567_0123));
31 pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0xCDEF_89AB));
32 }
31 if is_dual_bank() { 33 if is_dual_bank() {
32 pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0x4567_0123)); 34 if pac::FLASH.bank(1).cr().read().lock() {
33 pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); 35 pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0x4567_0123));
36 pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0xCDEF_89AB));
37 }
34 } 38 }
35} 39}
36 40
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs
index 24dcf99bc..1db0da923 100644
--- a/embassy-stm32/src/flash/l.rs
+++ b/embassy-stm32/src/flash/l.rs
@@ -28,17 +28,23 @@ pub(crate) unsafe fn lock() {
28pub(crate) unsafe fn unlock() { 28pub(crate) unsafe fn unlock() {
29 #[cfg(any(flash_wl, flash_wb, flash_l4))] 29 #[cfg(any(flash_wl, flash_wb, flash_l4))]
30 { 30 {
31 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); 31 if pac::FLASH.cr().read().lock() {
32 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); 32 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123));
33 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB));
34 }
33 } 35 }
34 36
35 #[cfg(any(flash_l0, flash_l1))] 37 #[cfg(any(flash_l0, flash_l1))]
36 { 38 {
37 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF)); 39 if pac::FLASH.pecr().read().pelock() {
38 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405)); 40 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF));
41 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405));
42 }
39 43
40 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); 44 if pac::FLASH.pecr().read().prglock() {
41 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516)); 45 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF));
46 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516));
47 }
42 } 48 }
43} 49}
44 50
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 177e66a91..d6e25996c 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -19,8 +19,7 @@ where
19 const REGISTERS: *const () = T::REGS.as_ptr() as *const _; 19 const REGISTERS: *const () = T::REGS.as_ptr() as *const _;
20 20
21 fn enable(&mut self) { 21 fn enable(&mut self) {
22 <T as crate::rcc::sealed::RccPeripheral>::enable(); 22 T::enable_and_reset();
23 <T as crate::rcc::sealed::RccPeripheral>::reset();
24 } 23 }
25 24
26 fn memory_controller_enable(&mut self) { 25 fn memory_controller_enable(&mut self) {
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index c709d46da..e1702b008 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -1,6 +1,7 @@
1#![macro_use] 1#![macro_use]
2use core::convert::Infallible; 2use core::convert::Infallible;
3 3
4use critical_section::CriticalSection;
4use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; 5use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
5 6
6use crate::pac::gpio::{self, vals}; 7use crate::pac::gpio::{self, vals};
@@ -757,9 +758,9 @@ foreach_pin!(
757 }; 758 };
758); 759);
759 760
760pub(crate) unsafe fn init() { 761pub(crate) unsafe fn init(_cs: CriticalSection) {
761 #[cfg(afio)] 762 #[cfg(afio)]
762 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable(); 763 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs);
763 764
764 crate::_generated::init_gpio(); 765 crate::_generated::init_gpio();
765} 766}
@@ -974,6 +975,18 @@ mod eh1 {
974 type Error = Infallible; 975 type Error = Infallible;
975 } 976 }
976 977
978 impl<'d, T: Pin> InputPin for OutputOpenDrain<'d, T> {
979 #[inline]
980 fn is_high(&self) -> Result<bool, Self::Error> {
981 Ok(self.is_high())
982 }
983
984 #[inline]
985 fn is_low(&self) -> Result<bool, Self::Error> {
986 Ok(self.is_low())
987 }
988 }
989
977 impl<'d, T: Pin> OutputPin for OutputOpenDrain<'d, T> { 990 impl<'d, T: Pin> OutputPin for OutputOpenDrain<'d, T> {
978 #[inline] 991 #[inline]
979 fn set_high(&mut self) -> Result<(), Self::Error> { 992 fn set_high(&mut self) -> Result<(), Self::Error> {
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index c47b0c092..17096d48c 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -157,8 +157,7 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
157 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { 157 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
158 into_ref!(tim); 158 into_ref!(tim);
159 159
160 T::enable(); 160 T::enable_and_reset();
161 <T as crate::rcc::sealed::RccPeripheral>::reset();
162 161
163 #[cfg(stm32f334)] 162 #[cfg(stm32f334)]
164 if unsafe { get_freqs() }.hrtim.is_some() { 163 if unsafe { get_freqs() }.hrtim.is_some() {
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index b35678ed9..dde1a5040 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -7,14 +7,9 @@ use crate::interrupt;
7mod _version; 7mod _version;
8pub use _version::*; 8pub use _version::*;
9 9
10#[cfg(feature = "time")]
11mod timeout;
12#[cfg(feature = "time")]
13pub use timeout::*;
14
15use crate::peripherals; 10use crate::peripherals;
16 11
17#[derive(Debug)] 12#[derive(Debug, PartialEq, Eq)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))] 13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19pub enum Error { 14pub enum Error {
20 Bus, 15 Bus,
diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs
deleted file mode 100644
index 103017cd1..000000000
--- a/embassy-stm32/src/i2c/timeout.rs
+++ /dev/null
@@ -1,209 +0,0 @@
1use embassy_time::{Duration, Instant};
2
3use super::{Error, I2c, Instance};
4
5/// An I2C wrapper, which provides `embassy-time` based timeouts for all `embedded-hal` trait methods.
6///
7/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state.
8/// A regular [I2c] would freeze until condition is removed.
9pub struct TimeoutI2c<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> {
10 i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>,
11 timeout: Duration,
12}
13
14fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
15 let deadline = Instant::now() + timeout;
16 move || {
17 if Instant::now() > deadline {
18 Err(Error::Timeout)
19 } else {
20 Ok(())
21 }
22 }
23}
24
25impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
26 pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
27 Self { i2c, timeout }
28 }
29
30 // =========================
31 // Async public API
32
33 #[cfg(i2c_v2)]
34 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
35 where
36 TXDMA: crate::i2c::TxDma<T>,
37 {
38 self.write_timeout(address, write, self.timeout).await
39 }
40
41 #[cfg(i2c_v2)]
42 pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error>
43 where
44 TXDMA: crate::i2c::TxDma<T>,
45 {
46 self.i2c.write_timeout(address, write, timeout_fn(timeout)).await
47 }
48
49 #[cfg(i2c_v2)]
50 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
51 where
52 TXDMA: crate::i2c::TxDma<T>,
53 {
54 self.write_vectored_timeout(address, write, self.timeout).await
55 }
56
57 #[cfg(i2c_v2)]
58 pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error>
59 where
60 TXDMA: crate::i2c::TxDma<T>,
61 {
62 self.i2c
63 .write_vectored_timeout(address, write, timeout_fn(timeout))
64 .await
65 }
66
67 #[cfg(i2c_v2)]
68 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
69 where
70 RXDMA: crate::i2c::RxDma<T>,
71 {
72 self.read_timeout(address, buffer, self.timeout).await
73 }
74
75 #[cfg(i2c_v2)]
76 pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error>
77 where
78 RXDMA: crate::i2c::RxDma<T>,
79 {
80 self.i2c.read_timeout(address, buffer, timeout_fn(timeout)).await
81 }
82
83 #[cfg(i2c_v2)]
84 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
85 where
86 TXDMA: super::TxDma<T>,
87 RXDMA: super::RxDma<T>,
88 {
89 self.write_read_timeout(address, write, read, self.timeout).await
90 }
91
92 #[cfg(i2c_v2)]
93 pub async fn write_read_timeout(
94 &mut self,
95 address: u8,
96 write: &[u8],
97 read: &mut [u8],
98 timeout: Duration,
99 ) -> Result<(), Error>
100 where
101 TXDMA: super::TxDma<T>,
102 RXDMA: super::RxDma<T>,
103 {
104 self.i2c
105 .write_read_timeout(address, write, read, timeout_fn(timeout))
106 .await
107 }
108
109 // =========================
110 // Blocking public API
111
112 /// Blocking read with a custom timeout
113 pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
114 self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout))
115 }
116
117 /// Blocking read with default timeout, provided in [`TimeoutI2c::new()`]
118 pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> {
119 self.blocking_read_timeout(addr, read, self.timeout)
120 }
121
122 /// Blocking write with a custom timeout
123 pub fn blocking_write_timeout(&mut self, addr: u8, write: &[u8], timeout: Duration) -> Result<(), Error> {
124 self.i2c.blocking_write_timeout(addr, write, timeout_fn(timeout))
125 }
126
127 /// Blocking write with default timeout, provided in [`TimeoutI2c::new()`]
128 pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> {
129 self.blocking_write_timeout(addr, write, self.timeout)
130 }
131
132 /// Blocking write-read with a custom timeout
133 pub fn blocking_write_read_timeout(
134 &mut self,
135 addr: u8,
136 write: &[u8],
137 read: &mut [u8],
138 timeout: Duration,
139 ) -> Result<(), Error> {
140 self.i2c
141 .blocking_write_read_timeout(addr, write, read, timeout_fn(timeout))
142 }
143
144 /// Blocking write-read with default timeout, provided in [`TimeoutI2c::new()`]
145 pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
146 self.blocking_write_read_timeout(addr, write, read, self.timeout)
147 }
148}
149
150impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read
151 for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
152{
153 type Error = Error;
154
155 fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> {
156 self.blocking_read(addr, read)
157 }
158}
159
160impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write
161 for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
162{
163 type Error = Error;
164
165 fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> {
166 self.blocking_write(addr, write)
167 }
168}
169
170impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead
171 for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA>
172{
173 type Error = Error;
174
175 fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
176 self.blocking_write_read(addr, write, read)
177 }
178}
179
180#[cfg(feature = "unstable-traits")]
181mod eh1 {
182 use super::*;
183
184 impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
185 type Error = Error;
186 }
187
188 impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> {
189 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
190 self.blocking_read(address, read)
191 }
192
193 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
194 self.blocking_write(address, write)
195 }
196
197 fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
198 self.blocking_write_read(address, write, read)
199 }
200
201 fn transaction(
202 &mut self,
203 _address: u8,
204 _operations: &mut [embedded_hal_1::i2c::Operation<'_>],
205 ) -> Result<(), Self::Error> {
206 todo!();
207 }
208 }
209}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index f32dd0f0c..ab59f5ab9 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -56,8 +56,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
56 ) -> Self { 56 ) -> Self {
57 into_ref!(scl, sda, tx_dma, rx_dma); 57 into_ref!(scl, sda, tx_dma, rx_dma);
58 58
59 T::enable(); 59 T::enable_and_reset();
60 T::reset();
61 60
62 scl.set_as_af_pull( 61 scl.set_as_af_pull(
63 scl.af_num(), 62 scl.af_num(),
@@ -518,7 +517,8 @@ impl Timings {
518 517
519impl<'d, T: Instance> SetConfig for I2c<'d, T> { 518impl<'d, T: Instance> SetConfig for I2c<'d, T> {
520 type Config = Hertz; 519 type Config = Hertz;
521 fn set_config(&mut self, config: &Self::Config) { 520 type ConfigError = ();
521 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
522 let timings = Timings::new(T::frequency(), *config); 522 let timings = Timings::new(T::frequency(), *config);
523 T::regs().cr2().modify(|reg| { 523 T::regs().cr2().modify(|reg| {
524 reg.set_freq(timings.freq); 524 reg.set_freq(timings.freq);
@@ -531,5 +531,7 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
531 T::regs().trise().modify(|reg| { 531 T::regs().trise().modify(|reg| {
532 reg.set_trise(timings.trise); 532 reg.set_trise(timings.trise);
533 }); 533 });
534
535 Ok(())
534 } 536 }
535} 537}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 36f70e32e..fc6dcd6ed 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -1,14 +1,21 @@
1use core::cmp; 1use core::cmp;
2#[cfg(feature = "time")]
2use core::future::poll_fn; 3use core::future::poll_fn;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
5#[cfg(feature = "time")]
4use core::task::Poll; 6use core::task::Poll;
5 7
6use embassy_embedded_hal::SetConfig; 8use embassy_embedded_hal::SetConfig;
9#[cfg(feature = "time")]
7use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
8use embassy_hal_internal::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(feature = "time")]
14use embassy_time::{Duration, Instant};
10 15
11use crate::dma::{NoDma, Transfer}; 16use crate::dma::NoDma;
17#[cfg(feature = "time")]
18use crate::dma::Transfer;
12use crate::gpio::sealed::AFType; 19use crate::gpio::sealed::AFType;
13use crate::gpio::Pull; 20use crate::gpio::Pull;
14use crate::i2c::{Error, Instance, SclPin, SdaPin}; 21use crate::i2c::{Error, Instance, SclPin, SdaPin};
@@ -43,6 +50,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
43pub struct Config { 50pub struct Config {
44 pub sda_pullup: bool, 51 pub sda_pullup: bool,
45 pub scl_pullup: bool, 52 pub scl_pullup: bool,
53 #[cfg(feature = "time")]
54 pub transaction_timeout: Duration,
46} 55}
47 56
48impl Default for Config { 57impl Default for Config {
@@ -50,6 +59,8 @@ impl Default for Config {
50 Self { 59 Self {
51 sda_pullup: false, 60 sda_pullup: false,
52 scl_pullup: false, 61 scl_pullup: false,
62 #[cfg(feature = "time")]
63 transaction_timeout: Duration::from_millis(100),
53 } 64 }
54 } 65 }
55} 66}
@@ -68,9 +79,12 @@ impl State {
68 79
69pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { 80pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
70 _peri: PeripheralRef<'d, T>, 81 _peri: PeripheralRef<'d, T>,
82 #[allow(dead_code)]
71 tx_dma: PeripheralRef<'d, TXDMA>, 83 tx_dma: PeripheralRef<'d, TXDMA>,
72 #[allow(dead_code)] 84 #[allow(dead_code)]
73 rx_dma: PeripheralRef<'d, RXDMA>, 85 rx_dma: PeripheralRef<'d, RXDMA>,
86 #[cfg(feature = "time")]
87 timeout: Duration,
74} 88}
75 89
76impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { 90impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
@@ -86,8 +100,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
86 ) -> Self { 100 ) -> Self {
87 into_ref!(peri, scl, sda, tx_dma, rx_dma); 101 into_ref!(peri, scl, sda, tx_dma, rx_dma);
88 102
89 T::enable(); 103 T::enable_and_reset();
90 T::reset();
91 104
92 scl.set_as_af_pull( 105 scl.set_as_af_pull(
93 scl.af_num(), 106 scl.af_num(),
@@ -132,6 +145,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
132 _peri: peri, 145 _peri: peri,
133 tx_dma, 146 tx_dma,
134 rx_dma, 147 rx_dma,
148 #[cfg(feature = "time")]
149 timeout: config.transaction_timeout,
135 } 150 }
136 } 151 }
137 152
@@ -422,6 +437,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
422 result 437 result
423 } 438 }
424 439
440 #[cfg(feature = "time")]
425 async fn write_dma_internal( 441 async fn write_dma_internal(
426 &mut self, 442 &mut self,
427 address: u8, 443 address: u8,
@@ -512,6 +528,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
512 Ok(()) 528 Ok(())
513 } 529 }
514 530
531 #[cfg(feature = "time")]
515 async fn read_dma_internal( 532 async fn read_dma_internal(
516 &mut self, 533 &mut self,
517 address: u8, 534 address: u8,
@@ -594,42 +611,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
594 // ========================= 611 // =========================
595 // Async public API 612 // Async public API
596 613
614 #[cfg(feature = "time")]
597 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> 615 pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error>
598 where 616 where
599 TXDMA: crate::i2c::TxDma<T>, 617 TXDMA: crate::i2c::TxDma<T>,
600 { 618 {
601 self.write_timeout(address, write, || Ok(())).await 619 self.write_timeout(address, write, self.timeout).await
602 } 620 }
603 621
604 pub async fn write_timeout( 622 #[cfg(feature = "time")]
605 &mut self, 623 pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error>
606 address: u8,
607 write: &[u8],
608 check_timeout: impl Fn() -> Result<(), Error>,
609 ) -> Result<(), Error>
610 where 624 where
611 TXDMA: crate::i2c::TxDma<T>, 625 TXDMA: crate::i2c::TxDma<T>,
612 { 626 {
613 if write.is_empty() { 627 if write.is_empty() {
614 self.write_internal(address, write, true, check_timeout) 628 self.write_internal(address, write, true, timeout_fn(timeout))
615 } else { 629 } else {
616 self.write_dma_internal(address, write, true, true, check_timeout).await 630 embassy_time::with_timeout(
631 timeout,
632 self.write_dma_internal(address, write, true, true, timeout_fn(timeout)),
633 )
634 .await
635 .unwrap_or(Err(Error::Timeout))
617 } 636 }
618 } 637 }
619 638
639 #[cfg(feature = "time")]
620 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> 640 pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error>
621 where 641 where
622 TXDMA: crate::i2c::TxDma<T>, 642 TXDMA: crate::i2c::TxDma<T>,
623 { 643 {
624 self.write_vectored_timeout(address, write, || Ok(())).await 644 self.write_vectored_timeout(address, write, self.timeout).await
625 } 645 }
626 646
627 pub async fn write_vectored_timeout( 647 #[cfg(feature = "time")]
628 &mut self, 648 pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error>
629 address: u8,
630 write: &[&[u8]],
631 check_timeout: impl Fn() -> Result<(), Error>,
632 ) -> Result<(), Error>
633 where 649 where
634 TXDMA: crate::i2c::TxDma<T>, 650 TXDMA: crate::i2c::TxDma<T>,
635 { 651 {
@@ -644,67 +660,88 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
644 let next = iter.next(); 660 let next = iter.next();
645 let is_last = next.is_none(); 661 let is_last = next.is_none();
646 662
647 self.write_dma_internal(address, c, first, is_last, || check_timeout()) 663 embassy_time::with_timeout(
648 .await?; 664 timeout,
665 self.write_dma_internal(address, c, first, is_last, timeout_fn(timeout)),
666 )
667 .await
668 .unwrap_or(Err(Error::Timeout))?;
649 first = false; 669 first = false;
650 current = next; 670 current = next;
651 } 671 }
652 Ok(()) 672 Ok(())
653 } 673 }
654 674
675 #[cfg(feature = "time")]
655 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> 676 pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error>
656 where 677 where
657 RXDMA: crate::i2c::RxDma<T>, 678 RXDMA: crate::i2c::RxDma<T>,
658 { 679 {
659 self.read_timeout(address, buffer, || Ok(())).await 680 self.read_timeout(address, buffer, self.timeout).await
660 } 681 }
661 682
662 pub async fn read_timeout( 683 #[cfg(feature = "time")]
663 &mut self, 684 pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error>
664 address: u8,
665 buffer: &mut [u8],
666 check_timeout: impl Fn() -> Result<(), Error>,
667 ) -> Result<(), Error>
668 where 685 where
669 RXDMA: crate::i2c::RxDma<T>, 686 RXDMA: crate::i2c::RxDma<T>,
670 { 687 {
671 if buffer.is_empty() { 688 if buffer.is_empty() {
672 self.read_internal(address, buffer, false, check_timeout) 689 self.read_internal(address, buffer, false, timeout_fn(timeout))
673 } else { 690 } else {
674 self.read_dma_internal(address, buffer, false, check_timeout).await 691 embassy_time::with_timeout(
692 timeout,
693 self.read_dma_internal(address, buffer, false, timeout_fn(timeout)),
694 )
695 .await
696 .unwrap_or(Err(Error::Timeout))
675 } 697 }
676 } 698 }
677 699
700 #[cfg(feature = "time")]
678 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> 701 pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error>
679 where 702 where
680 TXDMA: super::TxDma<T>, 703 TXDMA: super::TxDma<T>,
681 RXDMA: super::RxDma<T>, 704 RXDMA: super::RxDma<T>,
682 { 705 {
683 self.write_read_timeout(address, write, read, || Ok(())).await 706 self.write_read_timeout(address, write, read, self.timeout).await
684 } 707 }
685 708
709 #[cfg(feature = "time")]
686 pub async fn write_read_timeout( 710 pub async fn write_read_timeout(
687 &mut self, 711 &mut self,
688 address: u8, 712 address: u8,
689 write: &[u8], 713 write: &[u8],
690 read: &mut [u8], 714 read: &mut [u8],
691 check_timeout: impl Fn() -> Result<(), Error>, 715 timeout: Duration,
692 ) -> Result<(), Error> 716 ) -> Result<(), Error>
693 where 717 where
694 TXDMA: super::TxDma<T>, 718 TXDMA: super::TxDma<T>,
695 RXDMA: super::RxDma<T>, 719 RXDMA: super::RxDma<T>,
696 { 720 {
721 let start_instant = Instant::now();
722 let check_timeout = timeout_fn(timeout);
697 if write.is_empty() { 723 if write.is_empty() {
698 self.write_internal(address, write, false, || check_timeout())?; 724 self.write_internal(address, write, false, &check_timeout)?;
699 } else { 725 } else {
700 self.write_dma_internal(address, write, true, true, || check_timeout()) 726 embassy_time::with_timeout(
701 .await?; 727 timeout,
728 self.write_dma_internal(address, write, true, true, &check_timeout),
729 )
730 .await
731 .unwrap_or(Err(Error::Timeout))?;
702 } 732 }
703 733
734 let time_left_until_timeout = timeout - Instant::now().duration_since(start_instant);
735
704 if read.is_empty() { 736 if read.is_empty() {
705 self.read_internal(address, read, true, check_timeout)?; 737 self.read_internal(address, read, true, &check_timeout)?;
706 } else { 738 } else {
707 self.read_dma_internal(address, read, true, check_timeout).await?; 739 embassy_time::with_timeout(
740 time_left_until_timeout,
741 self.read_dma_internal(address, read, true, &check_timeout),
742 )
743 .await
744 .unwrap_or(Err(Error::Timeout))?;
708 } 745 }
709 746
710 Ok(()) 747 Ok(())
@@ -713,33 +750,73 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
713 // ========================= 750 // =========================
714 // Blocking public API 751 // Blocking public API
715 752
753 #[cfg(feature = "time")]
754 pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> {
755 self.read_internal(address, read, false, timeout_fn(timeout))
756 // Automatic Stop
757 }
758
759 #[cfg(not(feature = "time"))]
716 pub fn blocking_read_timeout( 760 pub fn blocking_read_timeout(
717 &mut self, 761 &mut self,
718 address: u8, 762 address: u8,
719 read: &mut [u8], 763 read: &mut [u8],
720 check_timeout: impl Fn() -> Result<(), Error>, 764 check_timeout: impl Fn() -> Result<(), Error>,
721 ) -> Result<(), Error> { 765 ) -> Result<(), Error> {
722 self.read_internal(address, read, false, &check_timeout) 766 self.read_internal(address, read, false, check_timeout)
723 // Automatic Stop 767 // Automatic Stop
724 } 768 }
725 769
770 #[cfg(feature = "time")]
771 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
772 self.blocking_read_timeout(address, read, self.timeout)
773 }
774
775 #[cfg(not(feature = "time"))]
726 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { 776 pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> {
727 self.blocking_read_timeout(address, read, || Ok(())) 777 self.blocking_read_timeout(address, read, || Ok(()))
728 } 778 }
729 779
780 #[cfg(feature = "time")]
781 pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> {
782 self.write_internal(address, write, true, timeout_fn(timeout))
783 }
784
785 #[cfg(not(feature = "time"))]
730 pub fn blocking_write_timeout( 786 pub fn blocking_write_timeout(
731 &mut self, 787 &mut self,
732 address: u8, 788 address: u8,
733 write: &[u8], 789 write: &[u8],
734 check_timeout: impl Fn() -> Result<(), Error>, 790 check_timeout: impl Fn() -> Result<(), Error>,
735 ) -> Result<(), Error> { 791 ) -> Result<(), Error> {
736 self.write_internal(address, write, true, &check_timeout) 792 self.write_internal(address, write, true, check_timeout)
737 } 793 }
738 794
795 #[cfg(feature = "time")]
796 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
797 self.blocking_write_timeout(address, write, self.timeout)
798 }
799
800 #[cfg(not(feature = "time"))]
739 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { 801 pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> {
740 self.blocking_write_timeout(address, write, || Ok(())) 802 self.blocking_write_timeout(address, write, || Ok(()))
741 } 803 }
742 804
805 #[cfg(feature = "time")]
806 pub fn blocking_write_read_timeout(
807 &mut self,
808 address: u8,
809 write: &[u8],
810 read: &mut [u8],
811 timeout: Duration,
812 ) -> Result<(), Error> {
813 let check_timeout = timeout_fn(timeout);
814 self.write_internal(address, write, false, &check_timeout)?;
815 self.read_internal(address, read, true, &check_timeout)
816 // Automatic Stop
817 }
818
819 #[cfg(not(feature = "time"))]
743 pub fn blocking_write_read_timeout( 820 pub fn blocking_write_read_timeout(
744 &mut self, 821 &mut self,
745 address: u8, 822 address: u8,
@@ -752,11 +829,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
752 // Automatic Stop 829 // Automatic Stop
753 } 830 }
754 831
832 #[cfg(feature = "time")]
833 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
834 self.blocking_write_read_timeout(address, write, read, self.timeout)
835 }
836
837 #[cfg(not(feature = "time"))]
755 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { 838 pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> {
756 self.blocking_write_read_timeout(address, write, read, || Ok(())) 839 self.blocking_write_read_timeout(address, write, read, || Ok(()))
757 } 840 }
758 841
759 pub fn blocking_write_vectored_timeout( 842 fn blocking_write_vectored_with_timeout(
760 &mut self, 843 &mut self,
761 address: u8, 844 address: u8,
762 write: &[&[u8]], 845 write: &[&[u8]],
@@ -765,6 +848,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
765 if write.is_empty() { 848 if write.is_empty() {
766 return Err(Error::ZeroLengthTransfer); 849 return Err(Error::ZeroLengthTransfer);
767 } 850 }
851
768 let first_length = write[0].len(); 852 let first_length = write[0].len();
769 let last_slice_index = write.len() - 1; 853 let last_slice_index = write.len() - 1;
770 854
@@ -833,6 +917,33 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
833 result 917 result
834 } 918 }
835 919
920 #[cfg(feature = "time")]
921 pub fn blocking_write_vectored_timeout(
922 &mut self,
923 address: u8,
924 write: &[&[u8]],
925 timeout: Duration,
926 ) -> Result<(), Error> {
927 let check_timeout = timeout_fn(timeout);
928 self.blocking_write_vectored_with_timeout(address, write, check_timeout)
929 }
930
931 #[cfg(not(feature = "time"))]
932 pub fn blocking_write_vectored_timeout(
933 &mut self,
934 address: u8,
935 write: &[&[u8]],
936 check_timeout: impl Fn() -> Result<(), Error>,
937 ) -> Result<(), Error> {
938 self.blocking_write_vectored_with_timeout(address, write, check_timeout)
939 }
940
941 #[cfg(feature = "time")]
942 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
943 self.blocking_write_vectored_timeout(address, write, self.timeout)
944 }
945
946 #[cfg(not(feature = "time"))]
836 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { 947 pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> {
837 self.blocking_write_vectored_timeout(address, write, || Ok(())) 948 self.blocking_write_vectored_timeout(address, write, || Ok(()))
838 } 949 }
@@ -844,6 +955,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
844 } 955 }
845} 956}
846 957
958#[cfg(feature = "time")]
847mod eh02 { 959mod eh02 {
848 use super::*; 960 use super::*;
849 961
@@ -1043,7 +1155,7 @@ mod eh1 {
1043 } 1155 }
1044} 1156}
1045 1157
1046#[cfg(all(feature = "unstable-traits", feature = "nightly"))] 1158#[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "time"))]
1047mod eha { 1159mod eha {
1048 use super::super::{RxDma, TxDma}; 1160 use super::super::{RxDma, TxDma};
1049 use super::*; 1161 use super::*;
@@ -1075,7 +1187,8 @@ mod eha {
1075 1187
1076impl<'d, T: Instance> SetConfig for I2c<'d, T> { 1188impl<'d, T: Instance> SetConfig for I2c<'d, T> {
1077 type Config = Hertz; 1189 type Config = Hertz;
1078 fn set_config(&mut self, config: &Self::Config) { 1190 type ConfigError = ();
1191 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
1079 let timings = Timings::new(T::frequency(), *config); 1192 let timings = Timings::new(T::frequency(), *config);
1080 T::regs().timingr().write(|reg| { 1193 T::regs().timingr().write(|reg| {
1081 reg.set_presc(timings.prescale); 1194 reg.set_presc(timings.prescale);
@@ -1084,5 +1197,19 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> {
1084 reg.set_sdadel(timings.sdadel); 1197 reg.set_sdadel(timings.sdadel);
1085 reg.set_scldel(timings.scldel); 1198 reg.set_scldel(timings.scldel);
1086 }); 1199 });
1200
1201 Ok(())
1202 }
1203}
1204
1205#[cfg(feature = "time")]
1206fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
1207 let deadline = Instant::now() + timeout;
1208 move || {
1209 if Instant::now() > deadline {
1210 Err(Error::Timeout)
1211 } else {
1212 Ok(())
1213 }
1087 } 1214 }
1088} 1215}
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 8fd3a8c6a..67d40c479 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -170,7 +170,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
170 let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg); 170 let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg);
171 171
172 #[cfg(all(rcc_f4, not(stm32f410)))] 172 #[cfg(all(rcc_f4, not(stm32f410)))]
173 let pclk = unsafe { get_freqs() }.plli2s.unwrap(); 173 let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap();
174 174
175 #[cfg(stm32f410)] 175 #[cfg(stm32f410)]
176 let pclk = T::frequency(); 176 let pclk = T::frequency();
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index e100ca5cc..1b1e182f0 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -93,8 +93,7 @@ pub struct Ipcc;
93 93
94impl Ipcc { 94impl Ipcc {
95 pub fn enable(_config: Config) { 95 pub fn enable(_config: Config) {
96 IPCC::enable(); 96 IPCC::enable_and_reset();
97 IPCC::reset();
98 IPCC::set_cpu2(true); 97 IPCC::set_cpu2(true);
99 98
100 _configure_pwr(); 99 _configure_pwr();
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 9dd2f6163..372246f87 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -1,5 +1,5 @@
1#![cfg_attr(not(test), no_std)] 1#![cfg_attr(not(test), no_std)]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
3 3
4//! ## Feature flags 4//! ## Feature flags
5#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] 5#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
@@ -49,6 +49,8 @@ pub mod i2s;
49pub mod ipcc; 49pub mod ipcc;
50#[cfg(feature = "low-power")] 50#[cfg(feature = "low-power")]
51pub mod low_power; 51pub mod low_power;
52#[cfg(opamp)]
53pub mod opamp;
52#[cfg(quadspi)] 54#[cfg(quadspi)]
53pub mod qspi; 55pub mod qspi;
54#[cfg(rng)] 56#[cfg(rng)]
@@ -153,79 +155,82 @@ impl Default for Config {
153 155
154/// Initialize embassy. 156/// Initialize embassy.
155pub fn init(config: Config) -> Peripherals { 157pub fn init(config: Config) -> Peripherals {
156 let p = Peripherals::take(); 158 critical_section::with(|cs| {
159 let p = Peripherals::take_with_cs(cs);
160
161 #[cfg(dbgmcu)]
162 if config.enable_debug_during_sleep {
163 crate::pac::DBGMCU.cr().modify(|cr| {
164 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))]
165 {
166 cr.set_dbg_stop(true);
167 cr.set_dbg_standby(true);
168 }
169 #[cfg(any(
170 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1,
171 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl
172 ))]
173 {
174 cr.set_dbg_sleep(true);
175 cr.set_dbg_stop(true);
176 cr.set_dbg_standby(true);
177 }
178 #[cfg(dbgmcu_h7)]
179 {
180 cr.set_d1dbgcken(true);
181 cr.set_d3dbgcken(true);
182 cr.set_dbgsleep_d1(true);
183 cr.set_dbgstby_d1(true);
184 cr.set_dbgstop_d1(true);
185 }
186 });
187 }
157 188
158 #[cfg(dbgmcu)] 189 #[cfg(not(any(stm32f1, stm32wb, stm32wl)))]
159 if config.enable_debug_during_sleep { 190 peripherals::SYSCFG::enable_and_reset_with_cs(cs);
160 crate::pac::DBGMCU.cr().modify(|cr| { 191 #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))]
161 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] 192 peripherals::PWR::enable_and_reset_with_cs(cs);
162 { 193 #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))]
163 cr.set_dbg_stop(true); 194 peripherals::FLASH::enable_and_reset_with_cs(cs);
164 cr.set_dbg_standby(true); 195
165 } 196 unsafe {
166 #[cfg(any( 197 #[cfg(feature = "_split-pins-enabled")]
167 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, 198 crate::pac::SYSCFG.pmcr().modify(|pmcr| {
168 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl 199 #[cfg(feature = "split-pa0")]
169 ))] 200 pmcr.set_pa0so(true);
170 { 201 #[cfg(feature = "split-pa1")]
171 cr.set_dbg_sleep(true); 202 pmcr.set_pa1so(true);
172 cr.set_dbg_stop(true); 203 #[cfg(feature = "split-pc2")]
173 cr.set_dbg_standby(true); 204 pmcr.set_pc2so(true);
174 } 205 #[cfg(feature = "split-pc3")]
175 #[cfg(dbgmcu_h7)] 206 pmcr.set_pc3so(true);
176 { 207 });
177 cr.set_d1dbgcken(true); 208
178 cr.set_d3dbgcken(true); 209 gpio::init(cs);
179 cr.set_dbgsleep_d1(true); 210 dma::init(
180 cr.set_dbgstby_d1(true); 211 cs,
181 cr.set_dbgstop_d1(true); 212 #[cfg(bdma)]
213 config.bdma_interrupt_priority,
214 #[cfg(dma)]
215 config.dma_interrupt_priority,
216 #[cfg(gpdma)]
217 config.gpdma_interrupt_priority,
218 );
219 #[cfg(feature = "exti")]
220 exti::init(cs);
221
222 rcc::init(config.rcc);
223
224 // must be after rcc init
225 #[cfg(feature = "_time-driver")]
226 time_driver::init(cs);
227
228 #[cfg(feature = "low-power")]
229 while !crate::rcc::low_power_ready() {
230 crate::rcc::clock_refcount_sub(cs);
182 } 231 }
183 });
184 }
185
186 #[cfg(not(any(stm32f1, stm32wb, stm32wl)))]
187 peripherals::SYSCFG::enable();
188 #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))]
189 peripherals::PWR::enable();
190 #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))]
191 peripherals::FLASH::enable();
192
193 unsafe {
194 #[cfg(feature = "_split-pins-enabled")]
195 crate::pac::SYSCFG.pmcr().modify(|pmcr| {
196 #[cfg(feature = "split-pa0")]
197 pmcr.set_pa0so(true);
198 #[cfg(feature = "split-pa1")]
199 pmcr.set_pa1so(true);
200 #[cfg(feature = "split-pc2")]
201 pmcr.set_pc2so(true);
202 #[cfg(feature = "split-pc3")]
203 pmcr.set_pc3so(true);
204 });
205
206 gpio::init();
207 dma::init(
208 #[cfg(bdma)]
209 config.bdma_interrupt_priority,
210 #[cfg(dma)]
211 config.dma_interrupt_priority,
212 #[cfg(gpdma)]
213 config.gpdma_interrupt_priority,
214 );
215 #[cfg(feature = "exti")]
216 exti::init();
217
218 rcc::init(config.rcc);
219
220 // must be after rcc init
221 #[cfg(feature = "_time-driver")]
222 time_driver::init();
223
224 #[cfg(feature = "low-power")]
225 while !crate::rcc::low_power_ready() {
226 crate::rcc::clock_refcount_sub();
227 } 232 }
228 }
229 233
230 p 234 p
235 })
231} 236}
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index ce8afb578..861a59d7b 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -1,5 +1,6 @@
1use core::arch::asm; 1use core::arch::asm;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering};
3 4
4use cortex_m::peripheral::SCB; 5use cortex_m::peripheral::SCB;
5use embassy_executor::*; 6use embassy_executor::*;
@@ -67,10 +68,8 @@ impl Executor {
67 } 68 }
68 69
69 unsafe fn on_wakeup_irq(&mut self) { 70 unsafe fn on_wakeup_irq(&mut self) {
70 trace!("low power: on wakeup irq");
71
72 self.time_driver.resume_time(); 71 self.time_driver.resume_time();
73 trace!("low power: resume time"); 72 trace!("low power: resume");
74 } 73 }
75 74
76 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) { 75 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) {
@@ -82,21 +81,18 @@ impl Executor {
82 } 81 }
83 82
84 fn configure_pwr(&mut self) { 83 fn configure_pwr(&mut self) {
85 trace!("low power: configure_pwr");
86
87 self.scb.clear_sleepdeep(); 84 self.scb.clear_sleepdeep();
88 if !low_power_ready() {
89 trace!("low power: configure_pwr: low power not ready");
90 return;
91 }
92 85
93 if self.time_driver.pause_time().is_err() { 86 compiler_fence(Ordering::SeqCst);
94 trace!("low power: configure_pwr: time driver failed to pause");
95 return;
96 }
97 87
98 trace!("low power: enter stop..."); 88 if !low_power_ready() {
99 self.scb.set_sleepdeep(); 89 trace!("low power: not ready to stop");
90 } else if self.time_driver.pause_time().is_err() {
91 trace!("low power: failed to pause time");
92 } else {
93 trace!("low power: stop");
94 self.scb.set_sleepdeep();
95 }
100 } 96 }
101 97
102 /// Run the executor. 98 /// Run the executor.
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
new file mode 100644
index 000000000..e0fad26eb
--- /dev/null
+++ b/embassy-stm32/src/opamp.rs
@@ -0,0 +1,159 @@
1#![macro_use]
2
3use embassy_hal_internal::{into_ref, PeripheralRef};
4
5use crate::Peripheral;
6
7#[derive(Clone, Copy)]
8pub enum OpAmpGain {
9 Mul1,
10 Mul2,
11 Mul4,
12 Mul8,
13 Mul16,
14}
15
16pub struct OpAmpOutput<'d, 'p, T: Instance, P: NonInvertingPin<T>> {
17 _inner: &'d OpAmp<'d, T>,
18 _input: &'p mut P,
19}
20
21pub struct OpAmp<'d, T: Instance> {
22 _inner: PeripheralRef<'d, T>,
23}
24
25impl<'d, T: Instance> OpAmp<'d, T> {
26 pub fn new(opamp: impl Peripheral<P = T> + 'd) -> Self {
27 Self::new_inner(opamp)
28 }
29
30 fn new_inner(opamp: impl Peripheral<P = T> + 'd) -> Self {
31 into_ref!(opamp);
32
33 #[cfg(opamp_f3)]
34 T::regs().opampcsr().modify(|w| {
35 w.set_opampen(true);
36 });
37
38 #[cfg(opamp_g4)]
39 T::regs().opamp_csr().modify(|w| {
40 w.set_opaen(true);
41 });
42
43 Self { _inner: opamp }
44 }
45
46 pub fn buffer_for<'a, 'b, P>(&'a mut self, pin: &'b mut P, gain: OpAmpGain) -> OpAmpOutput<'a, 'b, T, P>
47 where
48 P: NonInvertingPin<T>,
49 {
50 let (vm_sel, pga_gain) = match gain {
51 OpAmpGain::Mul1 => (0b11, 0b00),
52 OpAmpGain::Mul2 => (0b10, 0b00),
53 OpAmpGain::Mul4 => (0b10, 0b01),
54 OpAmpGain::Mul8 => (0b10, 0b10),
55 OpAmpGain::Mul16 => (0b10, 0b11),
56 };
57
58 #[cfg(opamp_f3)]
59 T::regs().opampcsr().modify(|w| {
60 w.set_vp_sel(pin.channel());
61 w.set_vm_sel(vm_sel);
62 w.set_pga_gain(pga_gain);
63 });
64
65 #[cfg(opamp_g4)]
66 T::regs().opamp_csr().modify(|w| {
67 use crate::pac::opamp::vals::*;
68
69 w.set_vp_sel(OpampCsrVpSel::from_bits(pin.channel()));
70 w.set_vm_sel(OpampCsrVmSel::from_bits(vm_sel));
71 w.set_pga_gain(OpampCsrPgaGain::from_bits(pga_gain));
72 });
73
74 OpAmpOutput {
75 _inner: self,
76 _input: pin,
77 }
78 }
79}
80
81pub trait Instance: sealed::Instance + 'static {}
82
83pub(crate) mod sealed {
84 pub trait Instance {
85 fn regs() -> crate::pac::opamp::Opamp;
86 }
87
88 pub trait NonInvertingPin<T: Instance> {
89 fn channel(&self) -> u8;
90 }
91
92 pub trait InvertingPin<T: Instance> {
93 fn channel(&self) -> u8;
94 }
95}
96
97pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
98
99pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
100
101#[cfg(opamp_f3)]
102macro_rules! impl_opamp_output {
103 ($inst:ident, $adc:ident, $ch:expr) => {
104 impl<'d, 'p, P: NonInvertingPin<crate::peripherals::$inst>> crate::adc::sealed::AdcPin<crate::peripherals::$adc>
105 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P>
106 {
107 fn channel(&self) -> u8 {
108 $ch
109 }
110 }
111
112 impl<'d, 'p, P: NonInvertingPin<crate::peripherals::$inst>> crate::adc::AdcPin<crate::peripherals::$adc>
113 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P>
114 {
115 }
116 };
117}
118
119#[cfg(opamp_f3)]
120foreach_peripheral!(
121 (opamp, OPAMP1) => {
122 impl_opamp_output!(OPAMP1, ADC1, 3);
123 };
124 (opamp, OPAMP2) => {
125 impl_opamp_output!(OPAMP2, ADC2, 3);
126 };
127 (opamp, OPAMP3) => {
128 impl_opamp_output!(OPAMP3, ADC3, 1);
129 };
130 (opamp, OPAMP4) => {
131 impl_opamp_output!(OPAMP4, ADC4, 3);
132 };
133);
134
135foreach_peripheral! {
136 (opamp, $inst:ident) => {
137 impl sealed::Instance for crate::peripherals::$inst {
138 fn regs() -> crate::pac::opamp::Opamp {
139 crate::pac::$inst
140 }
141 }
142
143 impl Instance for crate::peripherals::$inst {
144
145 }
146 };
147}
148
149#[allow(unused_macros)]
150macro_rules! impl_opamp_pin {
151 ($inst:ident, $pin:ident, $ch:expr) => {
152 impl crate::opamp::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {}
153 impl crate::opamp::sealed::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {
154 fn channel(&self) -> u8 {
155 $ch
156 }
157 }
158 };
159}
diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs
index 2dbe2b061..0412d991a 100644
--- a/embassy-stm32/src/qspi/enums.rs
+++ b/embassy-stm32/src/qspi/enums.rs
@@ -38,6 +38,22 @@ impl Into<u8> for QspiWidth {
38 } 38 }
39} 39}
40 40
41#[allow(dead_code)]
42#[derive(Copy, Clone)]
43pub enum FlashSelection {
44 Flash1,
45 Flash2,
46}
47
48impl Into<bool> for FlashSelection {
49 fn into(self) -> bool {
50 match self {
51 FlashSelection::Flash1 => false,
52 FlashSelection::Flash2 => true,
53 }
54 }
55}
56
41#[derive(Copy, Clone)] 57#[derive(Copy, Clone)]
42pub enum MemorySize { 58pub enum MemorySize {
43 _1KiB, 59 _1KiB,
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 32382fb28..4b0e8ecef 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -7,7 +7,7 @@ use enums::*;
7 7
8use crate::dma::Transfer; 8use crate::dma::Transfer;
9use crate::gpio::sealed::AFType; 9use crate::gpio::sealed::AFType;
10use crate::gpio::AnyPin; 10use crate::gpio::{AnyPin, Pull};
11use crate::pac::quadspi::Quadspi as Regs; 11use crate::pac::quadspi::Quadspi as Regs;
12use crate::rcc::RccPeripheral; 12use crate::rcc::RccPeripheral;
13use crate::{peripherals, Peripheral}; 13use crate::{peripherals, Peripheral};
@@ -83,30 +83,30 @@ pub struct Qspi<'d, T: Instance, Dma> {
83} 83}
84 84
85impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { 85impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
86 pub fn new( 86 pub fn new_bk1(
87 peri: impl Peripheral<P = T> + 'd, 87 peri: impl Peripheral<P = T> + 'd,
88 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 88 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
89 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 89 d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
90 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 90 d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
91 d3: impl Peripheral<P = impl D3Pin<T>> + 'd, 91 d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
92 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 92 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
93 nss: impl Peripheral<P = impl NSSPin<T>> + 'd, 93 nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
94 dma: impl Peripheral<P = Dma> + 'd, 94 dma: impl Peripheral<P = Dma> + 'd,
95 config: Config, 95 config: Config,
96 ) -> Self { 96 ) -> Self {
97 into_ref!(peri, d0, d1, d2, d3, sck, nss); 97 into_ref!(peri, d0, d1, d2, d3, sck, nss);
98 98
99 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 99 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
100 sck.set_speed(crate::gpio::Speed::VeryHigh); 100 sck.set_speed(crate::gpio::Speed::VeryHigh);
101 nss.set_as_af(nss.af_num(), AFType::OutputPushPull); 101 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
102 nss.set_speed(crate::gpio::Speed::VeryHigh); 102 nss.set_speed(crate::gpio::Speed::VeryHigh);
103 d0.set_as_af(d0.af_num(), AFType::OutputPushPull); 103 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
104 d0.set_speed(crate::gpio::Speed::VeryHigh); 104 d0.set_speed(crate::gpio::Speed::VeryHigh);
105 d1.set_as_af(d1.af_num(), AFType::OutputPushPull); 105 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
106 d1.set_speed(crate::gpio::Speed::VeryHigh); 106 d1.set_speed(crate::gpio::Speed::VeryHigh);
107 d2.set_as_af(d2.af_num(), AFType::OutputPushPull); 107 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
108 d2.set_speed(crate::gpio::Speed::VeryHigh); 108 d2.set_speed(crate::gpio::Speed::VeryHigh);
109 d3.set_as_af(d3.af_num(), AFType::OutputPushPull); 109 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
110 d3.set_speed(crate::gpio::Speed::VeryHigh); 110 d3.set_speed(crate::gpio::Speed::VeryHigh);
111 111
112 Self::new_inner( 112 Self::new_inner(
@@ -119,6 +119,47 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
119 Some(nss.map_into()), 119 Some(nss.map_into()),
120 dma, 120 dma,
121 config, 121 config,
122 FlashSelection::Flash2,
123 )
124 }
125
126 pub fn new_bk2(
127 peri: impl Peripheral<P = T> + 'd,
128 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
129 d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
130 d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
131 d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
132 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
133 nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
134 dma: impl Peripheral<P = Dma> + 'd,
135 config: Config,
136 ) -> Self {
137 into_ref!(peri, d0, d1, d2, d3, sck, nss);
138
139 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
140 sck.set_speed(crate::gpio::Speed::VeryHigh);
141 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
142 nss.set_speed(crate::gpio::Speed::VeryHigh);
143 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
144 d0.set_speed(crate::gpio::Speed::VeryHigh);
145 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
146 d1.set_speed(crate::gpio::Speed::VeryHigh);
147 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
148 d2.set_speed(crate::gpio::Speed::VeryHigh);
149 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
150 d3.set_speed(crate::gpio::Speed::VeryHigh);
151
152 Self::new_inner(
153 peri,
154 Some(d0.map_into()),
155 Some(d1.map_into()),
156 Some(d2.map_into()),
157 Some(d3.map_into()),
158 Some(sck.map_into()),
159 Some(nss.map_into()),
160 dma,
161 config,
162 FlashSelection::Flash2,
122 ) 163 )
123 } 164 }
124 165
@@ -132,22 +173,39 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
132 nss: Option<PeripheralRef<'d, AnyPin>>, 173 nss: Option<PeripheralRef<'d, AnyPin>>,
133 dma: impl Peripheral<P = Dma> + 'd, 174 dma: impl Peripheral<P = Dma> + 'd,
134 config: Config, 175 config: Config,
176 fsel: FlashSelection,
135 ) -> Self { 177 ) -> Self {
136 into_ref!(peri, dma); 178 into_ref!(peri, dma);
137 179
138 T::enable(); 180 T::enable_and_reset();
139 T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
140 181
141 while T::REGS.sr().read().busy() {} 182 while T::REGS.sr().read().busy() {}
142 183
143 T::REGS.cr().write(|w| { 184 #[cfg(stm32h7)]
144 w.set_prescaler(config.prescaler); 185 {
186 use stm32_metapac::quadspi::regs::Cr;
187 // Apply precautionary steps according to the errata...
188 T::REGS.cr().write_value(Cr(0));
189 while T::REGS.sr().read().busy() {}
190 T::REGS.cr().write_value(Cr(0xFF000001));
191 T::REGS.ccr().write(|w| w.set_frcm(true));
192 T::REGS.ccr().write(|w| w.set_frcm(true));
193 T::REGS.cr().write_value(Cr(0));
194 while T::REGS.sr().read().busy() {}
195 }
196
197 T::REGS.cr().modify(|w| {
145 w.set_en(true); 198 w.set_en(true);
199 //w.set_tcen(false);
200 w.set_sshift(false);
201 w.set_fthres(config.fifo_threshold.into());
202 w.set_prescaler(config.prescaler);
203 w.set_fsel(fsel.into());
146 }); 204 });
147 T::REGS.dcr().write(|w| { 205 T::REGS.dcr().modify(|w| {
148 w.set_fsize(config.memory_size.into()); 206 w.set_fsize(config.memory_size.into());
149 w.set_csht(config.cs_high_time.into()); 207 w.set_csht(config.cs_high_time.into());
150 w.set_ckmode(false); 208 w.set_ckmode(true);
151 }); 209 });
152 210
153 Self { 211 Self {
@@ -164,6 +222,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
164 } 222 }
165 223
166 pub fn command(&mut self, transaction: TransferConfig) { 224 pub fn command(&mut self, transaction: TransferConfig) {
225 #[cfg(not(stm32h7))]
167 T::REGS.cr().modify(|v| v.set_dmaen(false)); 226 T::REGS.cr().modify(|v| v.set_dmaen(false));
168 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 227 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
169 228
@@ -172,6 +231,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
172 } 231 }
173 232
174 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { 233 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
234 #[cfg(not(stm32h7))]
175 T::REGS.cr().modify(|v| v.set_dmaen(false)); 235 T::REGS.cr().modify(|v| v.set_dmaen(false));
176 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 236 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
177 237
@@ -195,7 +255,10 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
195 } 255 }
196 256
197 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { 257 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
258 // STM32H7 does not have dmaen
259 #[cfg(not(stm32h7))]
198 T::REGS.cr().modify(|v| v.set_dmaen(false)); 260 T::REGS.cr().modify(|v| v.set_dmaen(false));
261
199 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 262 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
200 263
201 if let Some(len) = transaction.data_len { 264 if let Some(len) = transaction.data_len {
@@ -238,6 +301,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
238 ) 301 )
239 }; 302 };
240 303
304 // STM32H7 does not have dmaen
305 #[cfg(not(stm32h7))]
241 T::REGS.cr().modify(|v| v.set_dmaen(true)); 306 T::REGS.cr().modify(|v| v.set_dmaen(true));
242 307
243 transfer.blocking_wait(); 308 transfer.blocking_wait();
@@ -264,6 +329,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
264 ) 329 )
265 }; 330 };
266 331
332 // STM32H7 does not have dmaen
333 #[cfg(not(stm32h7))]
267 T::REGS.cr().modify(|v| v.set_dmaen(true)); 334 T::REGS.cr().modify(|v| v.set_dmaen(true));
268 335
269 transfer.blocking_wait(); 336 transfer.blocking_wait();
@@ -313,11 +380,17 @@ pub(crate) mod sealed {
313pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 380pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
314 381
315pin_trait!(SckPin, Instance); 382pin_trait!(SckPin, Instance);
316pin_trait!(D0Pin, Instance); 383pin_trait!(BK1D0Pin, Instance);
317pin_trait!(D1Pin, Instance); 384pin_trait!(BK1D1Pin, Instance);
318pin_trait!(D2Pin, Instance); 385pin_trait!(BK1D2Pin, Instance);
319pin_trait!(D3Pin, Instance); 386pin_trait!(BK1D3Pin, Instance);
320pin_trait!(NSSPin, Instance); 387pin_trait!(BK1NSSPin, Instance);
388
389pin_trait!(BK2D0Pin, Instance);
390pin_trait!(BK2D1Pin, Instance);
391pin_trait!(BK2D2Pin, Instance);
392pin_trait!(BK2D3Pin, Instance);
393pin_trait!(BK2NSSPin, Instance);
321 394
322dma_trait!(QuadDma, Instance); 395dma_trait!(QuadDma, Instance);
323 396
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
index de27130f2..d20f58185 100644
--- a/embassy-stm32/src/rcc/bd.rs
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -1,102 +1,161 @@
1use core::sync::atomic::{compiler_fence, Ordering};
2
3use crate::pac::common::{Reg, RW};
4pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
5use crate::time::Hertz;
6
7#[cfg(any(stm32f0, stm32f1, stm32f3))]
8pub const LSI_FREQ: Hertz = Hertz(40_000);
9#[cfg(not(any(stm32f0, stm32f1, stm32f3)))]
10pub const LSI_FREQ: Hertz = Hertz(32_000);
11
12#[allow(dead_code)]
13#[derive(Clone, Copy)]
14pub enum LseMode {
15 Oscillator(LseDrive),
16 Bypass,
17}
18
19pub struct LseConfig {
20 pub frequency: Hertz,
21 pub mode: LseMode,
22}
23
1#[allow(dead_code)] 24#[allow(dead_code)]
2#[derive(Default, Clone, Copy)] 25#[derive(Default, Clone, Copy)]
3pub enum LseDrive { 26pub enum LseDrive {
4 #[cfg(any(rtc_v2f7, rtc_v2l4))]
5 Low = 0, 27 Low = 0,
6 MediumLow = 0x01, 28 MediumLow = 0x01,
7 #[default] 29 #[default]
8 MediumHigh = 0x02, 30 MediumHigh = 0x02,
9 #[cfg(any(rtc_v2f7, rtc_v2l4))]
10 High = 0x03, 31 High = 0x03,
11} 32}
12 33
13#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] 34// All families but these have the LSEDRV register
35#[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
14impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv { 36impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
15 fn from(value: LseDrive) -> Self { 37 fn from(value: LseDrive) -> Self {
16 use crate::pac::rcc::vals::Lsedrv; 38 use crate::pac::rcc::vals::Lsedrv;
17 39
18 match value { 40 match value {
19 #[cfg(any(rtc_v2f7, rtc_v2l4))]
20 LseDrive::Low => Lsedrv::LOW, 41 LseDrive::Low => Lsedrv::LOW,
21 LseDrive::MediumLow => Lsedrv::MEDIUMLOW, 42 LseDrive::MediumLow => Lsedrv::MEDIUMLOW,
22 LseDrive::MediumHigh => Lsedrv::MEDIUMHIGH, 43 LseDrive::MediumHigh => Lsedrv::MEDIUMHIGH,
23 #[cfg(any(rtc_v2f7, rtc_v2l4))]
24 LseDrive::High => Lsedrv::HIGH, 44 LseDrive::High => Lsedrv::HIGH,
25 } 45 }
26 } 46 }
27} 47}
28 48
29pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
30
31#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] 49#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))]
32#[allow(dead_code)]
33type Bdcr = crate::pac::rcc::regs::Bdcr; 50type Bdcr = crate::pac::rcc::regs::Bdcr;
34
35#[cfg(any(rtc_v2l0, rtc_v2l1))] 51#[cfg(any(rtc_v2l0, rtc_v2l1))]
36#[allow(dead_code)]
37type Bdcr = crate::pac::rcc::regs::Csr; 52type Bdcr = crate::pac::rcc::regs::Csr;
53#[cfg(any(stm32c0))]
54type Bdcr = crate::pac::rcc::regs::Csr1;
55
56#[cfg(any(stm32c0))]
57fn unlock() {}
58
59#[cfg(not(any(stm32c0)))]
60fn unlock() {
61 #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))]
62 let cr = crate::pac::PWR.cr();
63 #[cfg(not(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba)))]
64 let cr = crate::pac::PWR.cr1();
65 #[cfg(any(stm32u5, stm32h5, stm32wba))]
66 let cr = crate::pac::PWR.dbpcr();
67
68 cr.modify(|w| w.set_dbp(true));
69 while !cr.read().dbp() {}
70}
38 71
39#[allow(dead_code)] 72fn bdcr() -> Reg<Bdcr, RW> {
40pub struct BackupDomain {} 73 #[cfg(any(rtc_v2l0, rtc_v2l1))]
41 74 return crate::pac::RCC.csr();
42impl BackupDomain { 75 #[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))]
43 #[cfg(any( 76 return crate::pac::RCC.bdcr();
44 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, 77 #[cfg(any(stm32c0))]
45 rtc_v3u5 78 return crate::pac::RCC.csr1();
46 ))] 79}
47 #[allow(dead_code, unused_variables)]
48 fn modify<R>(f: impl FnOnce(&mut Bdcr) -> R) -> R {
49 #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1, rtc_v2l0))]
50 let cr = crate::pac::PWR.cr();
51 #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
52 let cr = crate::pac::PWR.cr1();
53
54 // TODO: Missing from PAC for l0 and f0?
55 #[cfg(not(any(rtc_v2f0, rtc_v3u5)))]
56 {
57 cr.modify(|w| w.set_dbp(true));
58 while !cr.read().dbp() {}
59 }
60 80
61 #[cfg(any(rtc_v2l0, rtc_v2l1))] 81pub struct LsConfig {
62 let cr = crate::pac::RCC.csr(); 82 pub rtc: RtcClockSource,
83 pub lsi: bool,
84 pub lse: Option<LseConfig>,
85}
63 86
64 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 87impl LsConfig {
65 let cr = crate::pac::RCC.bdcr(); 88 pub const fn default_lse() -> Self {
89 Self {
90 rtc: RtcClockSource::LSE,
91 lse: Some(LseConfig {
92 frequency: Hertz(32_768),
93 mode: LseMode::Oscillator(LseDrive::MediumHigh),
94 }),
95 lsi: false,
96 }
97 }
66 98
67 cr.modify(|w| f(w)) 99 pub const fn default_lsi() -> Self {
100 Self {
101 rtc: RtcClockSource::LSI,
102 lsi: true,
103 lse: None,
104 }
68 } 105 }
69 106
70 #[cfg(any( 107 pub const fn off() -> Self {
71 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, 108 Self {
72 rtc_v3u5 109 rtc: RtcClockSource::DISABLE,
73 ))] 110 lsi: false,
74 #[allow(dead_code)] 111 lse: None,
75 fn read() -> Bdcr { 112 }
76 #[cfg(any(rtc_v2l0, rtc_v2l1))] 113 }
77 let r = crate::pac::RCC.csr().read(); 114}
78 115
79 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 116impl Default for LsConfig {
80 let r = crate::pac::RCC.bdcr().read(); 117 fn default() -> Self {
118 // on L5, just the fact that LSI is enabled makes things crash.
119 // TODO: investigate.
81 120
82 r 121 #[cfg(not(stm32l5))]
122 return Self::default_lsi();
123 #[cfg(stm32l5)]
124 return Self::off();
83 } 125 }
126}
84 127
85 #[cfg(any( 128impl LsConfig {
86 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, 129 pub(crate) fn init(&self) -> Option<Hertz> {
87 rtc_v3u5 130 let rtc_clk = match self.rtc {
88 ))] 131 RtcClockSource::LSI => {
89 #[allow(dead_code, unused_variables)] 132 assert!(self.lsi);
90 pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseDrive>) { 133 Some(LSI_FREQ)
91 if lsi { 134 }
92 #[cfg(rtc_v3u5)] 135 RtcClockSource::LSE => Some(self.lse.as_ref().unwrap().frequency),
93 let csr = crate::pac::RCC.bdcr(); 136 RtcClockSource::DISABLE => None,
137 _ => todo!(),
138 };
94 139
95 #[cfg(not(rtc_v3u5))] 140 let (lse_en, lse_byp, lse_drv) = match &self.lse {
96 let csr = crate::pac::RCC.csr(); 141 Some(c) => match c.mode {
142 LseMode::Oscillator(lse_drv) => (true, false, Some(lse_drv)),
143 LseMode::Bypass => (true, true, None),
144 },
145 None => (false, false, None),
146 };
147 _ = lse_drv; // not all chips have it.
148
149 // Disable backup domain write protection
150 unlock();
97 151
98 // Disable backup domain write protection 152 if self.lsi {
99 Self::modify(|_| {}); 153 #[cfg(any(stm32u5, stm32h5, stm32wba))]
154 let csr = crate::pac::RCC.bdcr();
155 #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0)))]
156 let csr = crate::pac::RCC.csr();
157 #[cfg(any(stm32c0))]
158 let csr = crate::pac::RCC.csr2();
100 159
101 #[cfg(not(any(rcc_wb, rcc_wba)))] 160 #[cfg(not(any(rcc_wb, rcc_wba)))]
102 csr.modify(|w| w.set_lsion(true)); 161 csr.modify(|w| w.set_lsion(true));
@@ -111,66 +170,76 @@ impl BackupDomain {
111 while !csr.read().lsi1rdy() {} 170 while !csr.read().lsi1rdy() {}
112 } 171 }
113 172
114 if let Some(lse_drive) = lse { 173 // backup domain configuration (LSEON, RTCEN, RTCSEL) is kept across resets.
115 Self::modify(|w| { 174 // once set, changing it requires a backup domain reset.
116 #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] 175 // first check if the configuration matches what we want.
117 w.set_lsedrv(lse_drive.into());
118 w.set_lseon(true);
119 });
120 176
121 while !Self::read().lserdy() {} 177 // check if it's already enabled and in the source we want.
178 let reg = bdcr().read();
179 let mut ok = true;
180 ok &= reg.rtcsel() == self.rtc;
181 #[cfg(not(rcc_wba))]
182 {
183 ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE);
184 }
185 ok &= reg.lseon() == lse_en;
186 ok &= reg.lsebyp() == lse_byp;
187 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
188 if let Some(lse_drv) = lse_drv {
189 ok &= reg.lsedrv() == lse_drv.into();
122 } 190 }
123 191
124 match clock_source { 192 // if configuration is OK, we're done.
125 RtcClockSource::LSI => assert!(lsi), 193 if ok {
126 RtcClockSource::LSE => assert!(&lse.is_some()), 194 trace!("BDCR ok: {:08x}", bdcr().read().0);
127 _ => {} 195 return rtc_clk;
128 }; 196 }
129 197
130 if clock_source == RtcClockSource::NOCLOCK { 198 // If not OK, reset backup domain and configure it.
131 // disable it 199 #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32c0)))]
132 Self::modify(|w| { 200 {
133 #[cfg(not(rcc_wba))] 201 bdcr().modify(|w| w.set_bdrst(true));
134 w.set_rtcen(false); 202 bdcr().modify(|w| w.set_bdrst(false));
135 w.set_rtcsel(clock_source); 203 }
204 #[cfg(any(stm32h5))]
205 {
206 bdcr().modify(|w| w.set_vswrst(true));
207 bdcr().modify(|w| w.set_vswrst(false));
208 }
209 #[cfg(any(stm32c0))]
210 {
211 bdcr().modify(|w| w.set_rtcrst(true));
212 bdcr().modify(|w| w.set_rtcrst(false));
213 }
214
215 if lse_en {
216 bdcr().modify(|w| {
217 #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
218 if let Some(lse_drv) = lse_drv {
219 w.set_lsedrv(lse_drv.into());
220 }
221 w.set_lsebyp(lse_byp);
222 w.set_lseon(true);
136 }); 223 });
137 } else {
138 // check if it's already enabled and in the source we want.
139 let reg = Self::read();
140 let ok = reg.rtcsel() == clock_source;
141 #[cfg(not(rcc_wba))]
142 let ok = ok & reg.rtcen();
143
144 // if not, configure it.
145 if !ok {
146 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
147 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
148 224
149 #[cfg(not(any(rcc_l0, rcc_l1)))] 225 while !bdcr().read().lserdy() {}
150 Self::modify(|w| w.set_bdrst(true)); 226 }
151 227
152 Self::modify(|w| { 228 if self.rtc != RtcClockSource::DISABLE {
153 // Reset 229 bdcr().modify(|w| {
154 #[cfg(not(any(rcc_l0, rcc_l1)))] 230 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
155 w.set_bdrst(false); 231 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
156 232
157 #[cfg(not(rcc_wba))] 233 #[cfg(not(rcc_wba))]
158 w.set_rtcen(true); 234 w.set_rtcen(true);
159 w.set_rtcsel(clock_source); 235 w.set_rtcsel(self.rtc);
236 });
237 }
160 238
161 // Restore bcdr 239 trace!("BDCR configured: {:08x}", bdcr().read().0);
162 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
163 w.set_lscosel(reg.lscosel());
164 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
165 w.set_lscoen(reg.lscoen());
166 240
167 w.set_lseon(reg.lseon()); 241 compiler_fence(Ordering::SeqCst);
168 242
169 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] 243 rtc_clk
170 w.set_lsedrv(reg.lsedrv());
171 w.set_lsebyp(reg.lsebyp());
172 });
173 }
174 }
175 } 244 }
176} 245}
diff --git a/embassy-stm32/src/rcc/bus.rs b/embassy-stm32/src/rcc/bus.rs
deleted file mode 100644
index 495cf7fe1..000000000
--- a/embassy-stm32/src/rcc/bus.rs
+++ /dev/null
@@ -1,56 +0,0 @@
1use core::ops::Div;
2
3#[allow(unused_imports)]
4use crate::pac::rcc;
5pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
6use crate::time::Hertz;
7
8impl Div<AHBPrescaler> for Hertz {
9 type Output = Hertz;
10
11 fn div(self, rhs: AHBPrescaler) -> Self::Output {
12 let divisor = match rhs {
13 AHBPrescaler::DIV1 => 1,
14 AHBPrescaler::DIV2 => 2,
15 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
16 AHBPrescaler::DIV3 => 3,
17 AHBPrescaler::DIV4 => 4,
18 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
19 AHBPrescaler::DIV5 => 5,
20 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
21 AHBPrescaler::DIV6 => 6,
22 AHBPrescaler::DIV8 => 8,
23 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
24 AHBPrescaler::DIV10 => 10,
25 AHBPrescaler::DIV16 => 16,
26 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
27 AHBPrescaler::DIV32 => 32,
28 #[cfg(not(rcc_wba))]
29 AHBPrescaler::DIV64 => 64,
30 #[cfg(not(rcc_wba))]
31 AHBPrescaler::DIV128 => 128,
32 #[cfg(not(rcc_wba))]
33 AHBPrescaler::DIV256 => 256,
34 #[cfg(not(rcc_wba))]
35 AHBPrescaler::DIV512 => 512,
36 _ => unreachable!(),
37 };
38 Hertz(self.0 / divisor)
39 }
40}
41
42impl Div<APBPrescaler> for Hertz {
43 type Output = Hertz;
44
45 fn div(self, rhs: APBPrescaler) -> Self::Output {
46 let divisor = match rhs {
47 APBPrescaler::DIV1 => 1,
48 APBPrescaler::DIV2 => 2,
49 APBPrescaler::DIV4 => 4,
50 APBPrescaler::DIV8 => 8,
51 APBPrescaler::DIV16 => 16,
52 _ => unreachable!(),
53 };
54 Hertz(self.0 / divisor)
55 }
56}
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index 8f45e7c0f..68f029ca0 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -1,6 +1,6 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
3use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; 2use crate::pac::rcc::vals::Sw;
3pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Ppre as APBPrescaler};
4use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
5use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 6use crate::time::Hertz;
@@ -8,9 +8,6 @@ use crate::time::Hertz;
8/// HSI speed 8/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(48_000_000); 9pub const HSI_FREQ: Hertz = Hertz(48_000_000);
10 10
11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(32_000);
13
14/// System clock mux source 11/// System clock mux source
15#[derive(Clone, Copy)] 12#[derive(Clone, Copy)]
16pub enum ClockSrc { 13pub enum ClockSrc {
@@ -19,47 +16,22 @@ pub enum ClockSrc {
19 LSI, 16 LSI,
20} 17}
21 18
22#[derive(Clone, Copy)]
23pub enum HSIPrescaler {
24 NotDivided,
25 Div2,
26 Div4,
27 Div8,
28 Div16,
29 Div32,
30 Div64,
31 Div128,
32}
33
34impl Into<Hsidiv> for HSIPrescaler {
35 fn into(self) -> Hsidiv {
36 match self {
37 HSIPrescaler::NotDivided => Hsidiv::DIV1,
38 HSIPrescaler::Div2 => Hsidiv::DIV2,
39 HSIPrescaler::Div4 => Hsidiv::DIV4,
40 HSIPrescaler::Div8 => Hsidiv::DIV8,
41 HSIPrescaler::Div16 => Hsidiv::DIV16,
42 HSIPrescaler::Div32 => Hsidiv::DIV32,
43 HSIPrescaler::Div64 => Hsidiv::DIV64,
44 HSIPrescaler::Div128 => Hsidiv::DIV128,
45 }
46 }
47}
48
49/// Clocks configutation 19/// Clocks configutation
50pub struct Config { 20pub struct Config {
51 pub mux: ClockSrc, 21 pub mux: ClockSrc,
52 pub ahb_pre: AHBPrescaler, 22 pub ahb_pre: AHBPrescaler,
53 pub apb_pre: APBPrescaler, 23 pub apb_pre: APBPrescaler,
24 pub ls: super::LsConfig,
54} 25}
55 26
56impl Default for Config { 27impl Default for Config {
57 #[inline] 28 #[inline]
58 fn default() -> Config { 29 fn default() -> Config {
59 Config { 30 Config {
60 mux: ClockSrc::HSI(HSIPrescaler::NotDivided), 31 mux: ClockSrc::HSI(HSIPrescaler::DIV1),
61 ahb_pre: AHBPrescaler::DIV1, 32 ahb_pre: AHBPrescaler::DIV1,
62 apb_pre: APBPrescaler::DIV1, 33 apb_pre: APBPrescaler::DIV1,
34 ls: Default::default(),
63 } 35 }
64 } 36 }
65} 37}
@@ -68,33 +40,34 @@ pub(crate) unsafe fn init(config: Config) {
68 let (sys_clk, sw) = match config.mux { 40 let (sys_clk, sw) = match config.mux {
69 ClockSrc::HSI(div) => { 41 ClockSrc::HSI(div) => {
70 // Enable HSI 42 // Enable HSI
71 let div: Hsidiv = div.into();
72 RCC.cr().write(|w| { 43 RCC.cr().write(|w| {
73 w.set_hsidiv(div); 44 w.set_hsidiv(div);
74 w.set_hsion(true) 45 w.set_hsion(true)
75 }); 46 });
76 while !RCC.cr().read().hsirdy() {} 47 while !RCC.cr().read().hsirdy() {}
77 48
78 (HSI_FREQ.0 >> div.to_bits(), Sw::HSI) 49 (HSI_FREQ / div, Sw::HSI)
79 } 50 }
80 ClockSrc::HSE(freq) => { 51 ClockSrc::HSE(freq) => {
81 // Enable HSE 52 // Enable HSE
82 RCC.cr().write(|w| w.set_hseon(true)); 53 RCC.cr().write(|w| w.set_hseon(true));
83 while !RCC.cr().read().hserdy() {} 54 while !RCC.cr().read().hserdy() {}
84 55
85 (freq.0, Sw::HSE) 56 (freq, Sw::HSE)
86 } 57 }
87 ClockSrc::LSI => { 58 ClockSrc::LSI => {
88 // Enable LSI 59 // Enable LSI
89 RCC.csr2().write(|w| w.set_lsion(true)); 60 RCC.csr2().write(|w| w.set_lsion(true));
90 while !RCC.csr2().read().lsirdy() {} 61 while !RCC.csr2().read().lsirdy() {}
91 (LSI_FREQ.0, Sw::LSI) 62 (super::LSI_FREQ, Sw::LSI)
92 } 63 }
93 }; 64 };
94 65
66 let rtc = config.ls.init();
67
95 // Determine the flash latency implied by the target clock speed 68 // Determine the flash latency implied by the target clock speed
96 // RM0454 § 3.3.4: 69 // RM0454 § 3.3.4:
97 let target_flash_latency = if sys_clk <= 24_000_000 { 70 let target_flash_latency = if sys_clk <= Hertz(24_000_000) {
98 Latency::WS0 71 Latency::WS0
99 } else { 72 } else {
100 Latency::WS1 73 Latency::WS1
@@ -129,7 +102,7 @@ pub(crate) unsafe fn init(config: Config) {
129 } 102 }
130 103
131 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once 104 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once
132 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); 105 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
133 RCC.cfgr().modify(|w| { 106 RCC.cfgr().modify(|w| {
134 w.set_sw(sw); 107 w.set_sw(sw);
135 w.set_hpre(hpre); 108 w.set_hpre(hpre);
@@ -150,34 +123,23 @@ pub(crate) unsafe fn init(config: Config) {
150 FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); 123 FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
151 } 124 }
152 125
153 let ahb_div = match config.ahb_pre { 126 let ahb_freq = sys_clk / config.ahb_pre;
154 AHBPrescaler::DIV1 => 1,
155 AHBPrescaler::DIV2 => 2,
156 AHBPrescaler::DIV4 => 4,
157 AHBPrescaler::DIV8 => 8,
158 AHBPrescaler::DIV16 => 16,
159 AHBPrescaler::DIV64 => 64,
160 AHBPrescaler::DIV128 => 128,
161 AHBPrescaler::DIV256 => 256,
162 AHBPrescaler::DIV512 => 512,
163 _ => unreachable!(),
164 };
165 let ahb_freq = sys_clk / ahb_div;
166 127
167 let (apb_freq, apb_tim_freq) = match config.apb_pre { 128 let (apb_freq, apb_tim_freq) = match config.apb_pre {
168 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 129 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
169 pre => { 130 pre => {
170 let pre: Ppre = pre.into(); 131 let freq = ahb_freq / pre;
171 let pre: u8 = 1 << (pre.to_bits() - 3); 132 (freq, freq * 2u32)
172 let freq = ahb_freq / pre as u32;
173 (freq, freq * 2)
174 } 133 }
175 }; 134 };
176 135
177 set_freqs(Clocks { 136 set_freqs(Clocks {
178 sys: Hertz(sys_clk), 137 hsi: None,
179 ahb1: Hertz(ahb_freq), 138 lse: None,
180 apb1: Hertz(apb_freq), 139 sys: sys_clk,
181 apb1_tim: Hertz(apb_tim_freq), 140 hclk1: ahb_freq,
141 pclk1: apb_freq,
142 pclk1_tim: apb_tim_freq,
143 rtc,
182 }); 144 });
183} 145}
diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs
index ca6eed284..feaa2f4c0 100644
--- a/embassy-stm32/src/rcc/f0.rs
+++ b/embassy-stm32/src/rcc/f0.rs
@@ -8,9 +8,6 @@ use crate::time::Hertz;
8/// HSI speed 8/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(8_000_000); 9pub const HSI_FREQ: Hertz = Hertz(8_000_000);
10 10
11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(40_000);
13
14/// Configuration of the clocks 11/// Configuration of the clocks
15/// 12///
16/// hse takes precedence over hsi48 if both are enabled 13/// hse takes precedence over hsi48 if both are enabled
@@ -27,6 +24,8 @@ pub struct Config {
27 pub sys_ck: Option<Hertz>, 24 pub sys_ck: Option<Hertz>,
28 pub hclk: Option<Hertz>, 25 pub hclk: Option<Hertz>,
29 pub pclk: Option<Hertz>, 26 pub pclk: Option<Hertz>,
27
28 pub ls: super::LsConfig,
30} 29}
31 30
32pub(crate) unsafe fn init(config: Config) { 31pub(crate) unsafe fn init(config: Config) {
@@ -128,7 +127,7 @@ pub(crate) unsafe fn init(config: Config) {
128 } 127 }
129 128
130 if config.usb_pll { 129 if config.usb_pll {
131 RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLLCLK)); 130 RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLL1_P));
132 } 131 }
133 // TODO: Option to use CRS (Clock Recovery) 132 // TODO: Option to use CRS (Clock Recovery)
134 133
@@ -141,7 +140,7 @@ pub(crate) unsafe fn init(config: Config) {
141 RCC.cfgr().modify(|w| { 140 RCC.cfgr().modify(|w| {
142 w.set_ppre(Ppre::from_bits(ppre_bits)); 141 w.set_ppre(Ppre::from_bits(ppre_bits));
143 w.set_hpre(Hpre::from_bits(hpre_bits)); 142 w.set_hpre(Hpre::from_bits(hpre_bits));
144 w.set_sw(Sw::PLL) 143 w.set_sw(Sw::PLL1_P)
145 }); 144 });
146 } else { 145 } else {
147 RCC.cfgr().modify(|w| { 146 RCC.cfgr().modify(|w| {
@@ -159,12 +158,15 @@ pub(crate) unsafe fn init(config: Config) {
159 }) 158 })
160 } 159 }
161 160
161 let rtc = config.ls.init();
162
162 set_freqs(Clocks { 163 set_freqs(Clocks {
163 sys: Hertz(real_sysclk), 164 sys: Hertz(real_sysclk),
164 apb1: Hertz(pclk), 165 pclk1: Hertz(pclk),
165 apb2: Hertz(pclk), 166 pclk2: Hertz(pclk),
166 apb1_tim: Hertz(pclk * timer_mul), 167 pclk1_tim: Hertz(pclk * timer_mul),
167 apb2_tim: Hertz(pclk * timer_mul), 168 pclk2_tim: Hertz(pclk * timer_mul),
168 ahb1: Hertz(hclk), 169 hclk1: Hertz(hclk),
170 rtc,
169 }); 171 });
170} 172}
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs
index 081c0c767..8d315f7b2 100644
--- a/embassy-stm32/src/rcc/f1.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -9,9 +9,6 @@ use crate::time::Hertz;
9/// HSI speed 9/// HSI speed
10pub const HSI_FREQ: Hertz = Hertz(8_000_000); 10pub const HSI_FREQ: Hertz = Hertz(8_000_000);
11 11
12/// LSI speed
13pub const LSI_FREQ: Hertz = Hertz(40_000);
14
15/// Configuration of the clocks 12/// Configuration of the clocks
16/// 13///
17#[non_exhaustive] 14#[non_exhaustive]
@@ -25,6 +22,8 @@ pub struct Config {
25 pub pclk2: Option<Hertz>, 22 pub pclk2: Option<Hertz>,
26 pub adcclk: Option<Hertz>, 23 pub adcclk: Option<Hertz>,
27 pub pllxtpre: bool, 24 pub pllxtpre: bool,
25
26 pub ls: super::LsConfig,
28} 27}
29 28
30pub(crate) unsafe fn init(config: Config) { 29pub(crate) unsafe fn init(config: Config) {
@@ -103,7 +102,6 @@ pub(crate) unsafe fn init(config: Config) {
103 102
104 assert!(pclk2 <= 72_000_000); 103 assert!(pclk2 <= 72_000_000);
105 104
106 // Only needed for stm32f103?
107 FLASH.acr().write(|w| { 105 FLASH.acr().write(|w| {
108 w.set_latency(if real_sysclk <= 24_000_000 { 106 w.set_latency(if real_sysclk <= 24_000_000 {
109 Latency::WS0 107 Latency::WS0
@@ -112,6 +110,8 @@ pub(crate) unsafe fn init(config: Config) {
112 } else { 110 } else {
113 Latency::WS2 111 Latency::WS2
114 }); 112 });
113 // the prefetch buffer is enabled by default, let's keep it enabled
114 w.set_prftbe(true);
115 }); 115 });
116 116
117 // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the 117 // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
@@ -169,7 +169,14 @@ pub(crate) unsafe fn init(config: Config) {
169 #[cfg(not(rcc_f100))] 169 #[cfg(not(rcc_f100))]
170 w.set_usbpre(Usbpre::from_bits(usbpre as u8)); 170 w.set_usbpre(Usbpre::from_bits(usbpre as u8));
171 w.set_sw(if pllmul_bits.is_some() { 171 w.set_sw(if pllmul_bits.is_some() {
172 Sw::PLL 172 #[cfg(not(rcc_f1cl))]
173 {
174 Sw::PLL1_P
175 }
176 #[cfg(rcc_f1cl)]
177 {
178 Sw::PLL
179 }
173 } else if config.hse.is_some() { 180 } else if config.hse.is_some() {
174 Sw::HSE 181 Sw::HSE
175 } else { 182 } else {
@@ -177,13 +184,16 @@ pub(crate) unsafe fn init(config: Config) {
177 }); 184 });
178 }); 185 });
179 186
187 let rtc = config.ls.init();
188
180 set_freqs(Clocks { 189 set_freqs(Clocks {
181 sys: Hertz(real_sysclk), 190 sys: Hertz(real_sysclk),
182 apb1: Hertz(pclk1), 191 pclk1: Hertz(pclk1),
183 apb2: Hertz(pclk2), 192 pclk2: Hertz(pclk2),
184 apb1_tim: Hertz(pclk1 * timer_mul1), 193 pclk1_tim: Hertz(pclk1 * timer_mul1),
185 apb2_tim: Hertz(pclk2 * timer_mul2), 194 pclk2_tim: Hertz(pclk2 * timer_mul2),
186 ahb1: Hertz(hclk), 195 hclk1: Hertz(hclk),
187 adc: Some(Hertz(adcclk)), 196 adc: Some(Hertz(adcclk)),
197 rtc,
188 }); 198 });
189} 199}
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs
index 44de5bf19..9a66e75a4 100644
--- a/embassy-stm32/src/rcc/f2.rs
+++ b/embassy-stm32/src/rcc/f2.rs
@@ -1,21 +1,16 @@
1use core::convert::TryFrom;
2use core::ops::{Div, Mul};
3
4pub use super::bus::{AHBPrescaler, APBPrescaler};
5use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
6use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; 2use crate::pac::rcc::vals::Sw;
3pub use crate::pac::rcc::vals::{
4 Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc,
5 Ppre as APBPrescaler,
6};
7use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
8use crate::rcc::bd::BackupDomain;
9use crate::rcc::{set_freqs, Clocks}; 8use crate::rcc::{set_freqs, Clocks};
10use crate::rtc::RtcClockSource;
11use crate::time::Hertz; 9use crate::time::Hertz;
12 10
13/// HSI speed 11/// HSI speed
14pub const HSI_FREQ: Hertz = Hertz(16_000_000); 12pub const HSI_FREQ: Hertz = Hertz(16_000_000);
15 13
16/// LSI speed
17pub const LSI_FREQ: Hertz = Hertz(32_000);
18
19#[derive(Clone, Copy)] 14#[derive(Clone, Copy)]
20pub struct HSEConfig { 15pub struct HSEConfig {
21 pub frequency: Hertz, 16 pub frequency: Hertz,
@@ -43,17 +38,17 @@ pub enum HSESrc {
43pub struct PLLConfig { 38pub struct PLLConfig {
44 pub pre_div: PLLPreDiv, 39 pub pre_div: PLLPreDiv,
45 pub mul: PLLMul, 40 pub mul: PLLMul,
46 pub main_div: PLLMainDiv, 41 pub p_div: PLLPDiv,
47 pub pll48_div: PLL48Div, 42 pub q_div: PLLQDiv,
48} 43}
49 44
50impl Default for PLLConfig { 45impl Default for PLLConfig {
51 fn default() -> Self { 46 fn default() -> Self {
52 PLLConfig { 47 PLLConfig {
53 pre_div: PLLPreDiv(16), 48 pre_div: PLLPreDiv::DIV16,
54 mul: PLLMul(192), 49 mul: PLLMul::MUL192,
55 main_div: PLLMainDiv::Div2, 50 p_div: PLLPDiv::DIV2,
56 pll48_div: PLL48Div(4), 51 q_div: PLLQDiv::DIV4,
57 } 52 }
58 } 53 }
59} 54}
@@ -61,9 +56,9 @@ impl Default for PLLConfig {
61impl PLLConfig { 56impl PLLConfig {
62 pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { 57 pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
63 let in_freq = src_freq / self.pre_div; 58 let in_freq = src_freq / self.pre_div;
64 let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32); 59 let vco_freq = src_freq / self.pre_div * self.mul;
65 let main_freq = vco_freq / self.main_div; 60 let main_freq = vco_freq / self.p_div;
66 let pll48_freq = vco_freq / self.pll48_div; 61 let pll48_freq = vco_freq / self.q_div;
67 PLLClocks { 62 PLLClocks {
68 in_freq, 63 in_freq,
69 vco_freq, 64 vco_freq,
@@ -72,129 +67,6 @@ impl PLLConfig {
72 } 67 }
73 } 68 }
74} 69}
75
76/// Clock source for both main PLL and PLLI2S
77#[derive(Clone, Copy, PartialEq)]
78pub enum PLLSrc {
79 HSE,
80 HSI,
81}
82
83impl Into<Pllsrc> for PLLSrc {
84 fn into(self) -> Pllsrc {
85 match self {
86 PLLSrc::HSE => Pllsrc::HSE,
87 PLLSrc::HSI => Pllsrc::HSI,
88 }
89 }
90}
91
92/// Division factor for both main PLL and PLLI2S
93#[derive(Clone, Copy, PartialEq)]
94#[repr(transparent)]
95pub struct PLLPreDiv(u8);
96
97impl TryFrom<u8> for PLLPreDiv {
98 type Error = &'static str;
99
100 fn try_from(value: u8) -> Result<Self, Self::Error> {
101 match value {
102 2..=63 => Ok(PLLPreDiv(value)),
103 _ => Err("PLLPreDiv must be within range 2..=63"),
104 }
105 }
106}
107
108impl Div<PLLPreDiv> for Hertz {
109 type Output = Hertz;
110
111 fn div(self, rhs: PLLPreDiv) -> Self::Output {
112 Hertz(self.0 / u32::from(rhs.0))
113 }
114}
115
116/// Multiplication factor for main PLL
117#[derive(Clone, Copy, PartialEq)]
118#[repr(transparent)]
119pub struct PLLMul(u16);
120
121impl Mul<PLLMul> for Hertz {
122 type Output = Hertz;
123
124 fn mul(self, rhs: PLLMul) -> Self::Output {
125 Hertz(self.0 * u32::from(rhs.0))
126 }
127}
128
129impl TryFrom<u16> for PLLMul {
130 type Error = &'static str;
131
132 fn try_from(value: u16) -> Result<Self, Self::Error> {
133 match value {
134 192..=432 => Ok(PLLMul(value)),
135 _ => Err("PLLMul must be within range 192..=432"),
136 }
137 }
138}
139
140/// PLL division factor for the main system clock
141#[derive(Clone, Copy, PartialEq)]
142pub enum PLLMainDiv {
143 Div2,
144 Div4,
145 Div6,
146 Div8,
147}
148
149impl Into<Pllp> for PLLMainDiv {
150 fn into(self) -> Pllp {
151 match self {
152 PLLMainDiv::Div2 => Pllp::DIV2,
153 PLLMainDiv::Div4 => Pllp::DIV4,
154 PLLMainDiv::Div6 => Pllp::DIV6,
155 PLLMainDiv::Div8 => Pllp::DIV8,
156 }
157 }
158}
159
160impl Div<PLLMainDiv> for Hertz {
161 type Output = Hertz;
162
163 fn div(self, rhs: PLLMainDiv) -> Self::Output {
164 let divisor = match rhs {
165 PLLMainDiv::Div2 => 2,
166 PLLMainDiv::Div4 => 4,
167 PLLMainDiv::Div6 => 6,
168 PLLMainDiv::Div8 => 8,
169 };
170 Hertz(self.0 / divisor)
171 }
172}
173
174/// PLL division factor for USB OTG FS / SDIO / RNG
175#[derive(Clone, Copy, PartialEq)]
176#[repr(transparent)]
177pub struct PLL48Div(u8);
178
179impl Div<PLL48Div> for Hertz {
180 type Output = Hertz;
181
182 fn div(self, rhs: PLL48Div) -> Self::Output {
183 Hertz(self.0 / u32::from(rhs.0))
184 }
185}
186
187impl TryFrom<u8> for PLL48Div {
188 type Error = &'static str;
189
190 fn try_from(value: u8) -> Result<Self, Self::Error> {
191 match value {
192 2..=15 => Ok(PLL48Div(value)),
193 _ => Err("PLL48Div must be within range 2..=15"),
194 }
195 }
196}
197
198#[derive(Clone, Copy, PartialEq)] 70#[derive(Clone, Copy, PartialEq)]
199pub struct PLLClocks { 71pub struct PLLClocks {
200 pub in_freq: Hertz, 72 pub in_freq: Hertz,
@@ -303,13 +175,11 @@ pub struct Config {
303 pub pll_mux: PLLSrc, 175 pub pll_mux: PLLSrc,
304 pub pll: PLLConfig, 176 pub pll: PLLConfig,
305 pub mux: ClockSrc, 177 pub mux: ClockSrc,
306 pub rtc: Option<RtcClockSource>,
307 pub lsi: bool,
308 pub lse: Option<Hertz>,
309 pub voltage: VoltageScale, 178 pub voltage: VoltageScale,
310 pub ahb_pre: AHBPrescaler, 179 pub ahb_pre: AHBPrescaler,
311 pub apb1_pre: APBPrescaler, 180 pub apb1_pre: APBPrescaler,
312 pub apb2_pre: APBPrescaler, 181 pub apb2_pre: APBPrescaler,
182 pub ls: super::LsConfig,
313} 183}
314 184
315impl Default for Config { 185impl Default for Config {
@@ -322,12 +192,10 @@ impl Default for Config {
322 pll: PLLConfig::default(), 192 pll: PLLConfig::default(),
323 voltage: VoltageScale::Range3, 193 voltage: VoltageScale::Range3,
324 mux: ClockSrc::HSI, 194 mux: ClockSrc::HSI,
325 rtc: None,
326 lsi: false,
327 lse: None,
328 ahb_pre: AHBPrescaler::DIV1, 195 ahb_pre: AHBPrescaler::DIV1,
329 apb1_pre: APBPrescaler::DIV1, 196 apb1_pre: APBPrescaler::DIV1,
330 apb2_pre: APBPrescaler::DIV1, 197 apb2_pre: APBPrescaler::DIV1,
198 ls: Default::default(),
331 } 199 }
332 } 200 }
333} 201}
@@ -367,11 +235,11 @@ pub(crate) unsafe fn init(config: Config) {
367 assert!(pll_clocks.pll48_freq <= Hertz(48_000_000)); 235 assert!(pll_clocks.pll48_freq <= Hertz(48_000_000));
368 236
369 RCC.pllcfgr().write(|w| { 237 RCC.pllcfgr().write(|w| {
370 w.set_pllsrc(config.pll_mux.into()); 238 w.set_pllsrc(config.pll_mux);
371 w.set_pllm(config.pll.pre_div.0); 239 w.set_pllm(config.pll.pre_div);
372 w.set_plln(config.pll.mul.0); 240 w.set_plln(config.pll.mul);
373 w.set_pllp(config.pll.main_div.into()); 241 w.set_pllp(config.pll.p_div);
374 w.set_pllq(config.pll.pll48_div.0); 242 w.set_pllq(config.pll.q_div);
375 }); 243 });
376 244
377 let (sys_clk, sw) = match config.mux { 245 let (sys_clk, sw) = match config.mux {
@@ -388,7 +256,7 @@ pub(crate) unsafe fn init(config: Config) {
388 ClockSrc::PLL => { 256 ClockSrc::PLL => {
389 RCC.cr().modify(|w| w.set_pllon(true)); 257 RCC.cr().modify(|w| w.set_pllon(true));
390 while !RCC.cr().read().pllrdy() {} 258 while !RCC.cr().read().pllrdy() {}
391 (pll_clocks.main_freq, Sw::PLL) 259 (pll_clocks.main_freq, Sw::PLL1_P)
392 } 260 }
393 }; 261 };
394 // RM0033 Figure 9. Clock tree suggests max SYSCLK/HCLK is 168 MHz, but datasheet specifies PLL 262 // RM0033 Figure 9. Clock tree suggests max SYSCLK/HCLK is 168 MHz, but datasheet specifies PLL
@@ -424,9 +292,9 @@ pub(crate) unsafe fn init(config: Config) {
424 292
425 RCC.cfgr().modify(|w| { 293 RCC.cfgr().modify(|w| {
426 w.set_sw(sw.into()); 294 w.set_sw(sw.into());
427 w.set_hpre(config.ahb_pre.into()); 295 w.set_hpre(config.ahb_pre);
428 w.set_ppre1(config.apb1_pre.into()); 296 w.set_ppre1(config.apb1_pre);
429 w.set_ppre2(config.apb2_pre.into()); 297 w.set_ppre2(config.apb2_pre);
430 }); 298 });
431 while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {} 299 while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
432 300
@@ -435,21 +303,18 @@ pub(crate) unsafe fn init(config: Config) {
435 RCC.cr().modify(|w| w.set_hsion(false)); 303 RCC.cr().modify(|w| w.set_hsion(false));
436 } 304 }
437 305
438 BackupDomain::configure_ls( 306 let rtc = config.ls.init();
439 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
440 config.lsi,
441 config.lse.map(|_| Default::default()),
442 );
443 307
444 set_freqs(Clocks { 308 set_freqs(Clocks {
445 sys: sys_clk, 309 sys: sys_clk,
446 ahb1: ahb_freq, 310 hclk1: ahb_freq,
447 ahb2: ahb_freq, 311 hclk2: ahb_freq,
448 ahb3: ahb_freq, 312 hclk3: ahb_freq,
449 apb1: apb1_freq, 313 pclk1: apb1_freq,
450 apb1_tim: apb1_tim_freq, 314 pclk1_tim: apb1_tim_freq,
451 apb2: apb2_freq, 315 pclk2: apb2_freq,
452 apb2_tim: apb2_tim_freq, 316 pclk2_tim: apb2_tim_freq,
453 pll48: Some(pll_clocks.pll48_freq), 317 pll1_q: Some(pll_clocks.pll48_freq),
318 rtc,
454 }); 319 });
455} 320}
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 630dbd4fe..9dcd50df4 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,7 +1,8 @@
1#[cfg(rcc_f3)] 1#[cfg(rcc_f3)]
2use crate::pac::adccommon::vals::Ckmode; 2use crate::pac::adccommon::vals::Ckmode;
3use crate::pac::flash::vals::Latency; 3use crate::pac::flash::vals::Latency;
4use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 4pub use crate::pac::rcc::vals::Adcpres;
5use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
5use crate::pac::{FLASH, RCC}; 6use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks}; 7use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz; 8use crate::time::Hertz;
@@ -9,28 +10,6 @@ use crate::time::Hertz;
9/// HSI speed 10/// HSI speed
10pub const HSI_FREQ: Hertz = Hertz(8_000_000); 11pub const HSI_FREQ: Hertz = Hertz(8_000_000);
11 12
12/// LSI speed
13pub const LSI_FREQ: Hertz = Hertz(40_000);
14
15impl From<AdcClockSource> for Adcpres {
16 fn from(value: AdcClockSource) -> Self {
17 match value {
18 AdcClockSource::PllDiv1 => Adcpres::DIV1,
19 AdcClockSource::PllDiv2 => Adcpres::DIV2,
20 AdcClockSource::PllDiv4 => Adcpres::DIV4,
21 AdcClockSource::PllDiv6 => Adcpres::DIV6,
22 AdcClockSource::PllDiv8 => Adcpres::DIV8,
23 AdcClockSource::PllDiv12 => Adcpres::DIV12,
24 AdcClockSource::PllDiv16 => Adcpres::DIV16,
25 AdcClockSource::PllDiv32 => Adcpres::DIV32,
26 AdcClockSource::PllDiv64 => Adcpres::DIV64,
27 AdcClockSource::PllDiv128 => Adcpres::DIV128,
28 AdcClockSource::PllDiv256 => Adcpres::DIV256,
29 _ => unreachable!(),
30 }
31 }
32}
33
34#[cfg(rcc_f3)] 13#[cfg(rcc_f3)]
35impl From<AdcClockSource> for Ckmode { 14impl From<AdcClockSource> for Ckmode {
36 fn from(value: AdcClockSource) -> Self { 15 fn from(value: AdcClockSource) -> Self {
@@ -45,32 +24,13 @@ impl From<AdcClockSource> for Ckmode {
45 24
46#[derive(Clone, Copy)] 25#[derive(Clone, Copy)]
47pub enum AdcClockSource { 26pub enum AdcClockSource {
48 PllDiv1 = 1, 27 Pll(Adcpres),
49 PllDiv2 = 2,
50 PllDiv4 = 4,
51 PllDiv6 = 6,
52 PllDiv8 = 8,
53 PllDiv12 = 12,
54 PllDiv16 = 16,
55 PllDiv32 = 32,
56 PllDiv64 = 64,
57 PllDiv128 = 128,
58 PllDiv256 = 256,
59 BusDiv1, 28 BusDiv1,
60 BusDiv2, 29 BusDiv2,
61 BusDiv4, 30 BusDiv4,
62} 31}
63 32
64impl AdcClockSource { 33impl AdcClockSource {
65 pub fn is_bus(&self) -> bool {
66 match self {
67 Self::BusDiv1 => true,
68 Self::BusDiv2 => true,
69 Self::BusDiv4 => true,
70 _ => false,
71 }
72 }
73
74 pub fn bus_div(&self) -> u32 { 34 pub fn bus_div(&self) -> u32 {
75 match self { 35 match self {
76 Self::BusDiv1 => 1, 36 Self::BusDiv1 => 1,
@@ -124,6 +84,7 @@ pub struct Config {
124 pub adc34: Option<AdcClockSource>, 84 pub adc34: Option<AdcClockSource>,
125 #[cfg(stm32f334)] 85 #[cfg(stm32f334)]
126 pub hrtim: HrtimClockSource, 86 pub hrtim: HrtimClockSource,
87 pub ls: super::LsConfig,
127} 88}
128 89
129// Information required to setup the PLL clock 90// Information required to setup the PLL clock
@@ -137,67 +98,67 @@ struct PllConfig {
137/// Initialize and Set the clock frequencies 98/// Initialize and Set the clock frequencies
138pub(crate) unsafe fn init(config: Config) { 99pub(crate) unsafe fn init(config: Config) {
139 // Calculate the real System clock, and PLL configuration if applicable 100 // Calculate the real System clock, and PLL configuration if applicable
140 let (Hertz(sysclk), pll_config) = get_sysclk(&config); 101 let (sysclk, pll_config) = get_sysclk(&config);
141 assert!(sysclk <= 72_000_000); 102 assert!(sysclk.0 <= 72_000_000);
142 103
143 // Calculate real AHB clock 104 // Calculate real AHB clock
144 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk); 105 let hclk = config.hclk.map(|h| h).unwrap_or(sysclk);
145 let (hpre_bits, hpre_div) = match sysclk / hclk { 106 let hpre = match sysclk.0 / hclk.0 {
146 0 => unreachable!(), 107 0 => unreachable!(),
147 1 => (Hpre::DIV1, 1), 108 1 => Hpre::DIV1,
148 2 => (Hpre::DIV2, 2), 109 2 => Hpre::DIV2,
149 3..=5 => (Hpre::DIV4, 4), 110 3..=5 => Hpre::DIV4,
150 6..=11 => (Hpre::DIV8, 8), 111 6..=11 => Hpre::DIV8,
151 12..=39 => (Hpre::DIV16, 16), 112 12..=39 => Hpre::DIV16,
152 40..=95 => (Hpre::DIV64, 64), 113 40..=95 => Hpre::DIV64,
153 96..=191 => (Hpre::DIV128, 128), 114 96..=191 => Hpre::DIV128,
154 192..=383 => (Hpre::DIV256, 256), 115 192..=383 => Hpre::DIV256,
155 _ => (Hpre::DIV512, 512), 116 _ => Hpre::DIV512,
156 }; 117 };
157 let hclk = sysclk / hpre_div; 118 let hclk = sysclk / hpre;
158 assert!(hclk <= 72_000_000); 119 assert!(hclk <= Hertz(72_000_000));
159 120
160 // Calculate real APB1 clock 121 // Calculate real APB1 clock
161 let pclk1 = config.pclk1.map(|p| p.0).unwrap_or(hclk); 122 let pclk1 = config.pclk1.unwrap_or(hclk);
162 let (ppre1_bits, ppre1) = match hclk / pclk1 { 123 let ppre1 = match hclk / pclk1 {
163 0 => unreachable!(), 124 0 => unreachable!(),
164 1 => (Ppre::DIV1, 1), 125 1 => Ppre::DIV1,
165 2 => (Ppre::DIV2, 2), 126 2 => Ppre::DIV2,
166 3..=5 => (Ppre::DIV4, 4), 127 3..=5 => Ppre::DIV4,
167 6..=11 => (Ppre::DIV8, 8), 128 6..=11 => Ppre::DIV8,
168 _ => (Ppre::DIV16, 16), 129 _ => Ppre::DIV16,
169 }; 130 };
170 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; 131 let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 };
171 let pclk1 = hclk / ppre1; 132 let pclk1 = hclk / ppre1;
172 assert!(pclk1 <= 36_000_000); 133 assert!(pclk1 <= Hertz(36_000_000));
173 134
174 // Calculate real APB2 clock 135 // Calculate real APB2 clock
175 let pclk2 = config.pclk2.map(|p| p.0).unwrap_or(hclk); 136 let pclk2 = config.pclk2.unwrap_or(hclk);
176 let (ppre2_bits, ppre2) = match hclk / pclk2 { 137 let ppre2 = match hclk / pclk2 {
177 0 => unreachable!(), 138 0 => unreachable!(),
178 1 => (Ppre::DIV1, 1), 139 1 => Ppre::DIV1,
179 2 => (Ppre::DIV2, 2), 140 2 => Ppre::DIV2,
180 3..=5 => (Ppre::DIV4, 4), 141 3..=5 => Ppre::DIV4,
181 6..=11 => (Ppre::DIV8, 8), 142 6..=11 => Ppre::DIV8,
182 _ => (Ppre::DIV16, 16), 143 _ => Ppre::DIV16,
183 }; 144 };
184 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; 145 let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 };
185 let pclk2 = hclk / ppre2; 146 let pclk2 = hclk / ppre2;
186 assert!(pclk2 <= 72_000_000); 147 assert!(pclk2 <= Hertz(72_000_000));
187 148
188 // Set latency based on HCLK frquency 149 // Set latency based on HCLK frquency
189 // RM0316: "The prefetch buffer must be kept on when using a prescaler 150 // RM0316: "The prefetch buffer must be kept on when using a prescaler
190 // different from 1 on the AHB clock.", "Half-cycle access cannot be 151 // different from 1 on the AHB clock.", "Half-cycle access cannot be
191 // used when there is a prescaler different from 1 on the AHB clock" 152 // used when there is a prescaler different from 1 on the AHB clock"
192 FLASH.acr().modify(|w| { 153 FLASH.acr().modify(|w| {
193 w.set_latency(if hclk <= 24_000_000 { 154 w.set_latency(if hclk <= Hertz(24_000_000) {
194 Latency::WS0 155 Latency::WS0
195 } else if hclk <= 48_000_000 { 156 } else if hclk <= Hertz(48_000_000) {
196 Latency::WS1 157 Latency::WS1
197 } else { 158 } else {
198 Latency::WS2 159 Latency::WS2
199 }); 160 });
200 if hpre_div != 1 { 161 if hpre != Hpre::DIV1 {
201 w.set_hlfcya(false); 162 w.set_hlfcya(false);
202 w.set_prftbe(true); 163 w.set_prftbe(true);
203 } 164 }
@@ -240,9 +201,9 @@ pub(crate) unsafe fn init(config: Config) {
240 // Set prescalers 201 // Set prescalers
241 // CFGR has been written before (PLL, PLL48) don't overwrite these settings 202 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
242 RCC.cfgr().modify(|w| { 203 RCC.cfgr().modify(|w| {
243 w.set_ppre2(ppre2_bits); 204 w.set_ppre2(ppre2);
244 w.set_ppre1(ppre1_bits); 205 w.set_ppre1(ppre1);
245 w.set_hpre(hpre_bits); 206 w.set_hpre(hpre);
246 }); 207 });
247 208
248 // Wait for the new prescalers to kick in 209 // Wait for the new prescalers to kick in
@@ -253,52 +214,50 @@ pub(crate) unsafe fn init(config: Config) {
253 // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings 214 // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings
254 RCC.cfgr().modify(|w| { 215 RCC.cfgr().modify(|w| {
255 w.set_sw(match (pll_config, config.hse) { 216 w.set_sw(match (pll_config, config.hse) {
256 (Some(_), _) => Sw::PLL, 217 (Some(_), _) => Sw::PLL1_P,
257 (None, Some(_)) => Sw::HSE, 218 (None, Some(_)) => Sw::HSE,
258 (None, None) => Sw::HSI, 219 (None, None) => Sw::HSI,
259 }) 220 })
260 }); 221 });
261 222
262 #[cfg(rcc_f3)] 223 #[cfg(rcc_f3)]
263 let adc = config.adc.map(|adc| { 224 let adc = config.adc.map(|adc| match adc {
264 if !adc.is_bus() { 225 AdcClockSource::Pll(adcpres) => {
265 RCC.cfgr2().modify(|w| { 226 RCC.cfgr2().modify(|w| {
266 // Make sure that we're using the PLL 227 // Make sure that we're using the PLL
267 pll_config.unwrap(); 228 pll_config.unwrap();
268 w.set_adc12pres(adc.into()); 229 w.set_adc12pres(adcpres);
269 230
270 Hertz(sysclk / adc as u32) 231 sysclk / adcpres
271 }) 232 })
272 } else { 233 }
273 crate::pac::ADC_COMMON.ccr().modify(|w| { 234 _ => crate::pac::ADC_COMMON.ccr().modify(|w| {
274 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); 235 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
275 236
276 w.set_ckmode(adc.into()); 237 w.set_ckmode(adc.into());
277 238
278 Hertz(sysclk / adc.bus_div() as u32) 239 sysclk / adc.bus_div()
279 }) 240 }),
280 }
281 }); 241 });
282 242
283 #[cfg(all(rcc_f3, adc3_common))] 243 #[cfg(all(rcc_f3, adc3_common))]
284 let adc34 = config.adc.map(|adc| { 244 let adc34 = config.adc34.map(|adc| match adc {
285 if !adc.is_bus() { 245 AdcClockSource::Pll(adcpres) => {
286 RCC.cfgr2().modify(|w| { 246 RCC.cfgr2().modify(|w| {
287 // Make sure that we're using the PLL 247 // Make sure that we're using the PLL
288 pll_config.unwrap(); 248 pll_config.unwrap();
289 w.set_adc12pres(adc.into()); 249 w.set_adc34pres(adcpres);
290 250
291 Hertz(sysclk / adc as u32) 251 sysclk / adcpres
292 }) 252 })
293 } else { 253 }
294 crate::pac::ADC3_COMMON.ccr().modify(|w| { 254 _ => crate::pac::ADC_COMMON.ccr().modify(|w| {
295 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); 255 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
296 256
297 w.set_ckmode(adc.into()); 257 w.set_ckmode(adc.into());
298 258
299 Hertz(sysclk / adc.bus_div() as u32) 259 sysclk / adc.bus_div()
300 }) 260 }),
301 }
302 }); 261 });
303 262
304 #[cfg(stm32f334)] 263 #[cfg(stm32f334)]
@@ -310,21 +269,23 @@ pub(crate) unsafe fn init(config: Config) {
310 269
311 // Make sure that we're using the PLL 270 // Make sure that we're using the PLL
312 pll_config.unwrap(); 271 pll_config.unwrap();
313 assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk)); 272 assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk));
314 273
315 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL)); 274 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL1_P));
316 275
317 Some(Hertz(sysclk * 2)) 276 Some(sysclk * 2u32)
318 } 277 }
319 }; 278 };
320 279
280 let rtc = config.ls.init();
281
321 set_freqs(Clocks { 282 set_freqs(Clocks {
322 sys: Hertz(sysclk), 283 sys: sysclk,
323 apb1: Hertz(pclk1), 284 pclk1: pclk1,
324 apb2: Hertz(pclk2), 285 pclk2: pclk2,
325 apb1_tim: Hertz(pclk1 * timer_mul1), 286 pclk1_tim: pclk1 * timer_mul1,
326 apb2_tim: Hertz(pclk2 * timer_mul2), 287 pclk2_tim: pclk2 * timer_mul2,
327 ahb1: Hertz(hclk), 288 hclk1: hclk,
328 #[cfg(rcc_f3)] 289 #[cfg(rcc_f3)]
329 adc: adc, 290 adc: adc,
330 #[cfg(all(rcc_f3, adc3_common))] 291 #[cfg(all(rcc_f3, adc3_common))]
@@ -333,6 +294,7 @@ pub(crate) unsafe fn init(config: Config) {
333 adc34: None, 294 adc34: None,
334 #[cfg(stm32f334)] 295 #[cfg(stm32f334)]
335 hrtim: hrtim, 296 hrtim: hrtim,
297 rtc,
336 }); 298 });
337} 299}
338 300
@@ -421,16 +383,16 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
421 383
422#[inline] 384#[inline]
423#[allow(unused_variables)] 385#[allow(unused_variables)]
424fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre { 386fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option<PllConfig>) -> Usbpre {
425 cfg_if::cfg_if! { 387 cfg_if::cfg_if! {
426 // Some chips do not have USB 388 // Some chips do not have USB
427 if #[cfg(any(stm32f301, stm32f318, stm32f334))] { 389 if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
428 panic!("USB clock not supported by the chip"); 390 panic!("USB clock not supported by the chip");
429 } else { 391 } else {
430 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000); 392 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000));
431 match (usb_ok, sysclk) { 393 match (usb_ok, sysclk) {
432 (true, 72_000_000) => Usbpre::DIV1_5, 394 (true, Hertz(72_000_000)) => Usbpre::DIV1_5,
433 (true, 48_000_000) => Usbpre::DIV1, 395 (true, Hertz(48_000_000)) => Usbpre::DIV1,
434 _ => panic!( 396 _ => panic!(
435 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz" 397 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
436 ), 398 ),
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
deleted file mode 100644
index ebf78d0e2..000000000
--- a/embassy-stm32/src/rcc/f4.rs
+++ /dev/null
@@ -1,579 +0,0 @@
1use core::marker::PhantomData;
2
3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};
5
6use crate::gpio::sealed::AFType;
7use crate::gpio::Speed;
8use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
9use crate::pac::{FLASH, PWR, RCC};
10use crate::rcc::bd::{BackupDomain, RtcClockSource};
11use crate::rcc::{set_freqs, Clocks};
12use crate::time::Hertz;
13use crate::{peripherals, Peripheral};
14
15/// HSI speed
16pub const HSI_FREQ: Hertz = Hertz(16_000_000);
17
18/// LSI speed
19pub const LSI_FREQ: Hertz = Hertz(32_000);
20
21/// Clocks configuration
22#[non_exhaustive]
23#[derive(Default)]
24pub struct Config {
25 pub hse: Option<Hertz>,
26 pub bypass_hse: bool,
27 pub hclk: Option<Hertz>,
28 pub sys_ck: Option<Hertz>,
29 pub pclk1: Option<Hertz>,
30 pub pclk2: Option<Hertz>,
31
32 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
33 pub plli2s: Option<Hertz>,
34
35 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
36 pub pllsai: Option<Hertz>,
37
38 pub pll48: bool,
39 pub rtc: Option<RtcClockSource>,
40 pub lsi: bool,
41 pub lse: Option<Hertz>,
42}
43
44#[cfg(stm32f410)]
45fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
46 None
47}
48
49// Not currently implemented, but will be in the future
50#[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
51fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
52 None
53}
54
55#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
56fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option<u32>) -> Option<(u32, u32, u32)> {
57 let min_div = 2;
58 let target = match target {
59 Some(target) => target,
60 None => return None,
61 };
62
63 // We loop through the possible divider values to find the best configuration. Looping
64 // through all possible "N" values would result in more iterations.
65 let (n, outdiv, output, _error) = (min_div..=max_div)
66 .filter_map(|outdiv| {
67 let target_vco_out = match target.checked_mul(outdiv) {
68 Some(x) => x,
69 None => return None,
70 };
71 let n = (target_vco_out + (vco_in >> 1)) / vco_in;
72 let vco_out = vco_in * n;
73 if !(100_000_000..=432_000_000).contains(&vco_out) {
74 return None;
75 }
76 let output = vco_out / outdiv;
77 let error = (output as i32 - target as i32).unsigned_abs();
78 Some((n, outdiv, output, error))
79 })
80 .min_by_key(|(_, _, _, error)| *error)?;
81
82 Some((n, outdiv, output))
83}
84
85#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
86fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
87 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?;
88
89 RCC.plli2scfgr().modify(|w| {
90 w.set_plli2sn(n as u16);
91 w.set_plli2sr(outdiv as u8);
92 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
93 w.set_plli2sq(outdiv as u8); //set sai divider same as i2s
94 });
95
96 Some(output)
97}
98
99#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
100fn setup_sai_pll(_vco_in: u32, _pllsai: Option<u32>) -> Option<u32> {
101 None
102}
103
104#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
105fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
106 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 15, pllsai)?;
107
108 RCC.pllsaicfgr().modify(|w| {
109 w.set_pllsain(n as u16);
110 w.set_pllsaiq(outdiv as u8);
111 });
112
113 Some(output)
114}
115
116fn setup_pll(
117 pllsrcclk: u32,
118 use_hse: bool,
119 pllsysclk: Option<u32>,
120 plli2s: Option<u32>,
121 pllsai: Option<u32>,
122 pll48clk: bool,
123) -> PllResults {
124 use crate::pac::rcc::vals::{Pllp, Pllsrc};
125
126 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
127 if pllsysclk.is_none() && !pll48clk {
128 RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)));
129
130 return PllResults {
131 use_pll: false,
132 pllsysclk: None,
133 pll48clk: None,
134 plli2sclk: None,
135 pllsaiclk: None,
136 };
137 }
138 // Input divisor from PLL source clock, must result to frequency in
139 // the range from 1 to 2 MHz
140 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
141 let pllm_max = pllsrcclk / 1_000_000;
142
143 // Sysclk output divisor must be one of 2, 4, 6 or 8
144 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
145
146 let target_freq = if pll48clk { 48_000_000 } else { sysclk * sysclk_div };
147
148 // Find the lowest pllm value that minimize the difference between
149 // target frequency and the real vco_out frequency.
150 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| {
151 let vco_in = pllsrcclk / pllm;
152 let plln = target_freq / vco_in;
153 target_freq - vco_in * plln
154 }));
155
156 let vco_in = pllsrcclk / pllm;
157 assert!((1_000_000..=2_000_000).contains(&vco_in));
158
159 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
160 // and <= 432MHz, min 50, max 432
161 let plln = if pll48clk {
162 // try the different valid pllq according to the valid
163 // main scaller values, and take the best
164 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
165 let plln = 48_000_000 * pllq / vco_in;
166 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
167 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
168 (pll48_diff, sysclk_diff)
169 }));
170 48_000_000 * pllq / vco_in
171 } else {
172 sysclk * sysclk_div / vco_in
173 };
174
175 let pllp = (sysclk_div / 2) - 1;
176
177 let pllq = (vco_in * plln + 47_999_999) / 48_000_000;
178 let real_pll48clk = vco_in * plln / pllq;
179
180 RCC.pllcfgr().modify(|w| {
181 w.set_pllm(pllm as u8);
182 w.set_plln(plln as u16);
183 w.set_pllp(Pllp::from_bits(pllp as u8));
184 w.set_pllq(pllq as u8);
185 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
186 w.set_pllr(0);
187 });
188
189 let real_pllsysclk = vco_in * plln / sysclk_div;
190
191 PllResults {
192 use_pll: true,
193 pllsysclk: Some(real_pllsysclk),
194 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
195 plli2sclk: setup_i2s_pll(vco_in, plli2s),
196 pllsaiclk: setup_sai_pll(vco_in, pllsai),
197 }
198}
199
200pub enum McoClock {
201 DIV1,
202 DIV2,
203 DIV3,
204 DIV4,
205 DIV5,
206}
207
208impl McoClock {
209 fn into_raw(&self) -> Mcopre {
210 match self {
211 McoClock::DIV1 => Mcopre::DIV1,
212 McoClock::DIV2 => Mcopre::DIV2,
213 McoClock::DIV3 => Mcopre::DIV3,
214 McoClock::DIV4 => Mcopre::DIV4,
215 McoClock::DIV5 => Mcopre::DIV5,
216 }
217 }
218}
219
220#[derive(Copy, Clone)]
221pub enum Mco1Source {
222 Hsi,
223 Lse,
224 Hse,
225 Pll,
226}
227
228impl Default for Mco1Source {
229 fn default() -> Self {
230 Self::Hsi
231 }
232}
233
234pub trait McoSource {
235 type Raw;
236
237 fn into_raw(&self) -> Self::Raw;
238}
239
240impl McoSource for Mco1Source {
241 type Raw = Mco1;
242 fn into_raw(&self) -> Self::Raw {
243 match self {
244 Mco1Source::Hsi => Mco1::HSI,
245 Mco1Source::Lse => Mco1::LSE,
246 Mco1Source::Hse => Mco1::HSE,
247 Mco1Source::Pll => Mco1::PLL,
248 }
249 }
250}
251
252#[derive(Copy, Clone)]
253pub enum Mco2Source {
254 SysClk,
255 Plli2s,
256 Hse,
257 Pll,
258}
259
260impl Default for Mco2Source {
261 fn default() -> Self {
262 Self::SysClk
263 }
264}
265
266impl McoSource for Mco2Source {
267 type Raw = Mco2;
268 fn into_raw(&self) -> Self::Raw {
269 match self {
270 Mco2Source::SysClk => Mco2::SYSCLK,
271 Mco2Source::Plli2s => Mco2::PLLI2S,
272 Mco2Source::Hse => Mco2::HSE,
273 Mco2Source::Pll => Mco2::PLL,
274 }
275 }
276}
277
278pub(crate) mod sealed {
279 use stm32_metapac::rcc::vals::Mcopre;
280 pub trait McoInstance {
281 type Source;
282 unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre);
283 }
284}
285
286pub trait McoInstance: sealed::McoInstance + 'static {}
287
288pin_trait!(McoPin, McoInstance);
289
290impl sealed::McoInstance for peripherals::MCO1 {
291 type Source = Mco1;
292 unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
293 RCC.cfgr().modify(|w| {
294 w.set_mco1(source);
295 w.set_mco1pre(prescaler);
296 });
297 match source {
298 Mco1::PLL => {
299 RCC.cr().modify(|w| w.set_pllon(true));
300 while !RCC.cr().read().pllrdy() {}
301 }
302 Mco1::HSI => {
303 RCC.cr().modify(|w| w.set_hsion(true));
304 while !RCC.cr().read().hsirdy() {}
305 }
306 _ => {}
307 }
308 }
309}
310impl McoInstance for peripherals::MCO1 {}
311
312impl sealed::McoInstance for peripherals::MCO2 {
313 type Source = Mco2;
314 unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
315 RCC.cfgr().modify(|w| {
316 w.set_mco2(source);
317 w.set_mco2pre(prescaler);
318 });
319 match source {
320 Mco2::PLL => {
321 RCC.cr().modify(|w| w.set_pllon(true));
322 while !RCC.cr().read().pllrdy() {}
323 }
324 #[cfg(not(stm32f410))]
325 Mco2::PLLI2S => {
326 RCC.cr().modify(|w| w.set_plli2son(true));
327 while !RCC.cr().read().plli2srdy() {}
328 }
329 _ => {}
330 }
331 }
332}
333impl McoInstance for peripherals::MCO2 {}
334
335pub struct Mco<'d, T: McoInstance> {
336 phantom: PhantomData<&'d mut T>,
337}
338
339impl<'d, T: McoInstance> Mco<'d, T> {
340 pub fn new(
341 _peri: impl Peripheral<P = T> + 'd,
342 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
343 source: impl McoSource<Raw = T::Source>,
344 prescaler: McoClock,
345 ) -> Self {
346 into_ref!(pin);
347
348 critical_section::with(|_| unsafe {
349 T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
350 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
351 pin.set_speed(Speed::VeryHigh);
352 });
353
354 Self { phantom: PhantomData }
355 }
356}
357
358fn flash_setup(sysclk: u32) {
359 use crate::pac::flash::vals::Latency;
360
361 // Be conservative with voltage ranges
362 const FLASH_LATENCY_STEP: u32 = 30_000_000;
363
364 critical_section::with(|_| {
365 FLASH
366 .acr()
367 .modify(|w| w.set_latency(Latency::from_bits(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
368 });
369}
370
371pub(crate) unsafe fn init(config: Config) {
372 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0);
373 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
374 let sysclk_on_pll = sysclk != pllsrcclk;
375
376 let plls = setup_pll(
377 pllsrcclk,
378 config.hse.is_some(),
379 if sysclk_on_pll { Some(sysclk) } else { None },
380 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
381 config.plli2s.map(|i2s| i2s.0),
382 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
383 None,
384 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
385 config.pllsai.map(|sai| sai.0),
386 #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
387 None,
388 config.pll48,
389 );
390
391 if config.pll48 {
392 let freq = unwrap!(plls.pll48clk);
393
394 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32);
395 }
396
397 let sysclk = if sysclk_on_pll { unwrap!(plls.pllsysclk) } else { sysclk };
398
399 // AHB prescaler
400 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
401 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
402 0 => unreachable!(),
403 1 => (Hpre::DIV1, 1),
404 2 => (Hpre::DIV2, 2),
405 3..=5 => (Hpre::DIV4, 4),
406 6..=11 => (Hpre::DIV8, 8),
407 12..=39 => (Hpre::DIV16, 16),
408 40..=95 => (Hpre::DIV64, 64),
409 96..=191 => (Hpre::DIV128, 128),
410 192..=383 => (Hpre::DIV256, 256),
411 _ => (Hpre::DIV512, 512),
412 };
413
414 // Calculate real AHB clock
415 let hclk = sysclk / hpre_div;
416
417 let pclk1 = config
418 .pclk1
419 .map(|p| p.0)
420 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
421
422 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
423 0 => unreachable!(),
424 1 => (0b000, 1),
425 2 => (0b100, 2),
426 3..=5 => (0b101, 4),
427 6..=11 => (0b110, 8),
428 _ => (0b111, 16),
429 };
430 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
431
432 // Calculate real APB1 clock
433 let pclk1 = hclk / ppre1;
434 assert!(pclk1 <= max::PCLK1_MAX);
435
436 let pclk2 = config
437 .pclk2
438 .map(|p| p.0)
439 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
440 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
441 0 => unreachable!(),
442 1 => (0b000, 1),
443 2 => (0b100, 2),
444 3..=5 => (0b101, 4),
445 6..=11 => (0b110, 8),
446 _ => (0b111, 16),
447 };
448 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
449
450 // Calculate real APB2 clock
451 let pclk2 = hclk / ppre2;
452 assert!(pclk2 <= max::PCLK2_MAX);
453
454 flash_setup(sysclk);
455
456 if config.hse.is_some() {
457 RCC.cr().modify(|w| {
458 w.set_hsebyp(config.bypass_hse);
459 w.set_hseon(true);
460 });
461 while !RCC.cr().read().hserdy() {}
462 }
463
464 if plls.use_pll {
465 RCC.cr().modify(|w| w.set_pllon(true));
466
467 if hclk > max::HCLK_OVERDRIVE_FREQUENCY {
468 PWR.cr1().modify(|w| w.set_oden(true));
469 while !PWR.csr1().read().odrdy() {}
470
471 PWR.cr1().modify(|w| w.set_odswen(true));
472 while !PWR.csr1().read().odswrdy() {}
473 }
474
475 while !RCC.cr().read().pllrdy() {}
476 }
477
478 #[cfg(not(stm32f410))]
479 if plls.plli2sclk.is_some() {
480 RCC.cr().modify(|w| w.set_plli2son(true));
481
482 while !RCC.cr().read().plli2srdy() {}
483 }
484
485 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
486 if plls.pllsaiclk.is_some() {
487 RCC.cr().modify(|w| w.set_pllsaion(true));
488 while !RCC.cr().read().pllsairdy() {}
489 }
490
491 RCC.cfgr().modify(|w| {
492 w.set_ppre2(Ppre::from_bits(ppre2_bits));
493 w.set_ppre1(Ppre::from_bits(ppre1_bits));
494 w.set_hpre(hpre_bits);
495 });
496
497 // Wait for the new prescalers to kick in
498 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
499 cortex_m::asm::delay(16);
500
501 RCC.cfgr().modify(|w| {
502 w.set_sw(if sysclk_on_pll {
503 Sw::PLL
504 } else if config.hse.is_some() {
505 Sw::HSE
506 } else {
507 Sw::HSI
508 })
509 });
510
511 BackupDomain::configure_ls(
512 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
513 config.lsi,
514 config.lse.map(|_| Default::default()),
515 );
516
517 let rtc = match config.rtc {
518 Some(RtcClockSource::LSI) => Some(LSI_FREQ),
519 Some(RtcClockSource::LSE) => Some(config.lse.unwrap()),
520 _ => None,
521 };
522
523 set_freqs(Clocks {
524 sys: Hertz(sysclk),
525 apb1: Hertz(pclk1),
526 apb2: Hertz(pclk2),
527
528 apb1_tim: Hertz(pclk1 * timer_mul1),
529 apb2_tim: Hertz(pclk2 * timer_mul2),
530
531 ahb1: Hertz(hclk),
532 ahb2: Hertz(hclk),
533 ahb3: Hertz(hclk),
534
535 pll48: plls.pll48clk.map(Hertz),
536
537 #[cfg(not(stm32f410))]
538 plli2s: plls.plli2sclk.map(Hertz),
539
540 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
541 pllsai: plls.pllsaiclk.map(Hertz),
542
543 rtc: rtc,
544 rtc_hse: None,
545 });
546}
547
548struct PllResults {
549 use_pll: bool,
550 pllsysclk: Option<u32>,
551 pll48clk: Option<u32>,
552 #[allow(dead_code)]
553 plli2sclk: Option<u32>,
554 #[allow(dead_code)]
555 pllsaiclk: Option<u32>,
556}
557
558mod max {
559 #[cfg(stm32f401)]
560 pub(crate) const SYSCLK_MAX: u32 = 84_000_000;
561 #[cfg(any(stm32f405, stm32f407, stm32f415, stm32f417,))]
562 pub(crate) const SYSCLK_MAX: u32 = 168_000_000;
563 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
564 pub(crate) const SYSCLK_MAX: u32 = 100_000_000;
565 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479,))]
566 pub(crate) const SYSCLK_MAX: u32 = 180_000_000;
567
568 pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 168_000_000;
569
570 pub(crate) const PCLK1_MAX: u32 = PCLK2_MAX / 2;
571
572 #[cfg(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
573 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX;
574 #[cfg(not(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,)))]
575 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
576
577 pub(crate) const PLL_48_CLK: u32 = 48_000_000;
578 pub(crate) const PLL_48_TOLERANCE: u32 = 120_000;
579}
diff --git a/embassy-stm32/src/rcc/f4f7.rs b/embassy-stm32/src/rcc/f4f7.rs
new file mode 100644
index 000000000..3f9a2be67
--- /dev/null
+++ b/embassy-stm32/src/rcc/f4f7.rs
@@ -0,0 +1,385 @@
1pub use crate::pac::rcc::vals::{
2 Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp, Pllq, Pllr, Pllsrc as PllSource,
3 Ppre as APBPrescaler, Sw as Sysclk,
4};
5use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz;
8
9// TODO: on some F4s, PLLM is shared between all PLLs. Enforce that.
10// TODO: on some F4s, add support for plli2s_src
11//
12// plli2s plli2s_m plli2s_src pllsai pllsai_m
13// f401 y shared
14// f410
15// f411 y individual
16// f412 y individual y
17// f4[12]3 y individual y
18// f446 y individual y individual
19// f4[67]9 y shared y shared
20// f4[23][79] y shared y shared
21// f4[01][57] y shared
22
23/// HSI speed
24pub const HSI_FREQ: Hertz = Hertz(16_000_000);
25
26#[derive(Clone, Copy, Eq, PartialEq)]
27pub enum HseMode {
28 /// crystal/ceramic oscillator (HSEBYP=0)
29 Oscillator,
30 /// external analog clock (low swing) (HSEBYP=1)
31 Bypass,
32}
33
34#[derive(Clone, Copy, Eq, PartialEq)]
35pub struct Hse {
36 /// HSE frequency.
37 pub freq: Hertz,
38 /// HSE mode.
39 pub mode: HseMode,
40}
41
42#[derive(Clone, Copy)]
43pub struct Pll {
44 /// PLL pre-divider (DIVM).
45 pub prediv: PllPreDiv,
46
47 /// PLL multiplication factor.
48 pub mul: PllMul,
49
50 /// PLL P division factor. If None, PLL P output is disabled.
51 pub divp: Option<Pllp>,
52 /// PLL Q division factor. If None, PLL Q output is disabled.
53 pub divq: Option<Pllq>,
54 /// PLL R division factor. If None, PLL R output is disabled.
55 pub divr: Option<Pllr>,
56}
57
58/// Configuration of the core clocks
59#[non_exhaustive]
60pub struct Config {
61 pub hsi: bool,
62 pub hse: Option<Hse>,
63 pub sys: Sysclk,
64
65 pub pll_src: PllSource,
66
67 pub pll: Option<Pll>,
68 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
69 pub plli2s: Option<Pll>,
70 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
71 pub pllsai: Option<Pll>,
72
73 pub ahb_pre: AHBPrescaler,
74 pub apb1_pre: APBPrescaler,
75 pub apb2_pre: APBPrescaler,
76
77 pub ls: super::LsConfig,
78}
79
80impl Default for Config {
81 fn default() -> Self {
82 Self {
83 hsi: true,
84 hse: None,
85 sys: Sysclk::HSI,
86 pll_src: PllSource::HSI,
87 pll: None,
88 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
89 plli2s: None,
90 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
91 pllsai: None,
92
93 ahb_pre: AHBPrescaler::DIV1,
94 apb1_pre: APBPrescaler::DIV1,
95 apb2_pre: APBPrescaler::DIV1,
96
97 ls: Default::default(),
98 }
99 }
100}
101
102pub(crate) unsafe fn init(config: Config) {
103 // always enable overdrive for now. Make it configurable in the future.
104 #[cfg(not(any(
105 stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f405, stm32f407, stm32f415, stm32f417
106 )))]
107 {
108 use crate::pac::PWR;
109 PWR.cr1().modify(|w| w.set_oden(true));
110 while !PWR.csr1().read().odrdy() {}
111
112 PWR.cr1().modify(|w| w.set_odswen(true));
113 while !PWR.csr1().read().odswrdy() {}
114 }
115
116 // Configure HSI
117 let hsi = match config.hsi {
118 false => {
119 RCC.cr().modify(|w| w.set_hsion(false));
120 None
121 }
122 true => {
123 RCC.cr().modify(|w| w.set_hsion(true));
124 while !RCC.cr().read().hsirdy() {}
125 Some(HSI_FREQ)
126 }
127 };
128
129 // Configure HSE
130 let hse = match config.hse {
131 None => {
132 RCC.cr().modify(|w| w.set_hseon(false));
133 None
134 }
135 Some(hse) => {
136 match hse.mode {
137 HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
138 HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
139 }
140
141 RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
142 RCC.cr().modify(|w| w.set_hseon(true));
143 while !RCC.cr().read().hserdy() {}
144 Some(hse.freq)
145 }
146 };
147
148 // Configure PLLs.
149 let pll_input = PllInput {
150 hse,
151 hsi,
152 source: config.pll_src,
153 };
154 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
155 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
156 let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
157 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
158 let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
159
160 // Configure sysclk
161 let sys = match config.sys {
162 Sysclk::HSI => unwrap!(hsi),
163 Sysclk::HSE => unwrap!(hse),
164 Sysclk::PLL1_P => unwrap!(pll.p),
165 _ => unreachable!(),
166 };
167
168 let hclk = sys / config.ahb_pre;
169 let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre);
170 let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre);
171
172 assert!(max::SYSCLK.contains(&sys));
173 assert!(max::HCLK.contains(&hclk));
174 assert!(max::PCLK1.contains(&pclk1));
175 assert!(max::PCLK2.contains(&pclk2));
176
177 let rtc = config.ls.init();
178
179 flash_setup(hclk);
180
181 RCC.cfgr().modify(|w| {
182 w.set_sw(config.sys);
183 w.set_hpre(config.ahb_pre);
184 w.set_ppre1(config.apb1_pre);
185 w.set_ppre2(config.apb2_pre);
186 });
187 while RCC.cfgr().read().sws() != config.sys {}
188
189 set_freqs(Clocks {
190 sys,
191 hclk1: hclk,
192 hclk2: hclk,
193 hclk3: hclk,
194 pclk1,
195 pclk2,
196 pclk1_tim,
197 pclk2_tim,
198 rtc,
199 pll1_q: pll.q,
200 #[cfg(all(rcc_f4, not(stm32f410)))]
201 plli2s1_q: _plli2s.q,
202 #[cfg(all(rcc_f4, not(stm32f410)))]
203 plli2s1_r: _plli2s.r,
204
205 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
206 pllsai1_q: _pllsai.q,
207 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
208 pllsai1_r: _pllsai.r,
209 });
210}
211
212struct PllInput {
213 source: PllSource,
214 hsi: Option<Hertz>,
215 hse: Option<Hertz>,
216}
217
218#[derive(Default)]
219#[allow(unused)]
220struct PllOutput {
221 p: Option<Hertz>,
222 q: Option<Hertz>,
223 r: Option<Hertz>,
224}
225
226#[derive(PartialEq, Eq, Clone, Copy)]
227enum PllInstance {
228 Pll,
229 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
230 Plli2s,
231 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
232 Pllsai,
233}
234
235fn pll_enable(instance: PllInstance, enabled: bool) {
236 match instance {
237 PllInstance::Pll => {
238 RCC.cr().modify(|w| w.set_pllon(enabled));
239 while RCC.cr().read().pllrdy() != enabled {}
240 }
241 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
242 PllInstance::Plli2s => {
243 RCC.cr().modify(|w| w.set_plli2son(enabled));
244 while RCC.cr().read().plli2srdy() != enabled {}
245 }
246 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
247 PllInstance::Pllsai => {
248 RCC.cr().modify(|w| w.set_pllsaion(enabled));
249 while RCC.cr().read().pllsairdy() != enabled {}
250 }
251 }
252}
253
254fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
255 // Disable PLL
256 pll_enable(instance, false);
257
258 let Some(pll) = config else { return PllOutput::default() };
259
260 let pll_src = match input.source {
261 PllSource::HSE => input.hse,
262 PllSource::HSI => input.hsi,
263 };
264
265 let pll_src = pll_src.unwrap();
266
267 let in_freq = pll_src / pll.prediv;
268 assert!(max::PLL_IN.contains(&in_freq));
269 let vco_freq = in_freq * pll.mul;
270 assert!(max::PLL_VCO.contains(&vco_freq));
271
272 let p = pll.divp.map(|div| vco_freq / div);
273 let q = pll.divq.map(|div| vco_freq / div);
274 let r = pll.divr.map(|div| vco_freq / div);
275
276 macro_rules! write_fields {
277 ($w:ident) => {
278 $w.set_plln(pll.mul);
279 if let Some(divp) = pll.divp {
280 $w.set_pllp(divp);
281 }
282 if let Some(divq) = pll.divq {
283 $w.set_pllq(divq);
284 }
285 if let Some(divr) = pll.divr {
286 $w.set_pllr(divr);
287 }
288 };
289 }
290
291 match instance {
292 PllInstance::Pll => RCC.pllcfgr().write(|w| {
293 w.set_pllm(pll.prediv);
294 w.set_pllsrc(input.source);
295 write_fields!(w);
296 }),
297 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
298 PllInstance::Plli2s => RCC.plli2scfgr().write(|w| {
299 write_fields!(w);
300 }),
301 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
302 PllInstance::Pllsai => RCC.pllsaicfgr().write(|w| {
303 write_fields!(w);
304 }),
305 }
306
307 // Enable PLL
308 pll_enable(instance, true);
309
310 PllOutput { p, q, r }
311}
312
313fn flash_setup(clk: Hertz) {
314 use crate::pac::flash::vals::Latency;
315
316 // Be conservative with voltage ranges
317 const FLASH_LATENCY_STEP: u32 = 30_000_000;
318
319 let latency = (clk.0 - 1) / FLASH_LATENCY_STEP;
320 debug!("flash: latency={}", latency);
321
322 let latency = Latency::from_bits(latency as u8);
323 FLASH.acr().write(|w| {
324 w.set_latency(latency);
325 });
326 while FLASH.acr().read().latency() != latency {}
327}
328
329fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
330where
331 Hertz: core::ops::Div<D, Output = Hertz>,
332{
333 let pclk = hclk / ppre;
334 let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
335 (pclk, pclk_tim)
336}
337
338#[cfg(stm32f7)]
339mod max {
340 use core::ops::RangeInclusive;
341
342 use crate::time::Hertz;
343
344 pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(26_000_000);
345 pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(50_000_000);
346
347 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000);
348 pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000);
349 pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000 / 4);
350 pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000 / 2);
351
352 pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(2_100_000);
353 pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(100_000_000)..=Hertz(432_000_000);
354}
355
356#[cfg(stm32f4)]
357mod max {
358 use core::ops::RangeInclusive;
359
360 use crate::time::Hertz;
361
362 pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(26_000_000);
363 pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(50_000_000);
364
365 #[cfg(stm32f401)]
366 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(84_000_000);
367 #[cfg(any(stm32f405, stm32f407, stm32f415, stm32f417,))]
368 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(168_000_000);
369 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
370 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(100_000_000);
371 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479,))]
372 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(180_000_000);
373
374 pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(SYSCLK.end().0);
375
376 pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(PCLK2.end().0 / 2);
377
378 #[cfg(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
379 pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(HCLK.end().0);
380 #[cfg(not(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,)))]
381 pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(HCLK.end().0 / 2);
382
383 pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(2_100_000);
384 pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(100_000_000)..=Hertz(432_000_000);
385}
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs
deleted file mode 100644
index f32559e26..000000000
--- a/embassy-stm32/src/rcc/f7.rs
+++ /dev/null
@@ -1,323 +0,0 @@
1use crate::pac::pwr::vals::Vos;
2use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
3use crate::pac::{FLASH, PWR, RCC};
4use crate::rcc::bd::{BackupDomain, RtcClockSource};
5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz;
7
8/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(16_000_000);
10
11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(32_000);
13
14/// Clocks configuration
15#[non_exhaustive]
16#[derive(Default)]
17pub struct Config {
18 pub hse: Option<Hertz>,
19 pub bypass_hse: bool,
20 pub hclk: Option<Hertz>,
21 pub sys_ck: Option<Hertz>,
22 pub pclk1: Option<Hertz>,
23 pub pclk2: Option<Hertz>,
24
25 pub pll48: bool,
26 pub rtc: Option<RtcClockSource>,
27 pub lsi: bool,
28 pub lse: Option<Hertz>,
29}
30
31fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults {
32 use crate::pac::rcc::vals::{Pllp, Pllsrc};
33
34 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
35 if pllsysclk.is_none() && !pll48clk {
36 RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)));
37
38 return PllResults {
39 use_pll: false,
40 pllsysclk: None,
41 pll48clk: None,
42 };
43 }
44 // Input divisor from PLL source clock, must result to frequency in
45 // the range from 1 to 2 MHz
46 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
47 let pllm_max = pllsrcclk / 1_000_000;
48
49 // Sysclk output divisor must be one of 2, 4, 6 or 8
50 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
51
52 let target_freq = if pll48clk { 48_000_000 } else { sysclk * sysclk_div };
53
54 // Find the lowest pllm value that minimize the difference between
55 // target frequency and the real vco_out frequency.
56 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| {
57 let vco_in = pllsrcclk / pllm;
58 let plln = target_freq / vco_in;
59 target_freq - vco_in * plln
60 }));
61
62 let vco_in = pllsrcclk / pllm;
63 assert!((1_000_000..=2_000_000).contains(&vco_in));
64
65 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
66 // and <= 432MHz, min 50, max 432
67 let plln = if pll48clk {
68 // try the different valid pllq according to the valid
69 // main scaller values, and take the best
70 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
71 let plln = 48_000_000 * pllq / vco_in;
72 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
73 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
74 (pll48_diff, sysclk_diff)
75 }));
76 48_000_000 * pllq / vco_in
77 } else {
78 sysclk * sysclk_div / vco_in
79 };
80
81 let pllp = (sysclk_div / 2) - 1;
82
83 let pllq = (vco_in * plln + 47_999_999) / 48_000_000;
84 let real_pll48clk = vco_in * plln / pllq;
85
86 RCC.pllcfgr().modify(|w| {
87 w.set_pllm(pllm as u8);
88 w.set_plln(plln as u16);
89 w.set_pllp(Pllp::from_bits(pllp as u8));
90 w.set_pllq(pllq as u8);
91 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
92 });
93
94 let real_pllsysclk = vco_in * plln / sysclk_div;
95
96 PllResults {
97 use_pll: true,
98 pllsysclk: Some(real_pllsysclk),
99 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
100 }
101}
102
103fn flash_setup(sysclk: u32) {
104 use crate::pac::flash::vals::Latency;
105
106 // Be conservative with voltage ranges
107 const FLASH_LATENCY_STEP: u32 = 30_000_000;
108
109 critical_section::with(|_| {
110 FLASH
111 .acr()
112 .modify(|w| w.set_latency(Latency::from_bits(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
113 });
114}
115
116pub(crate) unsafe fn init(config: Config) {
117 if let Some(hse) = config.hse {
118 if config.bypass_hse {
119 assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0));
120 } else {
121 assert!((max::HSE_OSC_MIN..=max::HSE_OSC_MAX).contains(&hse.0));
122 }
123 }
124
125 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0);
126 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
127 let sysclk_on_pll = sysclk != pllsrcclk;
128
129 assert!((max::SYSCLK_MIN..=max::SYSCLK_MAX).contains(&sysclk));
130
131 let plls = setup_pll(
132 pllsrcclk,
133 config.hse.is_some(),
134 if sysclk_on_pll { Some(sysclk) } else { None },
135 config.pll48,
136 );
137
138 if config.pll48 {
139 let freq = unwrap!(plls.pll48clk);
140
141 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32);
142 }
143
144 let sysclk = if sysclk_on_pll { unwrap!(plls.pllsysclk) } else { sysclk };
145
146 // AHB prescaler
147 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
148 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
149 0 => unreachable!(),
150 1 => (Hpre::DIV1, 1),
151 2 => (Hpre::DIV2, 2),
152 3..=5 => (Hpre::DIV4, 4),
153 6..=11 => (Hpre::DIV8, 8),
154 12..=39 => (Hpre::DIV16, 16),
155 40..=95 => (Hpre::DIV64, 64),
156 96..=191 => (Hpre::DIV128, 128),
157 192..=383 => (Hpre::DIV256, 256),
158 _ => (Hpre::DIV512, 512),
159 };
160
161 // Calculate real AHB clock
162 let hclk = sysclk / hpre_div;
163
164 assert!(hclk <= max::HCLK_MAX);
165
166 let pclk1 = config
167 .pclk1
168 .map(|p| p.0)
169 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
170
171 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
172 0 => unreachable!(),
173 1 => (0b000, 1),
174 2 => (0b100, 2),
175 3..=5 => (0b101, 4),
176 6..=11 => (0b110, 8),
177 _ => (0b111, 16),
178 };
179 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
180
181 // Calculate real APB1 clock
182 let pclk1 = hclk / ppre1;
183 assert!((max::PCLK1_MIN..=max::PCLK1_MAX).contains(&pclk1));
184
185 let pclk2 = config
186 .pclk2
187 .map(|p| p.0)
188 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
189 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
190 0 => unreachable!(),
191 1 => (0b000, 1),
192 2 => (0b100, 2),
193 3..=5 => (0b101, 4),
194 6..=11 => (0b110, 8),
195 _ => (0b111, 16),
196 };
197 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
198
199 // Calculate real APB2 clock
200 let pclk2 = hclk / ppre2;
201 assert!((max::PCLK2_MIN..=max::PCLK2_MAX).contains(&pclk2));
202
203 flash_setup(sysclk);
204
205 if config.hse.is_some() {
206 RCC.cr().modify(|w| {
207 w.set_hsebyp(config.bypass_hse);
208 w.set_hseon(true);
209 });
210 while !RCC.cr().read().hserdy() {}
211 }
212
213 if plls.use_pll {
214 RCC.cr().modify(|w| w.set_pllon(false));
215
216 // setup VOSScale
217 let vos_scale = if sysclk <= 144_000_000 {
218 3
219 } else if sysclk <= 168_000_000 {
220 2
221 } else {
222 1
223 };
224 PWR.cr1().modify(|w| {
225 w.set_vos(match vos_scale {
226 3 => Vos::SCALE3,
227 2 => Vos::SCALE2,
228 1 => Vos::SCALE1,
229 _ => panic!("Invalid VOS Scale."),
230 })
231 });
232
233 RCC.cr().modify(|w| w.set_pllon(true));
234
235 if hclk > max::HCLK_OVERDRIVE_FREQUENCY {
236 PWR.cr1().modify(|w| w.set_oden(true));
237 while !PWR.csr1().read().odrdy() {}
238
239 PWR.cr1().modify(|w| w.set_odswen(true));
240 while !PWR.csr1().read().odswrdy() {}
241 }
242
243 while !RCC.cr().read().pllrdy() {}
244 }
245
246 RCC.cfgr().modify(|w| {
247 w.set_ppre2(Ppre::from_bits(ppre2_bits));
248 w.set_ppre1(Ppre::from_bits(ppre1_bits));
249 w.set_hpre(hpre_bits);
250 });
251
252 // Wait for the new prescalers to kick in
253 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
254 cortex_m::asm::delay(16);
255
256 RCC.cfgr().modify(|w| {
257 w.set_sw(if sysclk_on_pll {
258 Sw::PLL
259 } else if config.hse.is_some() {
260 Sw::HSE
261 } else {
262 Sw::HSI
263 })
264 });
265
266 BackupDomain::configure_ls(
267 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
268 config.lsi,
269 config.lse.map(|_| Default::default()),
270 );
271
272 let rtc = match config.rtc {
273 Some(RtcClockSource::LSI) => Some(LSI_FREQ),
274 Some(RtcClockSource::LSE) => Some(config.lse.unwrap()),
275 _ => None,
276 };
277
278 set_freqs(Clocks {
279 sys: Hertz(sysclk),
280 apb1: Hertz(pclk1),
281 apb2: Hertz(pclk2),
282
283 apb1_tim: Hertz(pclk1 * timer_mul1),
284 apb2_tim: Hertz(pclk2 * timer_mul2),
285
286 ahb1: Hertz(hclk),
287 ahb2: Hertz(hclk),
288 ahb3: Hertz(hclk),
289
290 pll48: plls.pll48clk.map(Hertz),
291
292 rtc,
293 });
294}
295
296struct PllResults {
297 use_pll: bool,
298 pllsysclk: Option<u32>,
299 pll48clk: Option<u32>,
300}
301
302mod max {
303 pub(crate) const HSE_OSC_MIN: u32 = 4_000_000;
304 pub(crate) const HSE_OSC_MAX: u32 = 26_000_000;
305 pub(crate) const HSE_BYPASS_MIN: u32 = 1_000_000;
306 pub(crate) const HSE_BYPASS_MAX: u32 = 50_000_000;
307
308 pub(crate) const HCLK_MAX: u32 = 216_000_000;
309 pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 180_000_000;
310
311 pub(crate) const SYSCLK_MIN: u32 = 12_500_000;
312 pub(crate) const SYSCLK_MAX: u32 = 216_000_000;
313
314 pub(crate) const PCLK1_MIN: u32 = SYSCLK_MIN;
315 pub(crate) const PCLK1_MAX: u32 = SYSCLK_MAX / 4;
316
317 pub(crate) const PCLK2_MIN: u32 = SYSCLK_MIN;
318 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
319
320 // USB specification allows +-0.25%
321 pub(crate) const PLL_48_CLK: u32 = 48_000_000;
322 pub(crate) const PLL_48_TOLERANCE: u32 = 120_000;
323}
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index 7f0a2c7fb..85ebd32e1 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,6 +1,8 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
3use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; 2use crate::pac::rcc::vals::{self, Sw};
3pub use crate::pac::rcc::vals::{
4 Hpre as AHBPrescaler, Hsidiv as HSI16Prescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler,
5};
4use crate::pac::{FLASH, PWR, RCC}; 6use crate::pac::{FLASH, PWR, RCC};
5use crate::rcc::{set_freqs, Clocks}; 7use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 8use crate::time::Hertz;
@@ -8,9 +10,6 @@ use crate::time::Hertz;
8/// HSI speed 10/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(16_000_000); 11pub const HSI_FREQ: Hertz = Hertz(16_000_000);
10 12
11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(32_000);
13
14/// System clock mux source 13/// System clock mux source
15#[derive(Clone, Copy)] 14#[derive(Clone, Copy)]
16pub enum ClockSrc { 15pub enum ClockSrc {
@@ -20,33 +19,6 @@ pub enum ClockSrc {
20 LSI, 19 LSI,
21} 20}
22 21
23#[derive(Clone, Copy)]
24pub enum HSI16Prescaler {
25 NotDivided,
26 Div2,
27 Div4,
28 Div8,
29 Div16,
30 Div32,
31 Div64,
32 Div128,
33}
34
35impl Into<Hsidiv> for HSI16Prescaler {
36 fn into(self) -> Hsidiv {
37 match self {
38 HSI16Prescaler::NotDivided => Hsidiv::DIV1,
39 HSI16Prescaler::Div2 => Hsidiv::DIV2,
40 HSI16Prescaler::Div4 => Hsidiv::DIV4,
41 HSI16Prescaler::Div8 => Hsidiv::DIV8,
42 HSI16Prescaler::Div16 => Hsidiv::DIV16,
43 HSI16Prescaler::Div32 => Hsidiv::DIV32,
44 HSI16Prescaler::Div64 => Hsidiv::DIV64,
45 HSI16Prescaler::Div128 => Hsidiv::DIV128,
46 }
47 }
48}
49
50/// The PLL configuration. 22/// The PLL configuration.
51/// 23///
52/// * `VCOCLK = source / m * n` 24/// * `VCOCLK = source / m * n`
@@ -60,15 +32,15 @@ pub struct PllConfig {
60 /// The initial divisor of that clock signal 32 /// The initial divisor of that clock signal
61 pub m: Pllm, 33 pub m: Pllm,
62 /// The PLL VCO multiplier, which must be in the range `8..=86`. 34 /// The PLL VCO multiplier, which must be in the range `8..=86`.
63 pub n: u8, 35 pub n: Plln,
64 /// The final divisor for `PLLRCLK` output which drives the system clock 36 /// The final divisor for `PLLRCLK` output which drives the system clock
65 pub r: Pllr, 37 pub r: Pllr,
66 38
67 /// The divisor for the `PLLQCLK` output, if desired 39 /// The divisor for the `PLLQCLK` output, if desired
68 pub q: Option<Pllr>, 40 pub q: Option<Pllq>,
69 41
70 /// The divisor for the `PLLPCLK` output, if desired 42 /// The divisor for the `PLLPCLK` output, if desired
71 pub p: Option<Pllr>, 43 pub p: Option<Pllp>,
72} 44}
73 45
74impl Default for PllConfig { 46impl Default for PllConfig {
@@ -77,9 +49,9 @@ impl Default for PllConfig {
77 // HSI16 / 1 * 8 / 2 = 64 MHz 49 // HSI16 / 1 * 8 / 2 = 64 MHz
78 PllConfig { 50 PllConfig {
79 source: PllSrc::HSI16, 51 source: PllSrc::HSI16,
80 m: Pllm::Div1, 52 m: Pllm::DIV1,
81 n: 8, 53 n: Plln::MUL8,
82 r: Pllr::Div2, 54 r: Pllr::DIV2,
83 q: None, 55 q: None,
84 p: None, 56 p: None,
85 } 57 }
@@ -92,131 +64,51 @@ pub enum PllSrc {
92 HSE(Hertz), 64 HSE(Hertz),
93} 65}
94 66
95#[derive(Clone, Copy)]
96pub enum Pllm {
97 Div1,
98 Div2,
99 Div3,
100 Div4,
101 Div5,
102 Div6,
103 Div7,
104 Div8,
105}
106
107impl From<Pllm> for u8 {
108 fn from(v: Pllm) -> Self {
109 match v {
110 Pllm::Div1 => 0b000,
111 Pllm::Div2 => 0b001,
112 Pllm::Div3 => 0b010,
113 Pllm::Div4 => 0b011,
114 Pllm::Div5 => 0b100,
115 Pllm::Div6 => 0b101,
116 Pllm::Div7 => 0b110,
117 Pllm::Div8 => 0b111,
118 }
119 }
120}
121
122impl From<Pllm> for u32 {
123 fn from(v: Pllm) -> Self {
124 match v {
125 Pllm::Div1 => 1,
126 Pllm::Div2 => 2,
127 Pllm::Div3 => 3,
128 Pllm::Div4 => 4,
129 Pllm::Div5 => 5,
130 Pllm::Div6 => 6,
131 Pllm::Div7 => 7,
132 Pllm::Div8 => 8,
133 }
134 }
135}
136
137#[derive(Clone, Copy)]
138pub enum Pllr {
139 Div2,
140 Div3,
141 Div4,
142 Div5,
143 Div6,
144 Div7,
145 Div8,
146}
147
148impl From<Pllr> for u8 {
149 fn from(v: Pllr) -> Self {
150 match v {
151 Pllr::Div2 => 0b000,
152 Pllr::Div3 => 0b001,
153 Pllr::Div4 => 0b010,
154 Pllr::Div5 => 0b011,
155 Pllr::Div6 => 0b101,
156 Pllr::Div7 => 0b110,
157 Pllr::Div8 => 0b111,
158 }
159 }
160}
161
162impl From<Pllr> for u32 {
163 fn from(v: Pllr) -> Self {
164 match v {
165 Pllr::Div2 => 2,
166 Pllr::Div3 => 3,
167 Pllr::Div4 => 4,
168 Pllr::Div5 => 5,
169 Pllr::Div6 => 6,
170 Pllr::Div7 => 7,
171 Pllr::Div8 => 8,
172 }
173 }
174}
175
176/// Clocks configutation 67/// Clocks configutation
177pub struct Config { 68pub struct Config {
178 pub mux: ClockSrc, 69 pub mux: ClockSrc,
179 pub ahb_pre: AHBPrescaler, 70 pub ahb_pre: AHBPrescaler,
180 pub apb_pre: APBPrescaler, 71 pub apb_pre: APBPrescaler,
181 pub low_power_run: bool, 72 pub low_power_run: bool,
73 pub ls: super::LsConfig,
182} 74}
183 75
184impl Default for Config { 76impl Default for Config {
185 #[inline] 77 #[inline]
186 fn default() -> Config { 78 fn default() -> Config {
187 Config { 79 Config {
188 mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided), 80 mux: ClockSrc::HSI16(HSI16Prescaler::DIV1),
189 ahb_pre: AHBPrescaler::DIV1, 81 ahb_pre: AHBPrescaler::DIV1,
190 apb_pre: APBPrescaler::DIV1, 82 apb_pre: APBPrescaler::DIV1,
191 low_power_run: false, 83 low_power_run: false,
84 ls: Default::default(),
192 } 85 }
193 } 86 }
194} 87}
195 88
196impl PllConfig { 89impl PllConfig {
197 pub(crate) fn init(self) -> u32 { 90 pub(crate) fn init(self) -> Hertz {
198 assert!(self.n >= 8 && self.n <= 86);
199 let (src, input_freq) = match self.source { 91 let (src, input_freq) = match self.source {
200 PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), 92 PllSrc::HSI16 => (vals::Pllsrc::HSI, HSI_FREQ),
201 PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq.0), 93 PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq),
202 }; 94 };
203 95
204 let m_freq = input_freq / u32::from(self.m); 96 let m_freq = input_freq / self.m;
205 // RM0454 § 5.4.4: 97 // RM0454 § 5.4.4:
206 // > Caution: The software must set these bits so that the PLL input frequency after the 98 // > Caution: The software must set these bits so that the PLL input frequency after the
207 // > /M divider is between 2.66 and 16 MHz. 99 // > /M divider is between 2.66 and 16 MHz.
208 debug_assert!(m_freq >= 2_660_000 && m_freq <= 16_000_000); 100 debug_assert!(m_freq.0 >= 2_660_000 && m_freq.0 <= 16_000_000);
209 101
210 let n_freq = m_freq * self.n as u32; 102 let n_freq = m_freq * self.n as u32;
211 // RM0454 § 5.4.4: 103 // RM0454 § 5.4.4:
212 // > Caution: The software must set these bits so that the VCO output frequency is between 104 // > Caution: The software must set these bits so that the VCO output frequency is between
213 // > 64 and 344 MHz. 105 // > 64 and 344 MHz.
214 debug_assert!(n_freq >= 64_000_000 && n_freq <= 344_000_000); 106 debug_assert!(n_freq.0 >= 64_000_000 && n_freq.0 <= 344_000_000);
215 107
216 let r_freq = n_freq / u32::from(self.r); 108 let r_freq = n_freq / self.r;
217 // RM0454 § 5.4.4: 109 // RM0454 § 5.4.4:
218 // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock. 110 // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock.
219 debug_assert!(r_freq <= 64_000_000); 111 debug_assert!(r_freq.0 <= 64_000_000);
220 112
221 // RM0454 § 5.2.3: 113 // RM0454 § 5.2.3:
222 // > To modify the PLL configuration, proceed as follows: 114 // > To modify the PLL configuration, proceed as follows:
@@ -239,25 +131,16 @@ impl PllConfig {
239 } 131 }
240 } 132 }
241 133
242 // Configure PLLSYSCFGR 134 // Configure PLLCFGR
243 RCC.pllsyscfgr().modify(|w| { 135 RCC.pllcfgr().modify(|w| {
244 w.set_pllr(u8::from(self.r)); 136 w.set_pllr(self.r);
245 w.set_pllren(false); 137 w.set_pllren(false);
246 138 w.set_pllq(self.q.unwrap_or(Pllq::DIV2));
247 if let Some(q) = self.q {
248 w.set_pllq(u8::from(q));
249 }
250 w.set_pllqen(false); 139 w.set_pllqen(false);
251 140 w.set_pllp(self.p.unwrap_or(Pllp::DIV2));
252 if let Some(p) = self.p {
253 w.set_pllp(u8::from(p));
254 }
255 w.set_pllpen(false); 141 w.set_pllpen(false);
256
257 w.set_plln(self.n); 142 w.set_plln(self.n);
258 143 w.set_pllm(self.m);
259 w.set_pllm(self.m as u8);
260
261 w.set_pllsrc(src) 144 w.set_pllsrc(src)
262 }); 145 });
263 146
@@ -269,7 +152,7 @@ impl PllConfig {
269 152
270 // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL 153 // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL
271 // > configuration register (RCC_PLLCFGR). 154 // > configuration register (RCC_PLLCFGR).
272 RCC.pllsyscfgr().modify(|w| { 155 RCC.pllcfgr().modify(|w| {
273 // We'll use R for system clock, so enable that unconditionally 156 // We'll use R for system clock, so enable that unconditionally
274 w.set_pllren(true); 157 w.set_pllren(true);
275 158
@@ -286,39 +169,38 @@ pub(crate) unsafe fn init(config: Config) {
286 let (sys_clk, sw) = match config.mux { 169 let (sys_clk, sw) = match config.mux {
287 ClockSrc::HSI16(div) => { 170 ClockSrc::HSI16(div) => {
288 // Enable HSI16 171 // Enable HSI16
289 let div: Hsidiv = div.into();
290 RCC.cr().write(|w| { 172 RCC.cr().write(|w| {
291 w.set_hsidiv(div); 173 w.set_hsidiv(div);
292 w.set_hsion(true) 174 w.set_hsion(true)
293 }); 175 });
294 while !RCC.cr().read().hsirdy() {} 176 while !RCC.cr().read().hsirdy() {}
295 177
296 (HSI_FREQ.0 >> div.to_bits(), Sw::HSI) 178 (HSI_FREQ / div, Sw::HSI)
297 } 179 }
298 ClockSrc::HSE(freq) => { 180 ClockSrc::HSE(freq) => {
299 // Enable HSE 181 // Enable HSE
300 RCC.cr().write(|w| w.set_hseon(true)); 182 RCC.cr().write(|w| w.set_hseon(true));
301 while !RCC.cr().read().hserdy() {} 183 while !RCC.cr().read().hserdy() {}
302 184
303 (freq.0, Sw::HSE) 185 (freq, Sw::HSE)
304 } 186 }
305 ClockSrc::PLL(pll) => { 187 ClockSrc::PLL(pll) => {
306 let freq = pll.init(); 188 let freq = pll.init();
307 (freq, Sw::PLLRCLK) 189 (freq, Sw::PLL1_R)
308 } 190 }
309 ClockSrc::LSI => { 191 ClockSrc::LSI => {
310 // Enable LSI 192 // Enable LSI
311 RCC.csr().write(|w| w.set_lsion(true)); 193 RCC.csr().write(|w| w.set_lsion(true));
312 while !RCC.csr().read().lsirdy() {} 194 while !RCC.csr().read().lsirdy() {}
313 (LSI_FREQ.0, Sw::LSI) 195 (super::LSI_FREQ, Sw::LSI)
314 } 196 }
315 }; 197 };
316 198
317 // Determine the flash latency implied by the target clock speed 199 // Determine the flash latency implied by the target clock speed
318 // RM0454 § 3.3.4: 200 // RM0454 § 3.3.4:
319 let target_flash_latency = if sys_clk <= 24_000_000 { 201 let target_flash_latency = if sys_clk.0 <= 24_000_000 {
320 Latency::WS0 202 Latency::WS0
321 } else if sys_clk <= 48_000_000 { 203 } else if sys_clk.0 <= 48_000_000 {
322 Latency::WS1 204 Latency::WS1
323 } else { 205 } else {
324 Latency::WS2 206 Latency::WS2
@@ -353,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) {
353 } 235 }
354 236
355 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once 237 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once
356 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); 238 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
357 RCC.cfgr().modify(|w| { 239 RCC.cfgr().modify(|w| {
358 w.set_sw(sw); 240 w.set_sw(sw);
359 w.set_hpre(hpre); 241 w.set_hpre(hpre);
@@ -374,27 +256,28 @@ pub(crate) unsafe fn init(config: Config) {
374 FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); 256 FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
375 } 257 }
376 258
377 let ahb_freq = Hertz(sys_clk) / config.ahb_pre; 259 let ahb_freq = sys_clk / config.ahb_pre;
378 260
379 let (apb_freq, apb_tim_freq) = match config.apb_pre { 261 let (apb_freq, apb_tim_freq) = match config.apb_pre {
380 APBPrescaler::DIV1 => (ahb_freq.0, ahb_freq.0), 262 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
381 pre => { 263 pre => {
382 let pre: Ppre = pre.into(); 264 let freq = ahb_freq / pre;
383 let pre: u8 = 1 << (pre.to_bits() - 3); 265 (freq, freq * 2u32)
384 let freq = ahb_freq.0 / pre as u32;
385 (freq, freq * 2)
386 } 266 }
387 }; 267 };
388 268
389 if config.low_power_run { 269 if config.low_power_run {
390 assert!(sys_clk <= 2_000_000); 270 assert!(sys_clk.0 <= 2_000_000);
391 PWR.cr1().modify(|w| w.set_lpr(true)); 271 PWR.cr1().modify(|w| w.set_lpr(true));
392 } 272 }
393 273
274 let rtc = config.ls.init();
275
394 set_freqs(Clocks { 276 set_freqs(Clocks {
395 sys: Hertz(sys_clk), 277 sys: sys_clk,
396 ahb1: ahb_freq, 278 hclk1: ahb_freq,
397 apb1: Hertz(apb_freq), 279 pclk1: apb_freq,
398 apb1_tim: Hertz(apb_tim_freq), 280 pclk1_tim: apb_tim_freq,
281 rtc,
399 }); 282 });
400} 283}
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index 41bebc918..ba2a5e19c 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -2,7 +2,10 @@ use stm32_metapac::flash::vals::Latency;
2use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; 2use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
3use stm32_metapac::FLASH; 3use stm32_metapac::FLASH;
4 4
5pub use super::bus::{AHBPrescaler, APBPrescaler}; 5pub use crate::pac::rcc::vals::{
6 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ,
7 Pllr as PllR, Ppre as APBPrescaler,
8};
6use crate::pac::{PWR, RCC}; 9use crate::pac::{PWR, RCC};
7use crate::rcc::sealed::RccPeripheral; 10use crate::rcc::sealed::RccPeripheral;
8use crate::rcc::{set_freqs, Clocks}; 11use crate::rcc::{set_freqs, Clocks};
@@ -11,32 +14,6 @@ use crate::time::Hertz;
11/// HSI speed 14/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000); 15pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13 16
14/// LSI speed
15pub const LSI_FREQ: Hertz = Hertz(32_000);
16
17#[derive(Clone, Copy)]
18pub enum AdcClockSource {
19 NoClk,
20 SysClk,
21 PllP,
22}
23
24impl AdcClockSource {
25 pub fn adcsel(&self) -> Adcsel {
26 match self {
27 AdcClockSource::NoClk => Adcsel::NOCLK,
28 AdcClockSource::SysClk => Adcsel::SYSCLK,
29 AdcClockSource::PllP => Adcsel::PLLP,
30 }
31 }
32}
33
34impl Default for AdcClockSource {
35 fn default() -> Self {
36 Self::NoClk
37 }
38}
39
40/// System clock mux source 17/// System clock mux source
41#[derive(Clone, Copy)] 18#[derive(Clone, Copy)]
42pub enum ClockSrc { 19pub enum ClockSrc {
@@ -56,182 +33,7 @@ impl Into<Pllsrc> for PllSrc {
56 fn into(self) -> Pllsrc { 33 fn into(self) -> Pllsrc {
57 match self { 34 match self {
58 PllSrc::HSE(..) => Pllsrc::HSE, 35 PllSrc::HSE(..) => Pllsrc::HSE,
59 PllSrc::HSI16 => Pllsrc::HSI16, 36 PllSrc::HSI16 => Pllsrc::HSI,
60 }
61 }
62}
63
64seq_macro::seq!(P in 2..=31 {
65 /// Output divider for the PLL P output.
66 #[derive(Clone, Copy)]
67 pub enum PllP {
68 // Note: If PLL P is set to 0 the PLLP bit controls the output division. There does not seem to
69 // a good reason to do this so the API does not support it.
70 // Div1 is invalid
71 #(
72 Div~P,
73 )*
74 }
75
76 impl From<PllP> for u8 {
77 /// Returns the register value for the P output divider.
78 fn from(val: PllP) -> u8 {
79 match val {
80 #(
81 PllP::Div~P => P,
82 )*
83 }
84 }
85 }
86});
87
88impl PllP {
89 /// Returns the numeric value of the P output divider.
90 pub fn to_div(self) -> u32 {
91 let val: u8 = self.into();
92 val as u32
93 }
94}
95
96/// Output divider for the PLL Q output.
97#[derive(Clone, Copy)]
98pub enum PllQ {
99 Div2,
100 Div4,
101 Div6,
102 Div8,
103}
104
105impl PllQ {
106 /// Returns the numeric value of the Q output divider.
107 pub fn to_div(self) -> u32 {
108 let val: u8 = self.into();
109 (val as u32 + 1) * 2
110 }
111}
112
113impl From<PllQ> for u8 {
114 /// Returns the register value for the Q output divider.
115 fn from(val: PllQ) -> u8 {
116 match val {
117 PllQ::Div2 => 0b00,
118 PllQ::Div4 => 0b01,
119 PllQ::Div6 => 0b10,
120 PllQ::Div8 => 0b11,
121 }
122 }
123}
124
125/// Output divider for the PLL R output.
126#[derive(Clone, Copy)]
127pub enum PllR {
128 Div2,
129 Div4,
130 Div6,
131 Div8,
132}
133
134impl PllR {
135 /// Returns the numeric value of the R output divider.
136 pub fn to_div(self) -> u32 {
137 let val: u8 = self.into();
138 (val as u32 + 1) * 2
139 }
140}
141
142impl From<PllR> for u8 {
143 /// Returns the register value for the R output divider.
144 fn from(val: PllR) -> u8 {
145 match val {
146 PllR::Div2 => 0b00,
147 PllR::Div4 => 0b01,
148 PllR::Div6 => 0b10,
149 PllR::Div8 => 0b11,
150 }
151 }
152}
153
154seq_macro::seq!(N in 8..=127 {
155 /// Multiplication factor for the PLL VCO input clock.
156 #[derive(Clone, Copy)]
157 pub enum PllN {
158 #(
159 Mul~N,
160 )*
161 }
162
163 impl From<PllN> for u8 {
164 /// Returns the register value for the N multiplication factor.
165 fn from(val: PllN) -> u8 {
166 match val {
167 #(
168 PllN::Mul~N => N,
169 )*
170 }
171 }
172 }
173
174 impl PllN {
175 /// Returns the numeric value of the N multiplication factor.
176 pub fn to_mul(self) -> u32 {
177 match self {
178 #(
179 PllN::Mul~N => N,
180 )*
181 }
182 }
183 }
184});
185
186/// PLL Pre-division. This must be set such that the PLL input is between 2.66 MHz and 16 MHz.
187#[derive(Copy, Clone)]
188pub enum PllM {
189 Div1,
190 Div2,
191 Div3,
192 Div4,
193 Div5,
194 Div6,
195 Div7,
196 Div8,
197 Div9,
198 Div10,
199 Div11,
200 Div12,
201 Div13,
202 Div14,
203 Div15,
204 Div16,
205}
206
207impl PllM {
208 /// Returns the numeric value of the M pre-division.
209 pub fn to_div(self) -> u32 {
210 let val: u8 = self.into();
211 val as u32 + 1
212 }
213}
214
215impl From<PllM> for u8 {
216 /// Returns the register value for the M pre-division.
217 fn from(val: PllM) -> u8 {
218 match val {
219 PllM::Div1 => 0b0000,
220 PllM::Div2 => 0b0001,
221 PllM::Div3 => 0b0010,
222 PllM::Div4 => 0b0011,
223 PllM::Div5 => 0b0100,
224 PllM::Div6 => 0b0101,
225 PllM::Div7 => 0b0110,
226 PllM::Div8 => 0b0111,
227 PllM::Div9 => 0b1000,
228 PllM::Div10 => 0b1001,
229 PllM::Div11 => 0b1010,
230 PllM::Div12 => 0b1011,
231 PllM::Div13 => 0b1100,
232 PllM::Div14 => 0b1101,
233 PllM::Div15 => 0b1110,
234 PllM::Div16 => 0b1111,
235 } 37 }
236 } 38 }
237} 39}
@@ -261,32 +63,6 @@ pub struct Pll {
261 pub div_r: Option<PllR>, 63 pub div_r: Option<PllR>,
262} 64}
263 65
264fn ahb_div(ahb: AHBPrescaler) -> u32 {
265 match ahb {
266 AHBPrescaler::DIV1 => 1,
267 AHBPrescaler::DIV2 => 2,
268 AHBPrescaler::DIV4 => 4,
269 AHBPrescaler::DIV8 => 8,
270 AHBPrescaler::DIV16 => 16,
271 AHBPrescaler::DIV64 => 64,
272 AHBPrescaler::DIV128 => 128,
273 AHBPrescaler::DIV256 => 256,
274 AHBPrescaler::DIV512 => 512,
275 _ => unreachable!(),
276 }
277}
278
279fn apb_div(apb: APBPrescaler) -> u32 {
280 match apb {
281 APBPrescaler::DIV1 => 1,
282 APBPrescaler::DIV2 => 2,
283 APBPrescaler::DIV4 => 4,
284 APBPrescaler::DIV8 => 8,
285 APBPrescaler::DIV16 => 16,
286 _ => unreachable!(),
287 }
288}
289
290/// Sets the source for the 48MHz clock to the USB and RNG peripherals. 66/// Sets the source for the 48MHz clock to the USB and RNG peripherals.
291pub enum Clock48MhzSrc { 67pub enum Clock48MhzSrc {
292 /// Use the High Speed Internal Oscillator. For USB usage, the CRS must be used to calibrate the 68 /// Use the High Speed Internal Oscillator. For USB usage, the CRS must be used to calibrate the
@@ -322,6 +98,8 @@ pub struct Config {
322 pub clock_48mhz_src: Option<Clock48MhzSrc>, 98 pub clock_48mhz_src: Option<Clock48MhzSrc>,
323 pub adc12_clock_source: AdcClockSource, 99 pub adc12_clock_source: AdcClockSource,
324 pub adc345_clock_source: AdcClockSource, 100 pub adc345_clock_source: AdcClockSource,
101
102 pub ls: super::LsConfig,
325} 103}
326 104
327/// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator. 105/// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator.
@@ -340,9 +118,10 @@ impl Default for Config {
340 apb2_pre: APBPrescaler::DIV1, 118 apb2_pre: APBPrescaler::DIV1,
341 low_power_run: false, 119 low_power_run: false,
342 pll: None, 120 pll: None,
343 clock_48mhz_src: None, 121 clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(None)),
344 adc12_clock_source: Default::default(), 122 adc12_clock_source: Adcsel::DISABLE,
345 adc345_clock_source: Default::default(), 123 adc345_clock_source: Adcsel::DISABLE,
124 ls: Default::default(),
346 } 125 }
347 } 126 }
348} 127}
@@ -360,12 +139,12 @@ pub(crate) unsafe fn init(config: Config) {
360 RCC.cr().write(|w| w.set_hsion(true)); 139 RCC.cr().write(|w| w.set_hsion(true));
361 while !RCC.cr().read().hsirdy() {} 140 while !RCC.cr().read().hsirdy() {}
362 141
363 HSI_FREQ.0 142 HSI_FREQ
364 } 143 }
365 PllSrc::HSE(freq) => { 144 PllSrc::HSE(freq) => {
366 RCC.cr().write(|w| w.set_hseon(true)); 145 RCC.cr().write(|w| w.set_hseon(true));
367 while !RCC.cr().read().hserdy() {} 146 while !RCC.cr().read().hserdy() {}
368 freq.0 147 freq
369 } 148 }
370 }; 149 };
371 150
@@ -373,36 +152,36 @@ pub(crate) unsafe fn init(config: Config) {
373 RCC.cr().modify(|w| w.set_pllon(false)); 152 RCC.cr().modify(|w| w.set_pllon(false));
374 while RCC.cr().read().pllrdy() {} 153 while RCC.cr().read().pllrdy() {}
375 154
376 let internal_freq = src_freq / pll_config.prediv_m.to_div() * pll_config.mul_n.to_mul(); 155 let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n;
377 156
378 RCC.pllcfgr().write(|w| { 157 RCC.pllcfgr().write(|w| {
379 w.set_plln(pll_config.mul_n.into()); 158 w.set_plln(pll_config.mul_n);
380 w.set_pllm(pll_config.prediv_m.into()); 159 w.set_pllm(pll_config.prediv_m);
381 w.set_pllsrc(pll_config.source.into()); 160 w.set_pllsrc(pll_config.source.into());
382 }); 161 });
383 162
384 let pll_p_freq = pll_config.div_p.map(|div_p| { 163 let pll_p_freq = pll_config.div_p.map(|div_p| {
385 RCC.pllcfgr().modify(|w| { 164 RCC.pllcfgr().modify(|w| {
386 w.set_pllpdiv(div_p.into()); 165 w.set_pllp(div_p);
387 w.set_pllpen(true); 166 w.set_pllpen(true);
388 }); 167 });
389 Hertz(internal_freq / div_p.to_div()) 168 internal_freq / div_p
390 }); 169 });
391 170
392 let pll_q_freq = pll_config.div_q.map(|div_q| { 171 let pll_q_freq = pll_config.div_q.map(|div_q| {
393 RCC.pllcfgr().modify(|w| { 172 RCC.pllcfgr().modify(|w| {
394 w.set_pllq(div_q.into()); 173 w.set_pllq(div_q);
395 w.set_pllqen(true); 174 w.set_pllqen(true);
396 }); 175 });
397 Hertz(internal_freq / div_q.to_div()) 176 internal_freq / div_q
398 }); 177 });
399 178
400 let pll_r_freq = pll_config.div_r.map(|div_r| { 179 let pll_r_freq = pll_config.div_r.map(|div_r| {
401 RCC.pllcfgr().modify(|w| { 180 RCC.pllcfgr().modify(|w| {
402 w.set_pllr(div_r.into()); 181 w.set_pllr(div_r);
403 w.set_pllren(true); 182 w.set_pllren(true);
404 }); 183 });
405 Hertz(internal_freq / div_r.to_div()) 184 internal_freq / div_r
406 }); 185 });
407 186
408 // Enable the PLL 187 // Enable the PLL
@@ -422,14 +201,14 @@ pub(crate) unsafe fn init(config: Config) {
422 RCC.cr().write(|w| w.set_hsion(true)); 201 RCC.cr().write(|w| w.set_hsion(true));
423 while !RCC.cr().read().hsirdy() {} 202 while !RCC.cr().read().hsirdy() {}
424 203
425 (HSI_FREQ.0, Sw::HSI16) 204 (HSI_FREQ, Sw::HSI)
426 } 205 }
427 ClockSrc::HSE(freq) => { 206 ClockSrc::HSE(freq) => {
428 // Enable HSE 207 // Enable HSE
429 RCC.cr().write(|w| w.set_hseon(true)); 208 RCC.cr().write(|w| w.set_hseon(true));
430 while !RCC.cr().read().hserdy() {} 209 while !RCC.cr().read().hserdy() {}
431 210
432 (freq.0, Sw::HSE) 211 (freq, Sw::HSE)
433 } 212 }
434 ClockSrc::PLL => { 213 ClockSrc::PLL => {
435 assert!(pll_freq.is_some()); 214 assert!(pll_freq.is_some());
@@ -470,35 +249,32 @@ pub(crate) unsafe fn init(config: Config) {
470 } 249 }
471 } 250 }
472 251
473 (freq, Sw::PLLRCLK) 252 (Hertz(freq), Sw::PLL1_R)
474 } 253 }
475 }; 254 };
476 255
477 RCC.cfgr().modify(|w| { 256 RCC.cfgr().modify(|w| {
478 w.set_sw(sw); 257 w.set_sw(sw);
479 w.set_hpre(config.ahb_pre.into()); 258 w.set_hpre(config.ahb_pre);
480 w.set_ppre1(config.apb1_pre.into()); 259 w.set_ppre1(config.apb1_pre);
481 w.set_ppre2(config.apb2_pre.into()); 260 w.set_ppre2(config.apb2_pre);
482 }); 261 });
483 262
484 let ahb_freq: u32 = match config.ahb_pre { 263 let ahb_freq = sys_clk / config.ahb_pre;
485 AHBPrescaler::DIV1 => sys_clk,
486 pre => sys_clk / ahb_div(pre),
487 };
488 264
489 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 265 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
490 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 266 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
491 pre => { 267 pre => {
492 let freq = ahb_freq / apb_div(pre); 268 let freq = ahb_freq / pre;
493 (freq, freq * 2) 269 (freq, freq * 2u32)
494 } 270 }
495 }; 271 };
496 272
497 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 273 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
498 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 274 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
499 pre => { 275 pre => {
500 let freq = ahb_freq / apb_div(pre); 276 let freq = ahb_freq / pre;
501 (freq, freq * 2) 277 (freq, freq * 2u32)
502 } 278 }
503 }; 279 };
504 280
@@ -510,7 +286,7 @@ pub(crate) unsafe fn init(config: Config) {
510 let pllq_freq = pll_freq.as_ref().and_then(|f| f.pll_q); 286 let pllq_freq = pll_freq.as_ref().and_then(|f| f.pll_q);
511 assert!(pllq_freq.is_some() && pllq_freq.unwrap().0 == 48_000_000); 287 assert!(pllq_freq.is_some() && pllq_freq.unwrap().0 == 48_000_000);
512 288
513 crate::pac::rcc::vals::Clk48sel::PLLQCLK 289 crate::pac::rcc::vals::Clk48sel::PLL1_Q
514 } 290 }
515 Clock48MhzSrc::Hsi48(crs_config) => { 291 Clock48MhzSrc::Hsi48(crs_config) => {
516 // Enable HSI48 292 // Enable HSI48
@@ -520,7 +296,7 @@ pub(crate) unsafe fn init(config: Config) {
520 296
521 // Enable and setup CRS if needed 297 // Enable and setup CRS if needed
522 if let Some(crs_config) = crs_config { 298 if let Some(crs_config) = crs_config {
523 crate::peripherals::CRS::enable(); 299 crate::peripherals::CRS::enable_and_reset();
524 300
525 let sync_src = match crs_config.sync_src { 301 let sync_src = match crs_config.sync_src {
526 CrsSyncSource::Gpio => crate::pac::crs::vals::Syncsrc::GPIO, 302 CrsSyncSource::Gpio => crate::pac::crs::vals::Syncsrc::GPIO,
@@ -546,43 +322,41 @@ pub(crate) unsafe fn init(config: Config) {
546 RCC.ccipr().modify(|w| w.set_clk48sel(source)); 322 RCC.ccipr().modify(|w| w.set_clk48sel(source));
547 } 323 }
548 324
549 RCC.ccipr() 325 RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source));
550 .modify(|w| w.set_adc12sel(config.adc12_clock_source.adcsel())); 326 RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source));
551 RCC.ccipr()
552 .modify(|w| w.set_adc345sel(config.adc345_clock_source.adcsel()));
553 327
554 let adc12_ck = match config.adc12_clock_source { 328 let adc12_ck = match config.adc12_clock_source {
555 AdcClockSource::NoClk => None, 329 AdcClockSource::DISABLE => None,
556 AdcClockSource::PllP => match &pll_freq { 330 AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p,
557 Some(pll) => pll.pll_p, 331 AdcClockSource::SYS => Some(sys_clk),
558 None => None, 332 _ => unreachable!(),
559 },
560 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
561 }; 333 };
562 334
563 let adc345_ck = match config.adc345_clock_source { 335 let adc345_ck = match config.adc345_clock_source {
564 AdcClockSource::NoClk => None, 336 AdcClockSource::DISABLE => None,
565 AdcClockSource::PllP => match &pll_freq { 337 AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p,
566 Some(pll) => pll.pll_p, 338 AdcClockSource::SYS => Some(sys_clk),
567 None => None, 339 _ => unreachable!(),
568 },
569 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
570 }; 340 };
571 341
572 if config.low_power_run { 342 if config.low_power_run {
573 assert!(sys_clk <= 2_000_000); 343 assert!(sys_clk <= Hertz(2_000_000));
574 PWR.cr1().modify(|w| w.set_lpr(true)); 344 PWR.cr1().modify(|w| w.set_lpr(true));
575 } 345 }
576 346
347 let rtc = config.ls.init();
348
577 set_freqs(Clocks { 349 set_freqs(Clocks {
578 sys: Hertz(sys_clk), 350 sys: sys_clk,
579 ahb1: Hertz(ahb_freq), 351 hclk1: ahb_freq,
580 ahb2: Hertz(ahb_freq), 352 hclk2: ahb_freq,
581 apb1: Hertz(apb1_freq), 353 pclk1: apb1_freq,
582 apb1_tim: Hertz(apb1_tim_freq), 354 pclk1_tim: apb1_tim_freq,
583 apb2: Hertz(apb2_freq), 355 pclk2: apb2_freq,
584 apb2_tim: Hertz(apb2_tim_freq), 356 pclk2_tim: apb2_tim_freq,
585 adc: adc12_ck, 357 adc: adc12_ck,
586 adc34: adc345_ck, 358 adc34: adc345_ck,
359 pll1_p: None,
360 rtc,
587 }); 361 });
588} 362}
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 43e8db22e..5dbcfea90 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -6,8 +6,8 @@ use crate::pac::pwr::vals::Vos;
6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; 6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
7#[cfg(stm32h7)] 7#[cfg(stm32h7)]
8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; 8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
9pub use crate::pac::rcc::vals::Ckpersel as PerClockSource;
10use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; 9use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre};
10pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul};
11use crate::pac::{FLASH, PWR, RCC}; 11use crate::pac::{FLASH, PWR, RCC};
12use crate::rcc::{set_freqs, Clocks}; 12use crate::rcc::{set_freqs, Clocks};
13use crate::time::Hertz; 13use crate::time::Hertz;
@@ -21,18 +21,15 @@ pub const CSI_FREQ: Hertz = Hertz(4_000_000);
21/// HSI48 speed 21/// HSI48 speed
22pub const HSI48_FREQ: Hertz = Hertz(48_000_000); 22pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
23 23
24/// LSI speed 24const VCO_RANGE: RangeInclusive<Hertz> = Hertz(150_000_000)..=Hertz(420_000_000);
25pub const LSI_FREQ: Hertz = Hertz(32_000);
26
27const VCO_RANGE: RangeInclusive<u32> = 150_000_000..=420_000_000;
28#[cfg(any(stm32h5, pwr_h7rm0455))] 25#[cfg(any(stm32h5, pwr_h7rm0455))]
29const VCO_WIDE_RANGE: RangeInclusive<u32> = 128_000_000..=560_000_000; 26const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(128_000_000)..=Hertz(560_000_000);
30#[cfg(pwr_h7rm0468)] 27#[cfg(pwr_h7rm0468)]
31const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=836_000_000; 28const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(836_000_000);
32#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] 29#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
33const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000; 30const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(960_000_000);
34 31
35pub use super::bus::{AHBPrescaler, APBPrescaler}; 32pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
36 33
37#[derive(Clone, Copy, Eq, PartialEq)] 34#[derive(Clone, Copy, Eq, PartialEq)]
38pub enum VoltageScale { 35pub enum VoltageScale {
@@ -46,9 +43,9 @@ pub enum VoltageScale {
46pub enum HseMode { 43pub enum HseMode {
47 /// crystal/ceramic oscillator (HSEBYP=0) 44 /// crystal/ceramic oscillator (HSEBYP=0)
48 Oscillator, 45 Oscillator,
49 /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0) 46 /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
50 Bypass, 47 Bypass,
51 /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1) 48 /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
52 #[cfg(any(rcc_h5, rcc_h50))] 49 #[cfg(any(rcc_h5, rcc_h50))]
53 BypassDigital, 50 BypassDigital,
54} 51}
@@ -98,19 +95,19 @@ pub struct Pll {
98 #[cfg(stm32h5)] 95 #[cfg(stm32h5)]
99 pub source: PllSource, 96 pub source: PllSource,
100 97
101 /// PLL pre-divider (DIVM). Must be between 1 and 63. 98 /// PLL pre-divider (DIVM).
102 pub prediv: u8, 99 pub prediv: PllPreDiv,
103 100
104 /// PLL multiplication factor. Must be between 4 and 512. 101 /// PLL multiplication factor.
105 pub mul: u16, 102 pub mul: PllMul,
106 103
107 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. 104 /// PLL P division factor. If None, PLL P output is disabled.
108 /// On PLL1, it must be even (in particular, it cannot be 1.) 105 /// On PLL1, it must be even (in particular, it cannot be 1.)
109 pub divp: Option<u16>, 106 pub divp: Option<PllDiv>,
110 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. 107 /// PLL Q division factor. If None, PLL Q output is disabled.
111 pub divq: Option<u16>, 108 pub divq: Option<PllDiv>,
112 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. 109 /// PLL R division factor. If None, PLL R output is disabled.
113 pub divr: Option<u16>, 110 pub divr: Option<PllDiv>,
114} 111}
115 112
116fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { 113fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
@@ -181,6 +178,7 @@ pub struct Config {
181 pub adc_clock_source: AdcClockSource, 178 pub adc_clock_source: AdcClockSource,
182 pub timer_prescaler: TimerPrescaler, 179 pub timer_prescaler: TimerPrescaler,
183 pub voltage_scale: VoltageScale, 180 pub voltage_scale: VoltageScale,
181 pub ls: super::LsConfig,
184} 182}
185 183
186impl Default for Config { 184impl Default for Config {
@@ -210,6 +208,7 @@ impl Default for Config {
210 adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5 208 adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5
211 timer_prescaler: TimerPrescaler::DefaultX2, 209 timer_prescaler: TimerPrescaler::DefaultX2,
212 voltage_scale: VoltageScale::Scale0, 210 voltage_scale: VoltageScale::Scale0,
211 ls: Default::default(),
213 } 212 }
214 } 213 }
215} 214}
@@ -372,14 +371,14 @@ pub(crate) unsafe fn init(config: Config) {
372 let pll1 = init_pll(0, config.pll1, &pll_input); 371 let pll1 = init_pll(0, config.pll1, &pll_input);
373 let pll2 = init_pll(1, config.pll2, &pll_input); 372 let pll2 = init_pll(1, config.pll2, &pll_input);
374 #[cfg(any(rcc_h5, stm32h7))] 373 #[cfg(any(rcc_h5, stm32h7))]
375 let _pll3 = init_pll(2, config.pll3, &pll_input); 374 let pll3 = init_pll(2, config.pll3, &pll_input);
376 375
377 // Configure sysclk 376 // Configure sysclk
378 let (sys, sw) = match config.sys { 377 let (sys, sw) = match config.sys {
379 Sysclk::HSI => (unwrap!(hsi), Sw::HSI), 378 Sysclk::HSI => (unwrap!(hsi), Sw::HSI),
380 Sysclk::HSE => (unwrap!(hse), Sw::HSE), 379 Sysclk::HSE => (unwrap!(hse), Sw::HSE),
381 Sysclk::CSI => (unwrap!(csi), Sw::CSI), 380 Sysclk::CSI => (unwrap!(csi), Sw::CSI),
382 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1), 381 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P),
383 }; 382 };
384 383
385 // Check limits. 384 // Check limits.
@@ -431,23 +430,25 @@ pub(crate) unsafe fn init(config: Config) {
431 #[cfg(stm32h7)] 430 #[cfg(stm32h7)]
432 let adc = match config.adc_clock_source { 431 let adc = match config.adc_clock_source {
433 AdcClockSource::PLL2_P => pll2.p, 432 AdcClockSource::PLL2_P => pll2.p,
434 AdcClockSource::PLL3_R => _pll3.r, 433 AdcClockSource::PLL3_R => pll3.r,
435 AdcClockSource::PER => _per_ck, 434 AdcClockSource::PER => _per_ck,
436 _ => unreachable!(), 435 _ => unreachable!(),
437 }; 436 };
438 #[cfg(stm32h5)] 437 #[cfg(stm32h5)]
439 let adc = match config.adc_clock_source { 438 let adc = match config.adc_clock_source {
440 AdcClockSource::HCLK => Some(hclk), 439 AdcClockSource::HCLK1 => Some(hclk),
441 AdcClockSource::SYSCLK => Some(sys), 440 AdcClockSource::SYS => Some(sys),
442 AdcClockSource::PLL2_R => pll2.r, 441 AdcClockSource::PLL2_R => pll2.r,
443 AdcClockSource::HSE => hse, 442 AdcClockSource::HSE => hse,
444 AdcClockSource::HSI_KER => hsi, 443 AdcClockSource::HSI => hsi,
445 AdcClockSource::CSI_KER => csi, 444 AdcClockSource::CSI => csi,
446 _ => unreachable!(), 445 _ => unreachable!(),
447 }; 446 };
448 447
449 flash_setup(hclk, config.voltage_scale); 448 flash_setup(hclk, config.voltage_scale);
450 449
450 let rtc = config.ls.init();
451
451 #[cfg(stm32h7)] 452 #[cfg(stm32h7)]
452 { 453 {
453 RCC.d1cfgr().modify(|w| { 454 RCC.d1cfgr().modify(|w| {
@@ -514,18 +515,65 @@ pub(crate) unsafe fn init(config: Config) {
514 515
515 set_freqs(Clocks { 516 set_freqs(Clocks {
516 sys, 517 sys,
517 ahb1: hclk, 518 hclk1: hclk,
518 ahb2: hclk, 519 hclk2: hclk,
519 ahb3: hclk, 520 hclk3: hclk,
520 ahb4: hclk, 521 hclk4: hclk,
521 apb1, 522 pclk1: apb1,
522 apb2, 523 pclk2: apb2,
523 apb3, 524 pclk3: apb3,
525 #[cfg(stm32h7)]
526 pclk4: apb4,
527 #[cfg(stm32h5)]
528 pclk4: Hertz(1),
529 pclk1_tim: apb1_tim,
530 pclk2_tim: apb2_tim,
531 adc,
532 rtc,
533
534 #[cfg(any(stm32h5, stm32h7))]
535 hsi: None,
536 #[cfg(stm32h5)]
537 hsi48: None,
538 #[cfg(stm32h5)]
539 lsi: None,
540 #[cfg(any(stm32h5, stm32h7))]
541 csi: None,
542
543 #[cfg(any(stm32h5, stm32h7))]
544 lse: None,
545 #[cfg(any(stm32h5, stm32h7))]
546 hse: None,
547
548 #[cfg(any(stm32h5, stm32h7))]
549 pll1_q: pll1.q,
550 #[cfg(any(stm32h5, stm32h7))]
551 pll2_p: pll2.p,
552 #[cfg(any(stm32h5, stm32h7))]
553 pll2_q: pll2.q,
554 #[cfg(any(stm32h5, stm32h7))]
555 pll2_r: pll2.r,
556 #[cfg(any(rcc_h5, stm32h7))]
557 pll3_p: pll3.p,
558 #[cfg(any(rcc_h5, stm32h7))]
559 pll3_q: pll3.q,
560 #[cfg(any(rcc_h5, stm32h7))]
561 pll3_r: pll3.r,
562
563 #[cfg(rcc_h50)]
564 pll3_p: None,
565 #[cfg(rcc_h50)]
566 pll3_q: None,
567 #[cfg(rcc_h50)]
568 pll3_r: None,
569
570 #[cfg(stm32h5)]
571 audioclk: None,
572 #[cfg(any(stm32h5, stm32h7))]
573 per: None,
574
524 #[cfg(stm32h7)] 575 #[cfg(stm32h7)]
525 apb4, 576 rcc_pclk_d3: None,
526 apb1_tim,
527 apb2_tim,
528 adc: adc,
529 }); 577 });
530} 578}
531 579
@@ -553,9 +601,9 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
553 601
554 // "To save power when PLL1 is not used, the value of PLL1M must be set to 0."" 602 // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
555 #[cfg(stm32h7)] 603 #[cfg(stm32h7)]
556 RCC.pllckselr().write(|w| w.set_divm(num, 0)); 604 RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0)));
557 #[cfg(stm32h5)] 605 #[cfg(stm32h5)]
558 RCC.pllcfgr(num).write(|w| w.set_divm(0)); 606 RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));
559 607
560 return PllOutput { 608 return PllOutput {
561 p: None, 609 p: None,
@@ -564,9 +612,6 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
564 }; 612 };
565 }; 613 };
566 614
567 assert!(1 <= config.prediv && config.prediv <= 63);
568 assert!(4 <= config.mul && config.mul <= 512);
569
570 #[cfg(stm32h5)] 615 #[cfg(stm32h5)]
571 let source = config.source; 616 let source = config.source;
572 #[cfg(stm32h7)] 617 #[cfg(stm32h7)]
@@ -593,31 +638,25 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
593 let wide_allowed = ref_range != Pllrge::RANGE1; 638 let wide_allowed = ref_range != Pllrge::RANGE1;
594 639
595 let vco_clk = ref_clk * config.mul; 640 let vco_clk = ref_clk * config.mul;
596 let vco_range = if VCO_RANGE.contains(&vco_clk.0) { 641 let vco_range = if VCO_RANGE.contains(&vco_clk) {
597 Pllvcosel::MEDIUMVCO 642 Pllvcosel::MEDIUMVCO
598 } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk.0) { 643 } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk) {
599 Pllvcosel::WIDEVCO 644 Pllvcosel::WIDEVCO
600 } else { 645 } else {
601 panic!("pll vco_clk out of range: {} mhz", vco_clk.0) 646 panic!("pll vco_clk out of range: {} mhz", vco_clk.0)
602 }; 647 };
603 648
604 let p = config.divp.map(|div| { 649 let p = config.divp.map(|div| {
605 assert!(1 <= div && div <= 128);
606 if num == 0 { 650 if num == 0 {
607 // on PLL1, DIVP must be even. 651 // on PLL1, DIVP must be even.
608 assert!(div % 2 == 0); 652 // The enum value is 1 less than the divider, so check it's odd.
653 assert!(div.to_bits() % 2 == 1);
609 } 654 }
610 655
611 vco_clk / div 656 vco_clk / div
612 }); 657 });
613 let q = config.divq.map(|div| { 658 let q = config.divq.map(|div| vco_clk / div);
614 assert!(1 <= div && div <= 128); 659 let r = config.divr.map(|div| vco_clk / div);
615 vco_clk / div
616 });
617 let r = config.divr.map(|div| {
618 assert!(1 <= div && div <= 128);
619 vco_clk / div
620 });
621 660
622 #[cfg(stm32h5)] 661 #[cfg(stm32h5)]
623 RCC.pllcfgr(num).write(|w| { 662 RCC.pllcfgr(num).write(|w| {
@@ -648,10 +687,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
648 } 687 }
649 688
650 RCC.plldivr(num).write(|w| { 689 RCC.plldivr(num).write(|w| {
651 w.set_plln(config.mul - 1); 690 w.set_plln(config.mul);
652 w.set_pllp((config.divp.unwrap_or(1) - 1) as u8); 691 w.set_pllp(config.divp.unwrap_or(PllDiv::DIV2));
653 w.set_pllq((config.divq.unwrap_or(1) - 1) as u8); 692 w.set_pllq(config.divq.unwrap_or(PllDiv::DIV2));
654 w.set_pllr((config.divr.unwrap_or(1) - 1) as u8); 693 w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2));
655 }); 694 });
656 695
657 RCC.cr().modify(|w| w.set_pllon(num, true)); 696 RCC.cr().modify(|w| w.set_pllon(num, true));
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs
deleted file mode 100644
index 7358be31b..000000000
--- a/embassy-stm32/src/rcc/l0.rs
+++ /dev/null
@@ -1,349 +0,0 @@
1use super::bd::BackupDomain;
2pub use super::bus::{AHBPrescaler, APBPrescaler};
3use super::RtcClockSource;
4pub use crate::pac::pwr::vals::Vos as VoltageScale;
5use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
6#[cfg(crs)]
7use crate::pac::{crs, CRS, SYSCFG};
8use crate::pac::{FLASH, PWR, RCC};
9use crate::rcc::{set_freqs, Clocks};
10use crate::time::Hertz;
11
12/// HSI speed
13pub const HSI_FREQ: Hertz = Hertz(16_000_000);
14
15/// LSI speed
16pub const LSI_FREQ: Hertz = Hertz(32_000);
17
18/// System clock mux source
19#[derive(Clone, Copy)]
20pub enum ClockSrc {
21 MSI(MSIRange),
22 PLL(PLLSource, PLLMul, PLLDiv),
23 HSE(Hertz),
24 HSI16,
25}
26
27/// MSI Clock Range
28///
29/// These ranges control the frequency of the MSI. Internally, these ranges map
30/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
31#[derive(Clone, Copy)]
32pub enum MSIRange {
33 /// Around 65.536 kHz
34 Range0,
35 /// Around 131.072 kHz
36 Range1,
37 /// Around 262.144 kHz
38 Range2,
39 /// Around 524.288 kHz
40 Range3,
41 /// Around 1.048 MHz
42 Range4,
43 /// Around 2.097 MHz (reset value)
44 Range5,
45 /// Around 4.194 MHz
46 Range6,
47}
48
49impl Default for MSIRange {
50 fn default() -> MSIRange {
51 MSIRange::Range5
52 }
53}
54
55/// PLL divider
56#[derive(Clone, Copy)]
57pub enum PLLDiv {
58 Div2,
59 Div3,
60 Div4,
61}
62
63/// PLL multiplier
64#[derive(Clone, Copy)]
65pub enum PLLMul {
66 Mul3,
67 Mul4,
68 Mul6,
69 Mul8,
70 Mul12,
71 Mul16,
72 Mul24,
73 Mul32,
74 Mul48,
75}
76
77/// PLL clock input source
78#[derive(Clone, Copy)]
79pub enum PLLSource {
80 HSI16,
81 HSE(Hertz),
82}
83
84impl From<PLLMul> for Pllmul {
85 fn from(val: PLLMul) -> Pllmul {
86 match val {
87 PLLMul::Mul3 => Pllmul::MUL3,
88 PLLMul::Mul4 => Pllmul::MUL4,
89 PLLMul::Mul6 => Pllmul::MUL6,
90 PLLMul::Mul8 => Pllmul::MUL8,
91 PLLMul::Mul12 => Pllmul::MUL12,
92 PLLMul::Mul16 => Pllmul::MUL16,
93 PLLMul::Mul24 => Pllmul::MUL24,
94 PLLMul::Mul32 => Pllmul::MUL32,
95 PLLMul::Mul48 => Pllmul::MUL48,
96 }
97 }
98}
99
100impl From<PLLDiv> for Plldiv {
101 fn from(val: PLLDiv) -> Plldiv {
102 match val {
103 PLLDiv::Div2 => Plldiv::DIV2,
104 PLLDiv::Div3 => Plldiv::DIV3,
105 PLLDiv::Div4 => Plldiv::DIV4,
106 }
107 }
108}
109
110impl From<PLLSource> for Pllsrc {
111 fn from(val: PLLSource) -> Pllsrc {
112 match val {
113 PLLSource::HSI16 => Pllsrc::HSI16,
114 PLLSource::HSE(_) => Pllsrc::HSE,
115 }
116 }
117}
118
119impl From<MSIRange> for Msirange {
120 fn from(val: MSIRange) -> Msirange {
121 match val {
122 MSIRange::Range0 => Msirange::RANGE0,
123 MSIRange::Range1 => Msirange::RANGE1,
124 MSIRange::Range2 => Msirange::RANGE2,
125 MSIRange::Range3 => Msirange::RANGE3,
126 MSIRange::Range4 => Msirange::RANGE4,
127 MSIRange::Range5 => Msirange::RANGE5,
128 MSIRange::Range6 => Msirange::RANGE6,
129 }
130 }
131}
132
133/// Clocks configutation
134pub struct Config {
135 pub mux: ClockSrc,
136 pub ahb_pre: AHBPrescaler,
137 pub apb1_pre: APBPrescaler,
138 pub apb2_pre: APBPrescaler,
139 #[cfg(crs)]
140 pub enable_hsi48: bool,
141 pub rtc: Option<RtcClockSource>,
142 pub lse: Option<Hertz>,
143 pub lsi: bool,
144 pub voltage_scale: VoltageScale,
145}
146
147impl Default for Config {
148 #[inline]
149 fn default() -> Config {
150 Config {
151 mux: ClockSrc::MSI(MSIRange::default()),
152 ahb_pre: AHBPrescaler::DIV1,
153 apb1_pre: APBPrescaler::DIV1,
154 apb2_pre: APBPrescaler::DIV1,
155 #[cfg(crs)]
156 enable_hsi48: false,
157 rtc: None,
158 lse: None,
159 lsi: false,
160 voltage_scale: VoltageScale::RANGE1,
161 }
162 }
163}
164
165pub(crate) unsafe fn init(config: Config) {
166 // Set voltage scale
167 while PWR.csr().read().vosf() {}
168 PWR.cr().write(|w| w.set_vos(config.voltage_scale));
169 while PWR.csr().read().vosf() {}
170
171 let (sys_clk, sw) = match config.mux {
172 ClockSrc::MSI(range) => {
173 // Set MSI range
174 RCC.icscr().write(|w| w.set_msirange(range.into()));
175
176 // Enable MSI
177 RCC.cr().write(|w| w.set_msion(true));
178 while !RCC.cr().read().msirdy() {}
179
180 let freq = 32_768 * (1 << (range as u8 + 1));
181 (freq, Sw::MSI)
182 }
183 ClockSrc::HSI16 => {
184 // Enable HSI16
185 RCC.cr().write(|w| w.set_hsi16on(true));
186 while !RCC.cr().read().hsi16rdyf() {}
187
188 (HSI_FREQ.0, Sw::HSI16)
189 }
190 ClockSrc::HSE(freq) => {
191 // Enable HSE
192 RCC.cr().write(|w| w.set_hseon(true));
193 while !RCC.cr().read().hserdy() {}
194
195 (freq.0, Sw::HSE)
196 }
197 ClockSrc::PLL(src, mul, div) => {
198 let freq = match src {
199 PLLSource::HSE(freq) => {
200 // Enable HSE
201 RCC.cr().write(|w| w.set_hseon(true));
202 while !RCC.cr().read().hserdy() {}
203 freq.0
204 }
205 PLLSource::HSI16 => {
206 // Enable HSI
207 RCC.cr().write(|w| w.set_hsi16on(true));
208 while !RCC.cr().read().hsi16rdyf() {}
209 HSI_FREQ.0
210 }
211 };
212
213 // Disable PLL
214 RCC.cr().modify(|w| w.set_pllon(false));
215 while RCC.cr().read().pllrdy() {}
216
217 let freq = match mul {
218 PLLMul::Mul3 => freq * 3,
219 PLLMul::Mul4 => freq * 4,
220 PLLMul::Mul6 => freq * 6,
221 PLLMul::Mul8 => freq * 8,
222 PLLMul::Mul12 => freq * 12,
223 PLLMul::Mul16 => freq * 16,
224 PLLMul::Mul24 => freq * 24,
225 PLLMul::Mul32 => freq * 32,
226 PLLMul::Mul48 => freq * 48,
227 };
228
229 let freq = match div {
230 PLLDiv::Div2 => freq / 2,
231 PLLDiv::Div3 => freq / 3,
232 PLLDiv::Div4 => freq / 4,
233 };
234 assert!(freq <= 32_000_000);
235
236 RCC.cfgr().write(move |w| {
237 w.set_pllmul(mul.into());
238 w.set_plldiv(div.into());
239 w.set_pllsrc(src.into());
240 });
241
242 // Enable PLL
243 RCC.cr().modify(|w| w.set_pllon(true));
244 while !RCC.cr().read().pllrdy() {}
245
246 (freq, Sw::PLL)
247 }
248 };
249
250 BackupDomain::configure_ls(
251 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
252 config.lsi,
253 config.lse.map(|_| Default::default()),
254 );
255
256 let wait_states = match config.voltage_scale {
257 VoltageScale::RANGE1 => match sys_clk {
258 ..=16_000_000 => 0,
259 _ => 1,
260 },
261 VoltageScale::RANGE2 => match sys_clk {
262 ..=8_000_000 => 0,
263 _ => 1,
264 },
265 VoltageScale::RANGE3 => 0,
266 _ => unreachable!(),
267 };
268 FLASH.acr().modify(|w| {
269 w.set_latency(wait_states != 0);
270 });
271
272 RCC.cfgr().modify(|w| {
273 w.set_sw(sw);
274 w.set_hpre(config.ahb_pre.into());
275 w.set_ppre1(config.apb1_pre.into());
276 w.set_ppre2(config.apb2_pre.into());
277 });
278
279 let ahb_freq: u32 = match config.ahb_pre {
280 AHBPrescaler::DIV1 => sys_clk,
281 pre => {
282 let pre: Hpre = pre.into();
283 let pre = 1 << (pre.to_bits() as u32 - 7);
284 sys_clk / pre
285 }
286 };
287
288 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
289 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
290 pre => {
291 let pre: Ppre = pre.into();
292 let pre: u8 = 1 << (pre.to_bits() - 3);
293 let freq = ahb_freq / pre as u32;
294 (freq, freq * 2)
295 }
296 };
297
298 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
299 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
300 pre => {
301 let pre: Ppre = pre.into();
302 let pre: u8 = 1 << (pre.to_bits() - 3);
303 let freq = ahb_freq / pre as u32;
304 (freq, freq * 2)
305 }
306 };
307
308 #[cfg(crs)]
309 if config.enable_hsi48 {
310 // Reset CRS peripheral
311 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
312 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
313
314 // Enable CRS peripheral
315 RCC.apb1enr().modify(|w| w.set_crsen(true));
316
317 // Initialize CRS
318 CRS.cfgr().write(|w|
319
320 // Select LSE as synchronization source
321 w.set_syncsrc(crs::vals::Syncsrc::LSE));
322 CRS.cr().modify(|w| {
323 w.set_autotrimen(true);
324 w.set_cen(true);
325 });
326
327 // Enable VREFINT reference for HSI48 oscillator
328 SYSCFG.cfgr3().modify(|w| {
329 w.set_enref_hsi48(true);
330 w.set_en_vrefint(true);
331 });
332
333 // Select HSI48 as USB clock
334 RCC.ccipr().modify(|w| w.set_hsi48msel(true));
335
336 // Enable dedicated USB clock
337 RCC.crrcr().modify(|w| w.set_hsi48on(true));
338 while !RCC.crrcr().read().hsi48rdy() {}
339 }
340
341 set_freqs(Clocks {
342 sys: Hertz(sys_clk),
343 ahb1: Hertz(ahb_freq),
344 apb1: Hertz(apb1_freq),
345 apb2: Hertz(apb2_freq),
346 apb1_tim: Hertz(apb1_tim_freq),
347 apb2_tim: Hertz(apb2_tim_freq),
348 });
349}
diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs
new file mode 100644
index 000000000..f10c5962a
--- /dev/null
+++ b/embassy-stm32/src/rcc/l0l1.rs
@@ -0,0 +1,219 @@
1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2pub use crate::pac::rcc::vals::{
3 Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler,
4};
5use crate::pac::rcc::vals::{Pllsrc, Sw};
6#[cfg(crs)]
7use crate::pac::{crs, CRS, SYSCFG};
8use crate::pac::{FLASH, PWR, RCC};
9use crate::rcc::{set_freqs, Clocks};
10use crate::time::Hertz;
11
12/// HSI speed
13pub const HSI_FREQ: Hertz = Hertz(16_000_000);
14
15/// System clock mux source
16#[derive(Clone, Copy)]
17pub enum ClockSrc {
18 MSI(MSIRange),
19 PLL(PLLSource, PLLMul, PLLDiv),
20 HSE(Hertz),
21 HSI16,
22}
23
24/// PLL clock input source
25#[derive(Clone, Copy)]
26pub enum PLLSource {
27 HSI16,
28 HSE(Hertz),
29}
30
31impl From<PLLSource> for Pllsrc {
32 fn from(val: PLLSource) -> Pllsrc {
33 match val {
34 PLLSource::HSI16 => Pllsrc::HSI,
35 PLLSource::HSE(_) => Pllsrc::HSE,
36 }
37 }
38}
39
40/// Clocks configutation
41pub struct Config {
42 pub mux: ClockSrc,
43 pub ahb_pre: AHBPrescaler,
44 pub apb1_pre: APBPrescaler,
45 pub apb2_pre: APBPrescaler,
46 #[cfg(crs)]
47 pub enable_hsi48: bool,
48 pub ls: super::LsConfig,
49 pub voltage_scale: VoltageScale,
50}
51
52impl Default for Config {
53 #[inline]
54 fn default() -> Config {
55 Config {
56 mux: ClockSrc::MSI(MSIRange::RANGE5),
57 ahb_pre: AHBPrescaler::DIV1,
58 apb1_pre: APBPrescaler::DIV1,
59 apb2_pre: APBPrescaler::DIV1,
60 #[cfg(crs)]
61 enable_hsi48: false,
62 voltage_scale: VoltageScale::RANGE1,
63 ls: Default::default(),
64 }
65 }
66}
67
68pub(crate) unsafe fn init(config: Config) {
69 // Set voltage scale
70 while PWR.csr().read().vosf() {}
71 PWR.cr().write(|w| w.set_vos(config.voltage_scale));
72 while PWR.csr().read().vosf() {}
73
74 let (sys_clk, sw) = match config.mux {
75 ClockSrc::MSI(range) => {
76 // Set MSI range
77 RCC.icscr().write(|w| w.set_msirange(range));
78
79 // Enable MSI
80 RCC.cr().write(|w| w.set_msion(true));
81 while !RCC.cr().read().msirdy() {}
82
83 let freq = 32_768 * (1 << (range as u8 + 1));
84 (Hertz(freq), Sw::MSI)
85 }
86 ClockSrc::HSI16 => {
87 // Enable HSI16
88 RCC.cr().write(|w| w.set_hsi16on(true));
89 while !RCC.cr().read().hsi16rdy() {}
90
91 (HSI_FREQ, Sw::HSI)
92 }
93 ClockSrc::HSE(freq) => {
94 // Enable HSE
95 RCC.cr().write(|w| w.set_hseon(true));
96 while !RCC.cr().read().hserdy() {}
97
98 (freq, Sw::HSE)
99 }
100 ClockSrc::PLL(src, mul, div) => {
101 let freq = match src {
102 PLLSource::HSE(freq) => {
103 // Enable HSE
104 RCC.cr().write(|w| w.set_hseon(true));
105 while !RCC.cr().read().hserdy() {}
106 freq
107 }
108 PLLSource::HSI16 => {
109 // Enable HSI
110 RCC.cr().write(|w| w.set_hsi16on(true));
111 while !RCC.cr().read().hsi16rdy() {}
112 HSI_FREQ
113 }
114 };
115
116 // Disable PLL
117 RCC.cr().modify(|w| w.set_pllon(false));
118 while RCC.cr().read().pllrdy() {}
119
120 let freq = freq * mul / div;
121
122 assert!(freq <= Hertz(32_000_000));
123
124 RCC.cfgr().write(move |w| {
125 w.set_pllmul(mul);
126 w.set_plldiv(div);
127 w.set_pllsrc(src.into());
128 });
129
130 // Enable PLL
131 RCC.cr().modify(|w| w.set_pllon(true));
132 while !RCC.cr().read().pllrdy() {}
133
134 (freq, Sw::PLL1_P)
135 }
136 };
137
138 let rtc = config.ls.init();
139
140 let wait_states = match (config.voltage_scale, sys_clk.0) {
141 (VoltageScale::RANGE1, ..=16_000_000) => 0,
142 (VoltageScale::RANGE2, ..=8_000_000) => 0,
143 (VoltageScale::RANGE3, ..=4_200_000) => 0,
144 _ => 1,
145 };
146
147 #[cfg(stm32l1)]
148 FLASH.acr().write(|w| w.set_acc64(true));
149 FLASH.acr().modify(|w| w.set_prften(true));
150 FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
151
152 RCC.cfgr().modify(|w| {
153 w.set_sw(sw);
154 w.set_hpre(config.ahb_pre);
155 w.set_ppre1(config.apb1_pre);
156 w.set_ppre2(config.apb2_pre);
157 });
158
159 let ahb_freq = sys_clk / config.ahb_pre;
160
161 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
162 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
163 pre => {
164 let freq = ahb_freq / pre;
165 (freq, freq * 2u32)
166 }
167 };
168
169 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
170 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
171 pre => {
172 let freq = ahb_freq / pre;
173 (freq, freq * 2u32)
174 }
175 };
176
177 #[cfg(crs)]
178 if config.enable_hsi48 {
179 // Reset CRS peripheral
180 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
181 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
182
183 // Enable CRS peripheral
184 RCC.apb1enr().modify(|w| w.set_crsen(true));
185
186 // Initialize CRS
187 CRS.cfgr().write(|w|
188
189 // Select LSE as synchronization source
190 w.set_syncsrc(crs::vals::Syncsrc::LSE));
191 CRS.cr().modify(|w| {
192 w.set_autotrimen(true);
193 w.set_cen(true);
194 });
195
196 // Enable VREFINT reference for HSI48 oscillator
197 SYSCFG.cfgr3().modify(|w| {
198 w.set_enref_hsi48(true);
199 w.set_en_vrefint(true);
200 });
201
202 // Select HSI48 as USB clock
203 RCC.ccipr().modify(|w| w.set_hsi48msel(true));
204
205 // Enable dedicated USB clock
206 RCC.crrcr().modify(|w| w.set_hsi48on(true));
207 while !RCC.crrcr().read().hsi48rdy() {}
208 }
209
210 set_freqs(Clocks {
211 sys: sys_clk,
212 hclk1: ahb_freq,
213 pclk1: apb1_freq,
214 pclk2: apb2_freq,
215 pclk1_tim: apb1_tim_freq,
216 pclk2_tim: apb2_tim_freq,
217 rtc,
218 });
219}
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs
deleted file mode 100644
index 90524fb37..000000000
--- a/embassy-stm32/src/rcc/l1.rs
+++ /dev/null
@@ -1,279 +0,0 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
3use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz;
6
7/// HSI speed
8pub const HSI_FREQ: Hertz = Hertz(16_000_000);
9
10/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(32_000);
12
13/// System clock mux source
14#[derive(Clone, Copy)]
15pub enum ClockSrc {
16 MSI(MSIRange),
17 PLL(PLLSource, PLLMul, PLLDiv),
18 HSE(Hertz),
19 HSI,
20}
21
22/// MSI Clock Range
23///
24/// These ranges control the frequency of the MSI. Internally, these ranges map
25/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
26#[derive(Clone, Copy)]
27pub enum MSIRange {
28 /// Around 65.536 kHz
29 Range0,
30 /// Around 131.072 kHz
31 Range1,
32 /// Around 262.144 kHz
33 Range2,
34 /// Around 524.288 kHz
35 Range3,
36 /// Around 1.048 MHz
37 Range4,
38 /// Around 2.097 MHz (reset value)
39 Range5,
40 /// Around 4.194 MHz
41 Range6,
42}
43
44impl Default for MSIRange {
45 fn default() -> MSIRange {
46 MSIRange::Range5
47 }
48}
49
50/// PLL divider
51#[derive(Clone, Copy)]
52pub enum PLLDiv {
53 Div2,
54 Div3,
55 Div4,
56}
57
58/// PLL multiplier
59#[derive(Clone, Copy)]
60pub enum PLLMul {
61 Mul3,
62 Mul4,
63 Mul6,
64 Mul8,
65 Mul12,
66 Mul16,
67 Mul24,
68 Mul32,
69 Mul48,
70}
71
72/// PLL clock input source
73#[derive(Clone, Copy)]
74pub enum PLLSource {
75 HSI,
76 HSE(Hertz),
77}
78
79impl From<PLLMul> for Pllmul {
80 fn from(val: PLLMul) -> Pllmul {
81 match val {
82 PLLMul::Mul3 => Pllmul::MUL3,
83 PLLMul::Mul4 => Pllmul::MUL4,
84 PLLMul::Mul6 => Pllmul::MUL6,
85 PLLMul::Mul8 => Pllmul::MUL8,
86 PLLMul::Mul12 => Pllmul::MUL12,
87 PLLMul::Mul16 => Pllmul::MUL16,
88 PLLMul::Mul24 => Pllmul::MUL24,
89 PLLMul::Mul32 => Pllmul::MUL32,
90 PLLMul::Mul48 => Pllmul::MUL48,
91 }
92 }
93}
94
95impl From<PLLDiv> for Plldiv {
96 fn from(val: PLLDiv) -> Plldiv {
97 match val {
98 PLLDiv::Div2 => Plldiv::DIV2,
99 PLLDiv::Div3 => Plldiv::DIV3,
100 PLLDiv::Div4 => Plldiv::DIV4,
101 }
102 }
103}
104
105impl From<PLLSource> for Pllsrc {
106 fn from(val: PLLSource) -> Pllsrc {
107 match val {
108 PLLSource::HSI => Pllsrc::HSI,
109 PLLSource::HSE(_) => Pllsrc::HSE,
110 }
111 }
112}
113
114impl From<MSIRange> for Msirange {
115 fn from(val: MSIRange) -> Msirange {
116 match val {
117 MSIRange::Range0 => Msirange::RANGE0,
118 MSIRange::Range1 => Msirange::RANGE1,
119 MSIRange::Range2 => Msirange::RANGE2,
120 MSIRange::Range3 => Msirange::RANGE3,
121 MSIRange::Range4 => Msirange::RANGE4,
122 MSIRange::Range5 => Msirange::RANGE5,
123 MSIRange::Range6 => Msirange::RANGE6,
124 }
125 }
126}
127
128/// Clocks configutation
129pub struct Config {
130 pub mux: ClockSrc,
131 pub ahb_pre: AHBPrescaler,
132 pub apb1_pre: APBPrescaler,
133 pub apb2_pre: APBPrescaler,
134}
135
136impl Default for Config {
137 #[inline]
138 fn default() -> Config {
139 Config {
140 mux: ClockSrc::MSI(MSIRange::default()),
141 ahb_pre: AHBPrescaler::DIV1,
142 apb1_pre: APBPrescaler::DIV1,
143 apb2_pre: APBPrescaler::DIV1,
144 }
145 }
146}
147
148pub(crate) unsafe fn init(config: Config) {
149 let (sys_clk, sw) = match config.mux {
150 ClockSrc::MSI(range) => {
151 // Set MSI range
152 RCC.icscr().write(|w| w.set_msirange(range.into()));
153
154 // Enable MSI
155 RCC.cr().write(|w| w.set_msion(true));
156 while !RCC.cr().read().msirdy() {}
157
158 let freq = 32_768 * (1 << (range as u8 + 1));
159 (freq, Sw::MSI)
160 }
161 ClockSrc::HSI => {
162 // Enable HSI
163 RCC.cr().write(|w| w.set_hsion(true));
164 while !RCC.cr().read().hsirdy() {}
165
166 (HSI_FREQ.0, Sw::HSI)
167 }
168 ClockSrc::HSE(freq) => {
169 // Enable HSE
170 RCC.cr().write(|w| w.set_hseon(true));
171 while !RCC.cr().read().hserdy() {}
172
173 (freq.0, Sw::HSE)
174 }
175 ClockSrc::PLL(src, mul, div) => {
176 let freq = match src {
177 PLLSource::HSE(freq) => {
178 // Enable HSE
179 RCC.cr().write(|w| w.set_hseon(true));
180 while !RCC.cr().read().hserdy() {}
181 freq.0
182 }
183 PLLSource::HSI => {
184 // Enable HSI
185 RCC.cr().write(|w| w.set_hsion(true));
186 while !RCC.cr().read().hsirdy() {}
187 HSI_FREQ.0
188 }
189 };
190
191 // Disable PLL
192 RCC.cr().modify(|w| w.set_pllon(false));
193 while RCC.cr().read().pllrdy() {}
194
195 let freq = match mul {
196 PLLMul::Mul3 => freq * 3,
197 PLLMul::Mul4 => freq * 4,
198 PLLMul::Mul6 => freq * 6,
199 PLLMul::Mul8 => freq * 8,
200 PLLMul::Mul12 => freq * 12,
201 PLLMul::Mul16 => freq * 16,
202 PLLMul::Mul24 => freq * 24,
203 PLLMul::Mul32 => freq * 32,
204 PLLMul::Mul48 => freq * 48,
205 };
206
207 let freq = match div {
208 PLLDiv::Div2 => freq / 2,
209 PLLDiv::Div3 => freq / 3,
210 PLLDiv::Div4 => freq / 4,
211 };
212 assert!(freq <= 32_000_000);
213
214 RCC.cfgr().write(move |w| {
215 w.set_pllmul(mul.into());
216 w.set_plldiv(div.into());
217 w.set_pllsrc(src.into());
218 });
219
220 // Enable PLL
221 RCC.cr().modify(|w| w.set_pllon(true));
222 while !RCC.cr().read().pllrdy() {}
223
224 (freq, Sw::PLL)
225 }
226 };
227
228 // Set flash 64-bit access, prefetch and wait states
229 if sys_clk >= 16_000_000 {
230 FLASH.acr().write(|w| w.set_acc64(true));
231 FLASH.acr().modify(|w| w.set_prften(true));
232 FLASH.acr().modify(|w| w.set_latency(true));
233 }
234
235 RCC.cfgr().modify(|w| {
236 w.set_sw(sw);
237 w.set_hpre(config.ahb_pre.into());
238 w.set_ppre1(config.apb1_pre.into());
239 w.set_ppre2(config.apb2_pre.into());
240 });
241
242 let ahb_freq: u32 = match config.ahb_pre {
243 AHBPrescaler::DIV1 => sys_clk,
244 pre => {
245 let pre: Hpre = pre.into();
246 let pre = 1 << (pre.to_bits() as u32 - 7);
247 sys_clk / pre
248 }
249 };
250
251 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
252 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
253 pre => {
254 let pre: Ppre = pre.into();
255 let pre: u8 = 1 << (pre.to_bits() - 3);
256 let freq = ahb_freq / pre as u32;
257 (freq, freq * 2)
258 }
259 };
260
261 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
262 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
263 pre => {
264 let pre: Ppre = pre.into();
265 let pre: u8 = 1 << (pre.to_bits() - 3);
266 let freq = ahb_freq / pre as u32;
267 (freq, freq * 2)
268 }
269 };
270
271 set_freqs(Clocks {
272 sys: Hertz(sys_clk),
273 ahb1: Hertz(ahb_freq),
274 apb1: Hertz(apb1_freq),
275 apb2: Hertz(apb2_freq),
276 apb1_tim: Hertz(apb1_tim_freq),
277 apb2_tim: Hertz(apb2_tim_freq),
278 });
279}
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
deleted file mode 100644
index 6f1f7458c..000000000
--- a/embassy-stm32/src/rcc/l4.rs
+++ /dev/null
@@ -1,619 +0,0 @@
1use core::marker::PhantomData;
2
3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::regs::Cfgr;
5use stm32_metapac::rcc::vals::{Mcopre, Mcosel};
6
7pub use super::bus::{AHBPrescaler, APBPrescaler};
8use crate::gpio::sealed::AFType;
9use crate::gpio::Speed;
10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
11use crate::pac::{FLASH, RCC};
12use crate::rcc::bd::{BackupDomain, RtcClockSource};
13use crate::rcc::{set_freqs, Clocks};
14use crate::time::Hertz;
15use crate::{peripherals, Peripheral};
16
17/// HSI speed
18pub const HSI_FREQ: Hertz = Hertz(16_000_000);
19
20/// LSI speed
21pub const LSI_FREQ: Hertz = Hertz(32_000);
22
23/// System clock mux source
24#[derive(Clone, Copy)]
25pub enum ClockSrc {
26 MSI(MSIRange),
27 PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
28 HSE(Hertz),
29 HSI16,
30}
31
32/// MSI Clock Range
33///
34/// These ranges control the frequency of the MSI. Internally, these ranges map
35/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
36#[derive(Clone, Copy)]
37pub enum MSIRange {
38 /// Around 100 kHz
39 Range0,
40 /// Around 200 kHz
41 Range1,
42 /// Around 400 kHz
43 Range2,
44 /// Around 800 kHz
45 Range3,
46 /// Around 1 MHz
47 Range4,
48 /// Around 2 MHz
49 Range5,
50 /// Around 4 MHz (reset value)
51 Range6,
52 /// Around 8 MHz
53 Range7,
54 /// Around 16 MHz
55 Range8,
56 /// Around 24 MHz
57 Range9,
58 /// Around 32 MHz
59 Range10,
60 /// Around 48 MHz
61 Range11,
62}
63
64impl Default for MSIRange {
65 fn default() -> MSIRange {
66 MSIRange::Range6
67 }
68}
69
70pub type PLL48Div = PLLClkDiv;
71pub type PLLSAI1RDiv = PLLClkDiv;
72pub type PLLSAI1QDiv = PLLClkDiv;
73pub type PLLSAI1PDiv = PLLClkDiv;
74
75/// PLL divider
76#[derive(Clone, Copy)]
77pub enum PLLDiv {
78 Div2,
79 Div3,
80 Div4,
81}
82
83/// PLL clock input source
84#[derive(Clone, Copy)]
85pub enum PLLSource {
86 HSI16,
87 HSE(Hertz),
88 MSI(MSIRange),
89}
90
91seq_macro::seq!(N in 8..=86 {
92 #[derive(Clone, Copy)]
93 pub enum PLLMul {
94 #(
95 Mul~N,
96 )*
97 }
98
99 impl From<PLLMul> for u8 {
100 fn from(val: PLLMul) -> u8 {
101 match val {
102 #(
103 PLLMul::Mul~N => N,
104 )*
105 }
106 }
107 }
108
109 impl PLLMul {
110 pub fn to_mul(self) -> u32 {
111 match self {
112 #(
113 PLLMul::Mul~N => N,
114 )*
115 }
116 }
117 }
118});
119
120#[derive(Clone, Copy)]
121pub enum PLLClkDiv {
122 Div2,
123 Div4,
124 Div6,
125 Div8,
126}
127
128impl PLLClkDiv {
129 pub fn to_div(self) -> u32 {
130 let val: u8 = self.into();
131 (val as u32 + 1) * 2
132 }
133}
134
135impl From<PLLClkDiv> for u8 {
136 fn from(val: PLLClkDiv) -> u8 {
137 match val {
138 PLLClkDiv::Div2 => 0b00,
139 PLLClkDiv::Div4 => 0b01,
140 PLLClkDiv::Div6 => 0b10,
141 PLLClkDiv::Div8 => 0b11,
142 }
143 }
144}
145
146#[derive(Clone, Copy)]
147pub enum PLLSrcDiv {
148 Div1,
149 Div2,
150 Div3,
151 Div4,
152 Div5,
153 Div6,
154 Div7,
155 Div8,
156}
157
158impl PLLSrcDiv {
159 pub fn to_div(self) -> u32 {
160 let val: u8 = self.into();
161 val as u32 + 1
162 }
163}
164
165impl From<PLLSrcDiv> for u8 {
166 fn from(val: PLLSrcDiv) -> u8 {
167 match val {
168 PLLSrcDiv::Div1 => 0b000,
169 PLLSrcDiv::Div2 => 0b001,
170 PLLSrcDiv::Div3 => 0b010,
171 PLLSrcDiv::Div4 => 0b011,
172 PLLSrcDiv::Div5 => 0b100,
173 PLLSrcDiv::Div6 => 0b101,
174 PLLSrcDiv::Div7 => 0b110,
175 PLLSrcDiv::Div8 => 0b111,
176 }
177 }
178}
179
180impl From<PLLSource> for Pllsrc {
181 fn from(val: PLLSource) -> Pllsrc {
182 match val {
183 PLLSource::HSI16 => Pllsrc::HSI16,
184 PLLSource::HSE(_) => Pllsrc::HSE,
185 PLLSource::MSI(_) => Pllsrc::MSI,
186 }
187 }
188}
189
190impl From<MSIRange> for Msirange {
191 fn from(val: MSIRange) -> Msirange {
192 match val {
193 MSIRange::Range0 => Msirange::RANGE100K,
194 MSIRange::Range1 => Msirange::RANGE200K,
195 MSIRange::Range2 => Msirange::RANGE400K,
196 MSIRange::Range3 => Msirange::RANGE800K,
197 MSIRange::Range4 => Msirange::RANGE1M,
198 MSIRange::Range5 => Msirange::RANGE2M,
199 MSIRange::Range6 => Msirange::RANGE4M,
200 MSIRange::Range7 => Msirange::RANGE8M,
201 MSIRange::Range8 => Msirange::RANGE16M,
202 MSIRange::Range9 => Msirange::RANGE24M,
203 MSIRange::Range10 => Msirange::RANGE32M,
204 MSIRange::Range11 => Msirange::RANGE48M,
205 }
206 }
207}
208
209impl From<MSIRange> for u32 {
210 fn from(val: MSIRange) -> u32 {
211 match val {
212 MSIRange::Range0 => 100_000,
213 MSIRange::Range1 => 200_000,
214 MSIRange::Range2 => 400_000,
215 MSIRange::Range3 => 800_000,
216 MSIRange::Range4 => 1_000_000,
217 MSIRange::Range5 => 2_000_000,
218 MSIRange::Range6 => 4_000_000,
219 MSIRange::Range7 => 8_000_000,
220 MSIRange::Range8 => 16_000_000,
221 MSIRange::Range9 => 24_000_000,
222 MSIRange::Range10 => 32_000_000,
223 MSIRange::Range11 => 48_000_000,
224 }
225 }
226}
227
228/// Clocks configutation
229pub struct Config {
230 pub mux: ClockSrc,
231 pub ahb_pre: AHBPrescaler,
232 pub apb1_pre: APBPrescaler,
233 pub apb2_pre: APBPrescaler,
234 pub pllsai1: Option<(
235 PLLMul,
236 PLLSrcDiv,
237 Option<PLLSAI1RDiv>,
238 Option<PLLSAI1QDiv>,
239 Option<PLLSAI1PDiv>,
240 )>,
241 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
242 pub hsi48: bool,
243 pub rtc_mux: RtcClockSource,
244 pub lse: Option<Hertz>,
245 pub lsi: bool,
246}
247
248impl Default for Config {
249 #[inline]
250 fn default() -> Config {
251 Config {
252 mux: ClockSrc::MSI(MSIRange::Range6),
253 ahb_pre: AHBPrescaler::DIV1,
254 apb1_pre: APBPrescaler::DIV1,
255 apb2_pre: APBPrescaler::DIV1,
256 pllsai1: None,
257 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
258 hsi48: false,
259 rtc_mux: RtcClockSource::LSI,
260 lsi: true,
261 lse: None,
262 }
263 }
264}
265
266pub enum McoClock {
267 DIV1,
268 DIV2,
269 DIV4,
270 DIV8,
271 DIV16,
272}
273
274impl McoClock {
275 fn into_raw(&self) -> Mcopre {
276 match self {
277 McoClock::DIV1 => Mcopre::DIV1,
278 McoClock::DIV2 => Mcopre::DIV2,
279 McoClock::DIV4 => Mcopre::DIV4,
280 McoClock::DIV8 => Mcopre::DIV8,
281 McoClock::DIV16 => Mcopre::DIV16,
282 }
283 }
284}
285
286#[derive(Copy, Clone)]
287pub enum Mco1Source {
288 Disabled,
289 Lse,
290 Lsi,
291 Hse,
292 Hsi16,
293 PllClk,
294 SysClk,
295 Msi,
296 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
297 Hsi48,
298}
299
300impl Default for Mco1Source {
301 fn default() -> Self {
302 Self::Hsi16
303 }
304}
305
306pub trait McoSource {
307 type Raw;
308
309 fn into_raw(&self) -> Self::Raw;
310}
311
312impl McoSource for Mco1Source {
313 type Raw = Mcosel;
314 fn into_raw(&self) -> Self::Raw {
315 match self {
316 Mco1Source::Disabled => Mcosel::NOCLOCK,
317 Mco1Source::Lse => Mcosel::LSE,
318 Mco1Source::Lsi => Mcosel::LSI,
319 Mco1Source::Hse => Mcosel::HSE,
320 Mco1Source::Hsi16 => Mcosel::HSI16,
321 Mco1Source::PllClk => Mcosel::PLL,
322 Mco1Source::SysClk => Mcosel::SYSCLK,
323 Mco1Source::Msi => Mcosel::MSI,
324 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
325 Mco1Source::Hsi48 => Mcosel::HSI48,
326 }
327 }
328}
329
330pub(crate) mod sealed {
331 use stm32_metapac::rcc::vals::Mcopre;
332 pub trait McoInstance {
333 type Source;
334 unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre);
335 }
336}
337
338pub trait McoInstance: sealed::McoInstance + 'static {}
339
340pin_trait!(McoPin, McoInstance);
341
342impl sealed::McoInstance for peripherals::MCO {
343 type Source = Mcosel;
344
345 unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
346 RCC.cfgr().modify(|w| {
347 w.set_mcosel(source);
348 w.set_mcopre(prescaler);
349 });
350
351 match source {
352 Mcosel::HSI16 => {
353 RCC.cr().modify(|w| w.set_hsion(true));
354 while !RCC.cr().read().hsirdy() {}
355 }
356 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
357 Mcosel::HSI48 => {
358 RCC.crrcr().modify(|w| w.set_hsi48on(true));
359 while !RCC.crrcr().read().hsi48rdy() {}
360 }
361 _ => {}
362 }
363 }
364}
365
366impl McoInstance for peripherals::MCO {}
367
368pub struct Mco<'d, T: McoInstance> {
369 phantom: PhantomData<&'d mut T>,
370}
371
372impl<'d, T: McoInstance> Mco<'d, T> {
373 pub fn new(
374 _peri: impl Peripheral<P = T> + 'd,
375 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
376 source: impl McoSource<Raw = T::Source>,
377 prescaler: McoClock,
378 ) -> Self {
379 into_ref!(pin);
380
381 critical_section::with(|_| unsafe {
382 T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
383 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
384 pin.set_speed(Speed::VeryHigh);
385 });
386
387 Self { phantom: PhantomData }
388 }
389}
390
391pub(crate) unsafe fn init(config: Config) {
392 // Switch to MSI to prevent problems with PLL configuration.
393 if !RCC.cr().read().msion() {
394 // Turn on MSI and configure it to 4MHz.
395 RCC.cr().modify(|w| {
396 w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0].
397 w.set_msirange(MSIRange::default().into());
398 w.set_msipllen(false);
399 w.set_msion(true)
400 });
401
402 // Wait until MSI is running
403 while !RCC.cr().read().msirdy() {}
404 }
405 if RCC.cfgr().read().sws() != Sw::MSI {
406 // Set MSI as a clock source, reset prescalers.
407 RCC.cfgr().write_value(Cfgr::default());
408 // Wait for clock switch status bits to change.
409 while RCC.cfgr().read().sws() != Sw::MSI {}
410 }
411
412 BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default()));
413
414 let (sys_clk, sw) = match config.mux {
415 ClockSrc::MSI(range) => {
416 // Enable MSI
417 RCC.cr().write(|w| {
418 let bits: Msirange = range.into();
419 w.set_msirange(bits);
420 w.set_msirgsel(true);
421 w.set_msion(true);
422
423 if let RtcClockSource::LSE = config.rtc_mux {
424 // If LSE is enabled, enable calibration of MSI
425 w.set_msipllen(true);
426 } else {
427 w.set_msipllen(false);
428 }
429 });
430 while !RCC.cr().read().msirdy() {}
431
432 // Enable as clock source for USB, RNG if running at 48 MHz
433 if let MSIRange::Range11 = range {
434 RCC.ccipr().modify(|w| {
435 w.set_clk48sel(0b11);
436 });
437 }
438 (range.into(), Sw::MSI)
439 }
440 ClockSrc::HSI16 => {
441 // Enable HSI16
442 RCC.cr().write(|w| w.set_hsion(true));
443 while !RCC.cr().read().hsirdy() {}
444
445 (HSI_FREQ.0, Sw::HSI16)
446 }
447 ClockSrc::HSE(freq) => {
448 // Enable HSE
449 RCC.cr().write(|w| w.set_hseon(true));
450 while !RCC.cr().read().hserdy() {}
451
452 (freq.0, Sw::HSE)
453 }
454 ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
455 let src_freq = match src {
456 PLLSource::HSE(freq) => {
457 // Enable HSE
458 RCC.cr().write(|w| w.set_hseon(true));
459 while !RCC.cr().read().hserdy() {}
460 freq.0
461 }
462 PLLSource::HSI16 => {
463 // Enable HSI
464 RCC.cr().write(|w| w.set_hsion(true));
465 while !RCC.cr().read().hsirdy() {}
466 HSI_FREQ.0
467 }
468 PLLSource::MSI(range) => {
469 // Enable MSI
470 RCC.cr().write(|w| {
471 let bits: Msirange = range.into();
472 w.set_msirange(bits);
473 w.set_msipllen(false); // should be turned on if LSE is started
474 w.set_msirgsel(true);
475 w.set_msion(true);
476 });
477 while !RCC.cr().read().msirdy() {}
478 range.into()
479 }
480 };
481
482 // Disable PLL
483 RCC.cr().modify(|w| w.set_pllon(false));
484 while RCC.cr().read().pllrdy() {}
485
486 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div();
487
488 #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
489 assert!(freq <= 120_000_000);
490 #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
491 assert!(freq <= 80_000_000);
492
493 RCC.pllcfgr().write(move |w| {
494 w.set_plln(mul.into());
495 w.set_pllm(prediv.into());
496 w.set_pllr(div.into());
497 if let Some(pll48div) = pll48div {
498 w.set_pllq(pll48div.into());
499 w.set_pllqen(true);
500 }
501 w.set_pllsrc(src.into());
502 });
503
504 // Enable as clock source for USB, RNG if PLL48 divisor is provided
505 if let Some(pll48div) = pll48div {
506 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
507 assert!(freq == 48_000_000);
508 RCC.ccipr().modify(|w| {
509 w.set_clk48sel(0b10);
510 });
511 }
512
513 if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
514 RCC.pllsai1cfgr().write(move |w| {
515 w.set_pllsai1n(mul.into());
516 w.set_pllsai1m(prediv.into());
517 if let Some(r_div) = r_div {
518 w.set_pllsai1r(r_div.into());
519 w.set_pllsai1ren(true);
520 }
521 if let Some(q_div) = q_div {
522 w.set_pllsai1q(q_div.into());
523 w.set_pllsai1qen(true);
524 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div();
525 if freq == 48_000_000 {
526 RCC.ccipr().modify(|w| {
527 w.set_clk48sel(0b1);
528 });
529 }
530 }
531 if let Some(p_div) = p_div {
532 w.set_pllsai1pdiv(p_div.into());
533 w.set_pllsai1pen(true);
534 }
535 });
536
537 RCC.cr().modify(|w| w.set_pllsai1on(true));
538 }
539
540 // Enable PLL
541 RCC.cr().modify(|w| w.set_pllon(true));
542 while !RCC.cr().read().pllrdy() {}
543 RCC.pllcfgr().modify(|w| w.set_pllren(true));
544
545 (freq, Sw::PLL)
546 }
547 };
548
549 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
550 if config.hsi48 {
551 RCC.crrcr().modify(|w| w.set_hsi48on(true));
552 while !RCC.crrcr().read().hsi48rdy() {}
553
554 // Enable as clock source for USB, RNG and SDMMC
555 RCC.ccipr().modify(|w| w.set_clk48sel(0));
556 }
557
558 // Set flash wait states
559 FLASH.acr().modify(|w| {
560 w.set_latency(if sys_clk <= 16_000_000 {
561 0b000
562 } else if sys_clk <= 32_000_000 {
563 0b001
564 } else if sys_clk <= 48_000_000 {
565 0b010
566 } else if sys_clk <= 64_000_000 {
567 0b011
568 } else {
569 0b100
570 });
571 });
572
573 RCC.cfgr().modify(|w| {
574 w.set_sw(sw);
575 w.set_hpre(config.ahb_pre.into());
576 w.set_ppre1(config.apb1_pre.into());
577 w.set_ppre2(config.apb2_pre.into());
578 });
579
580 let ahb_freq: u32 = match config.ahb_pre {
581 AHBPrescaler::DIV1 => sys_clk,
582 pre => {
583 let pre: Hpre = pre.into();
584 let pre = 1 << (pre.to_bits() as u32 - 7);
585 sys_clk / pre
586 }
587 };
588
589 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
590 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
591 pre => {
592 let pre: Ppre = pre.into();
593 let pre: u8 = 1 << (pre.to_bits() - 3);
594 let freq = ahb_freq / pre as u32;
595 (freq, freq * 2)
596 }
597 };
598
599 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
600 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
601 pre => {
602 let pre: Ppre = pre.into();
603 let pre: u8 = 1 << (pre.to_bits() - 3);
604 let freq = ahb_freq / pre as u32;
605 (freq, freq * 2)
606 }
607 };
608
609 set_freqs(Clocks {
610 sys: Hertz(sys_clk),
611 ahb1: Hertz(ahb_freq),
612 ahb2: Hertz(ahb_freq),
613 ahb3: Hertz(ahb_freq),
614 apb1: Hertz(apb1_freq),
615 apb2: Hertz(apb2_freq),
616 apb1_tim: Hertz(apb1_tim_freq),
617 apb2_tim: Hertz(apb2_tim_freq),
618 });
619}
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
new file mode 100644
index 000000000..683b47c05
--- /dev/null
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -0,0 +1,441 @@
1use crate::pac::rcc::regs::Cfgr;
2use crate::pac::rcc::vals::Msirgsel;
3pub use crate::pac::rcc::vals::{
4 Clk48sel as Clk48Src, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul,
5 Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
6};
7use crate::pac::{FLASH, RCC};
8use crate::rcc::{set_freqs, Clocks};
9use crate::time::Hertz;
10
11/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13
14#[derive(Clone, Copy)]
15pub struct Pll {
16 /// PLL source
17 pub source: PLLSource,
18
19 /// PLL pre-divider (DIVM).
20 pub prediv: PllPreDiv,
21
22 /// PLL multiplication factor.
23 pub mul: PllMul,
24
25 /// PLL P division factor. If None, PLL P output is disabled.
26 pub divp: Option<PllPDiv>,
27 /// PLL Q division factor. If None, PLL Q output is disabled.
28 pub divq: Option<PllQDiv>,
29 /// PLL R division factor. If None, PLL R output is disabled.
30 pub divr: Option<PllRDiv>,
31}
32
33/// Clocks configutation
34pub struct Config {
35 // base clock sources
36 pub msi: Option<MSIRange>,
37 pub hsi16: bool,
38 pub hse: Option<Hertz>,
39 #[cfg(not(any(stm32l47x, stm32l48x)))]
40 pub hsi48: bool,
41
42 // pll
43 pub pll: Option<Pll>,
44 pub pllsai1: Option<Pll>,
45 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
46 pub pllsai2: Option<Pll>,
47
48 // sysclk, buses.
49 pub mux: ClockSrc,
50 pub ahb_pre: AHBPrescaler,
51 pub apb1_pre: APBPrescaler,
52 pub apb2_pre: APBPrescaler,
53
54 // muxes
55 pub clk48_src: Clk48Src,
56
57 // low speed LSI/LSE/RTC
58 pub ls: super::LsConfig,
59}
60
61impl Default for Config {
62 #[inline]
63 fn default() -> Config {
64 Config {
65 hse: None,
66 hsi16: false,
67 msi: Some(MSIRange::RANGE4M),
68 mux: ClockSrc::MSI,
69 ahb_pre: AHBPrescaler::DIV1,
70 apb1_pre: APBPrescaler::DIV1,
71 apb2_pre: APBPrescaler::DIV1,
72 pll: None,
73 pllsai1: None,
74 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
75 pllsai2: None,
76 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
77 hsi48: true,
78 clk48_src: Clk48Src::HSI48,
79 ls: Default::default(),
80 }
81 }
82}
83
84pub(crate) unsafe fn init(config: Config) {
85 // Switch to MSI to prevent problems with PLL configuration.
86 if !RCC.cr().read().msion() {
87 // Turn on MSI and configure it to 4MHz.
88 RCC.cr().modify(|w| {
89 w.set_msirgsel(Msirgsel::CR);
90 w.set_msirange(MSIRange::RANGE4M);
91 w.set_msipllen(false);
92 w.set_msion(true)
93 });
94
95 // Wait until MSI is running
96 while !RCC.cr().read().msirdy() {}
97 }
98 if RCC.cfgr().read().sws() != ClockSrc::MSI {
99 // Set MSI as a clock source, reset prescalers.
100 RCC.cfgr().write_value(Cfgr::default());
101 // Wait for clock switch status bits to change.
102 while RCC.cfgr().read().sws() != ClockSrc::MSI {}
103 }
104
105 #[cfg(stm32l5)]
106 crate::pac::PWR.cr1().modify(|w| {
107 w.set_vos(crate::pac::pwr::vals::Vos::RANGE0);
108 });
109
110 let rtc = config.ls.init();
111
112 let msi = config.msi.map(|range| {
113 // Enable MSI
114 RCC.cr().write(|w| {
115 w.set_msirange(range);
116 w.set_msirgsel(Msirgsel::CR);
117 w.set_msion(true);
118
119 // If LSE is enabled, enable calibration of MSI
120 w.set_msipllen(config.ls.lse.is_some());
121 });
122 while !RCC.cr().read().msirdy() {}
123
124 // Enable as clock source for USB, RNG if running at 48 MHz
125 if range == MSIRange::RANGE48M {}
126
127 msirange_to_hertz(range)
128 });
129
130 let hsi16 = config.hsi16.then(|| {
131 RCC.cr().write(|w| w.set_hsion(true));
132 while !RCC.cr().read().hsirdy() {}
133
134 HSI_FREQ
135 });
136
137 let hse = config.hse.map(|freq| {
138 RCC.cr().write(|w| w.set_hseon(true));
139 while !RCC.cr().read().hserdy() {}
140
141 freq
142 });
143
144 #[cfg(not(any(stm32l47x, stm32l48x)))]
145 let hsi48 = config.hsi48.then(|| {
146 RCC.crrcr().modify(|w| w.set_hsi48on(true));
147 while !RCC.crrcr().read().hsi48rdy() {}
148
149 Hertz(48_000_000)
150 });
151 #[cfg(any(stm32l47x, stm32l48x))]
152 let hsi48 = None;
153
154 let _plls = [
155 &config.pll,
156 &config.pllsai1,
157 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
158 &config.pllsai2,
159 ];
160
161 // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs.
162 #[cfg(all(stm32l4, not(rcc_l4plus)))]
163 match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
164 Err(()) => panic!("Source must be equal across all enabled PLLs."),
165 Ok(None) => {}
166 Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| {
167 w.set_pllm(prediv);
168 w.set_pllsrc(source);
169 }),
170 };
171
172 // L4+ has shared PLLSRC, check it's equal in all PLLs.
173 #[cfg(any(rcc_l4plus))]
174 match get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
175 Err(()) => panic!("Source must be equal across all enabled PLLs."),
176 Ok(None) => {}
177 Ok(Some(source)) => RCC.pllcfgr().write(|w| {
178 w.set_pllsrc(source);
179 }),
180 };
181
182 let pll_input = PllInput { hse, hsi16, msi };
183 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
184 let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
185 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
186 let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
187
188 let sys_clk = match config.mux {
189 ClockSrc::HSE => hse.unwrap(),
190 ClockSrc::HSI => hsi16.unwrap(),
191 ClockSrc::MSI => msi.unwrap(),
192 #[cfg(rcc_l4)]
193 ClockSrc::PLL1_P => pll._r.unwrap(),
194 #[cfg(not(rcc_l4))]
195 ClockSrc::PLL1_R => pll._r.unwrap(),
196 };
197
198 #[cfg(stm32l4)]
199 RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
200 #[cfg(stm32l5)]
201 RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
202 let _clk48 = match config.clk48_src {
203 Clk48Src::HSI48 => hsi48,
204 Clk48Src::MSI => msi,
205 Clk48Src::PLLSAI1_Q => pllsai1._q,
206 Clk48Src::PLL1_Q => pll._q,
207 };
208
209 #[cfg(rcc_l4plus)]
210 assert!(sys_clk.0 <= 120_000_000);
211 #[cfg(all(stm32l4, not(rcc_l4plus)))]
212 assert!(sys_clk.0 <= 80_000_000);
213
214 // Set flash wait states
215 #[cfg(stm32l4)]
216 FLASH.acr().modify(|w| {
217 w.set_latency(match sys_clk.0 {
218 0..=16_000_000 => 0,
219 0..=32_000_000 => 1,
220 0..=48_000_000 => 2,
221 0..=64_000_000 => 3,
222 _ => 4,
223 })
224 });
225 // VCORE Range 0 (performance), others TODO
226 #[cfg(stm32l5)]
227 FLASH.acr().modify(|w| {
228 w.set_latency(match sys_clk.0 {
229 0..=20_000_000 => 0,
230 0..=40_000_000 => 1,
231 0..=60_000_000 => 2,
232 0..=80_000_000 => 3,
233 0..=100_000_000 => 4,
234 _ => 5,
235 })
236 });
237
238 RCC.cfgr().modify(|w| {
239 w.set_sw(config.mux);
240 w.set_hpre(config.ahb_pre);
241 w.set_ppre1(config.apb1_pre);
242 w.set_ppre2(config.apb2_pre);
243 });
244 while RCC.cfgr().read().sws() != config.mux {}
245
246 let ahb_freq = sys_clk / config.ahb_pre;
247
248 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
249 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
250 pre => {
251 let freq = ahb_freq / pre;
252 (freq, freq * 2u32)
253 }
254 };
255
256 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
257 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
258 pre => {
259 let freq = ahb_freq / pre;
260 (freq, freq * 2u32)
261 }
262 };
263
264 set_freqs(Clocks {
265 sys: sys_clk,
266 hclk1: ahb_freq,
267 hclk2: ahb_freq,
268 hclk3: ahb_freq,
269 pclk1: apb1_freq,
270 pclk2: apb2_freq,
271 pclk1_tim: apb1_tim_freq,
272 pclk2_tim: apb2_tim_freq,
273 #[cfg(rcc_l4)]
274 hsi: None,
275 #[cfg(rcc_l4)]
276 lse: None,
277 #[cfg(rcc_l4)]
278 pllsai1_p: None,
279 #[cfg(rcc_l4)]
280 pllsai2_p: None,
281 #[cfg(rcc_l4)]
282 pll1_p: None,
283 #[cfg(rcc_l4)]
284 pll1_q: None,
285 #[cfg(rcc_l4)]
286 sai1_extclk: None,
287 #[cfg(rcc_l4)]
288 sai2_extclk: None,
289 rtc,
290 });
291}
292
293fn msirange_to_hertz(range: MSIRange) -> Hertz {
294 match range {
295 MSIRange::RANGE100K => Hertz(100_000),
296 MSIRange::RANGE200K => Hertz(200_000),
297 MSIRange::RANGE400K => Hertz(400_000),
298 MSIRange::RANGE800K => Hertz(800_000),
299 MSIRange::RANGE1M => Hertz(1_000_000),
300 MSIRange::RANGE2M => Hertz(2_000_000),
301 MSIRange::RANGE4M => Hertz(4_000_000),
302 MSIRange::RANGE8M => Hertz(8_000_000),
303 MSIRange::RANGE16M => Hertz(16_000_000),
304 MSIRange::RANGE24M => Hertz(24_000_000),
305 MSIRange::RANGE32M => Hertz(32_000_000),
306 MSIRange::RANGE48M => Hertz(48_000_000),
307 _ => unreachable!(),
308 }
309}
310
311#[allow(unused)]
312fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
313 let Some(x) = iter.next() else { return Ok(None) };
314 if !iter.all(|y| y == x) {
315 return Err(());
316 }
317 return Ok(Some(x));
318}
319
320struct PllInput {
321 hsi16: Option<Hertz>,
322 hse: Option<Hertz>,
323 msi: Option<Hertz>,
324}
325
326#[derive(Default)]
327struct PllOutput {
328 _p: Option<Hertz>,
329 _q: Option<Hertz>,
330 _r: Option<Hertz>,
331}
332
333#[derive(PartialEq, Eq, Clone, Copy)]
334enum PllInstance {
335 Pll,
336 Pllsai1,
337 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
338 Pllsai2,
339}
340
341fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
342 // Disable PLL
343 match instance {
344 PllInstance::Pll => {
345 RCC.cr().modify(|w| w.set_pllon(false));
346 while RCC.cr().read().pllrdy() {}
347 }
348 PllInstance::Pllsai1 => {
349 RCC.cr().modify(|w| w.set_pllsai1on(false));
350 while RCC.cr().read().pllsai1rdy() {}
351 }
352 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
353 PllInstance::Pllsai2 => {
354 RCC.cr().modify(|w| w.set_pllsai2on(false));
355 while RCC.cr().read().pllsai2rdy() {}
356 }
357 }
358
359 let Some(pll) = config else { return PllOutput::default() };
360
361 let pll_src = match pll.source {
362 PLLSource::NONE => panic!("must not select PLL source as NONE"),
363 PLLSource::HSE => input.hse,
364 PLLSource::HSI => input.hsi16,
365 PLLSource::MSI => input.msi,
366 };
367
368 let pll_src = pll_src.unwrap();
369
370 let vco_freq = pll_src / pll.prediv * pll.mul;
371
372 let p = pll.divp.map(|div| vco_freq / div);
373 let q = pll.divq.map(|div| vco_freq / div);
374 let r = pll.divr.map(|div| vco_freq / div);
375
376 #[cfg(stm32l5)]
377 if instance == PllInstance::Pllsai2 {
378 assert!(q.is_none(), "PLLSAI2_Q is not available on L5");
379 assert!(r.is_none(), "PLLSAI2_R is not available on L5");
380 }
381
382 macro_rules! write_fields {
383 ($w:ident) => {
384 $w.set_plln(pll.mul);
385 if let Some(divp) = pll.divp {
386 $w.set_pllp(divp);
387 $w.set_pllpen(true);
388 }
389 if let Some(divq) = pll.divq {
390 $w.set_pllq(divq);
391 $w.set_pllqen(true);
392 }
393 if let Some(divr) = pll.divr {
394 $w.set_pllr(divr);
395 $w.set_pllren(true);
396 }
397 };
398 }
399
400 match instance {
401 PllInstance::Pll => RCC.pllcfgr().write(|w| {
402 w.set_pllm(pll.prediv);
403 w.set_pllsrc(pll.source);
404 write_fields!(w);
405 }),
406 PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
407 #[cfg(any(rcc_l4plus, stm32l5))]
408 w.set_pllm(pll.prediv);
409 #[cfg(stm32l5)]
410 w.set_pllsrc(pll.source);
411 write_fields!(w);
412 }),
413 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
414 PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| {
415 #[cfg(any(rcc_l4plus, stm32l5))]
416 w.set_pllm(pll.prediv);
417 #[cfg(stm32l5)]
418 w.set_pllsrc(pll.source);
419 write_fields!(w);
420 }),
421 }
422
423 // Enable PLL
424 match instance {
425 PllInstance::Pll => {
426 RCC.cr().modify(|w| w.set_pllon(true));
427 while !RCC.cr().read().pllrdy() {}
428 }
429 PllInstance::Pllsai1 => {
430 RCC.cr().modify(|w| w.set_pllsai1on(true));
431 while !RCC.cr().read().pllsai1rdy() {}
432 }
433 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
434 PllInstance::Pllsai2 => {
435 RCC.cr().modify(|w| w.set_pllsai2on(true));
436 while !RCC.cr().read().pllsai2rdy() {}
437 }
438 }
439
440 PllOutput { _p: p, _q: q, _r: r }
441}
diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs
deleted file mode 100644
index 652bdcb7b..000000000
--- a/embassy-stm32/src/rcc/l5.rs
+++ /dev/null
@@ -1,443 +0,0 @@
1use stm32_metapac::PWR;
2
3pub use super::bus::{AHBPrescaler, APBPrescaler};
4use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
5use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz;
8
9/// HSI speed
10pub const HSI_FREQ: Hertz = Hertz(16_000_000);
11
12/// LSI speed
13pub const LSI_FREQ: Hertz = Hertz(32_000);
14
15/// System clock mux source
16#[derive(Clone, Copy)]
17pub enum ClockSrc {
18 MSI(MSIRange),
19 PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
20 HSE(Hertz),
21 HSI16,
22}
23
24/// MSI Clock Range
25///
26/// These ranges control the frequency of the MSI. Internally, these ranges map
27/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
28#[derive(Clone, Copy)]
29pub enum MSIRange {
30 /// Around 100 kHz
31 Range0,
32 /// Around 200 kHz
33 Range1,
34 /// Around 400 kHz
35 Range2,
36 /// Around 800 kHz
37 Range3,
38 /// Around 1 MHz
39 Range4,
40 /// Around 2 MHz
41 Range5,
42 /// Around 4 MHz (reset value)
43 Range6,
44 /// Around 8 MHz
45 Range7,
46 /// Around 16 MHz
47 Range8,
48 /// Around 24 MHz
49 Range9,
50 /// Around 32 MHz
51 Range10,
52 /// Around 48 MHz
53 Range11,
54}
55
56impl Default for MSIRange {
57 fn default() -> MSIRange {
58 MSIRange::Range6
59 }
60}
61
62pub type PLL48Div = PLLClkDiv;
63pub type PLLSAI1RDiv = PLLClkDiv;
64pub type PLLSAI1QDiv = PLLClkDiv;
65pub type PLLSAI1PDiv = PLLClkDiv;
66
67/// PLL divider
68#[derive(Clone, Copy)]
69pub enum PLLDiv {
70 Div2,
71 Div3,
72 Div4,
73}
74
75/// PLL clock input source
76#[derive(Clone, Copy)]
77pub enum PLLSource {
78 HSI16,
79 HSE(Hertz),
80 MSI(MSIRange),
81}
82
83seq_macro::seq!(N in 8..=86 {
84 #[derive(Clone, Copy)]
85 pub enum PLLMul {
86 #(
87 Mul~N,
88 )*
89 }
90
91 impl From<PLLMul> for u8 {
92 fn from(val: PLLMul) -> u8 {
93 match val {
94 #(
95 PLLMul::Mul~N => N,
96 )*
97 }
98 }
99 }
100
101 impl PLLMul {
102 pub fn to_mul(self) -> u32 {
103 match self {
104 #(
105 PLLMul::Mul~N => N,
106 )*
107 }
108 }
109 }
110});
111
112#[derive(Clone, Copy)]
113pub enum PLLClkDiv {
114 Div2,
115 Div4,
116 Div6,
117 Div8,
118}
119
120impl PLLClkDiv {
121 pub fn to_div(self) -> u32 {
122 let val: u8 = self.into();
123 (val as u32 + 1) * 2
124 }
125}
126
127impl From<PLLClkDiv> for u8 {
128 fn from(val: PLLClkDiv) -> u8 {
129 match val {
130 PLLClkDiv::Div2 => 0b00,
131 PLLClkDiv::Div4 => 0b01,
132 PLLClkDiv::Div6 => 0b10,
133 PLLClkDiv::Div8 => 0b11,
134 }
135 }
136}
137
138#[derive(Clone, Copy)]
139pub enum PLLSrcDiv {
140 Div1,
141 Div2,
142 Div3,
143 Div4,
144 Div5,
145 Div6,
146 Div7,
147 Div8,
148}
149
150impl PLLSrcDiv {
151 pub fn to_div(self) -> u32 {
152 let val: u8 = self.into();
153 val as u32 + 1
154 }
155}
156
157impl From<PLLSrcDiv> for u8 {
158 fn from(val: PLLSrcDiv) -> u8 {
159 match val {
160 PLLSrcDiv::Div1 => 0b000,
161 PLLSrcDiv::Div2 => 0b001,
162 PLLSrcDiv::Div3 => 0b010,
163 PLLSrcDiv::Div4 => 0b011,
164 PLLSrcDiv::Div5 => 0b100,
165 PLLSrcDiv::Div6 => 0b101,
166 PLLSrcDiv::Div7 => 0b110,
167 PLLSrcDiv::Div8 => 0b111,
168 }
169 }
170}
171
172impl From<PLLSource> for Pllsrc {
173 fn from(val: PLLSource) -> Pllsrc {
174 match val {
175 PLLSource::HSI16 => Pllsrc::HSI16,
176 PLLSource::HSE(_) => Pllsrc::HSE,
177 PLLSource::MSI(_) => Pllsrc::MSI,
178 }
179 }
180}
181
182impl From<MSIRange> for Msirange {
183 fn from(val: MSIRange) -> Msirange {
184 match val {
185 MSIRange::Range0 => Msirange::RANGE100K,
186 MSIRange::Range1 => Msirange::RANGE200K,
187 MSIRange::Range2 => Msirange::RANGE400K,
188 MSIRange::Range3 => Msirange::RANGE800K,
189 MSIRange::Range4 => Msirange::RANGE1M,
190 MSIRange::Range5 => Msirange::RANGE2M,
191 MSIRange::Range6 => Msirange::RANGE4M,
192 MSIRange::Range7 => Msirange::RANGE8M,
193 MSIRange::Range8 => Msirange::RANGE16M,
194 MSIRange::Range9 => Msirange::RANGE24M,
195 MSIRange::Range10 => Msirange::RANGE32M,
196 MSIRange::Range11 => Msirange::RANGE48M,
197 }
198 }
199}
200
201impl From<MSIRange> for u32 {
202 fn from(val: MSIRange) -> u32 {
203 match val {
204 MSIRange::Range0 => 100_000,
205 MSIRange::Range1 => 200_000,
206 MSIRange::Range2 => 400_000,
207 MSIRange::Range3 => 800_000,
208 MSIRange::Range4 => 1_000_000,
209 MSIRange::Range5 => 2_000_000,
210 MSIRange::Range6 => 4_000_000,
211 MSIRange::Range7 => 8_000_000,
212 MSIRange::Range8 => 16_000_000,
213 MSIRange::Range9 => 24_000_000,
214 MSIRange::Range10 => 32_000_000,
215 MSIRange::Range11 => 48_000_000,
216 }
217 }
218}
219
220/// Clocks configutation
221pub struct Config {
222 pub mux: ClockSrc,
223 pub ahb_pre: AHBPrescaler,
224 pub apb1_pre: APBPrescaler,
225 pub apb2_pre: APBPrescaler,
226 pub pllsai1: Option<(
227 PLLMul,
228 PLLSrcDiv,
229 Option<PLLSAI1RDiv>,
230 Option<PLLSAI1QDiv>,
231 Option<PLLSAI1PDiv>,
232 )>,
233 pub hsi48: bool,
234}
235
236impl Default for Config {
237 #[inline]
238 fn default() -> Config {
239 Config {
240 mux: ClockSrc::MSI(MSIRange::Range6),
241 ahb_pre: AHBPrescaler::DIV1,
242 apb1_pre: APBPrescaler::DIV1,
243 apb2_pre: APBPrescaler::DIV1,
244 pllsai1: None,
245 hsi48: false,
246 }
247 }
248}
249
250pub(crate) unsafe fn init(config: Config) {
251 PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0));
252 let (sys_clk, sw) = match config.mux {
253 ClockSrc::MSI(range) => {
254 // Enable MSI
255 RCC.cr().write(|w| {
256 let bits: Msirange = range.into();
257 w.set_msirange(bits);
258 w.set_msipllen(false);
259 w.set_msirgsel(true);
260 w.set_msion(true);
261 });
262 while !RCC.cr().read().msirdy() {}
263
264 // Enable as clock source for USB, RNG if running at 48 MHz
265 if let MSIRange::Range11 = range {
266 RCC.ccipr1().modify(|w| {
267 w.set_clk48msel(0b11);
268 });
269 }
270 (range.into(), Sw::MSI)
271 }
272 ClockSrc::HSI16 => {
273 // Enable HSI16
274 RCC.cr().write(|w| w.set_hsion(true));
275 while !RCC.cr().read().hsirdy() {}
276
277 (HSI_FREQ.0, Sw::HSI16)
278 }
279 ClockSrc::HSE(freq) => {
280 // Enable HSE
281 RCC.cr().write(|w| w.set_hseon(true));
282 while !RCC.cr().read().hserdy() {}
283
284 (freq.0, Sw::HSE)
285 }
286 ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
287 let src_freq = match src {
288 PLLSource::HSE(freq) => {
289 // Enable HSE
290 RCC.cr().write(|w| w.set_hseon(true));
291 while !RCC.cr().read().hserdy() {}
292 freq.0
293 }
294 PLLSource::HSI16 => {
295 // Enable HSI
296 RCC.cr().write(|w| w.set_hsion(true));
297 while !RCC.cr().read().hsirdy() {}
298 HSI_FREQ.0
299 }
300 PLLSource::MSI(range) => {
301 // Enable MSI
302 RCC.cr().write(|w| {
303 let bits: Msirange = range.into();
304 w.set_msirange(bits);
305 w.set_msipllen(false); // should be turned on if LSE is started
306 w.set_msirgsel(true);
307 w.set_msion(true);
308 });
309 while !RCC.cr().read().msirdy() {}
310 range.into()
311 }
312 };
313
314 // Disable PLL
315 RCC.cr().modify(|w| w.set_pllon(false));
316 while RCC.cr().read().pllrdy() {}
317
318 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div();
319
320 RCC.pllcfgr().write(move |w| {
321 w.set_plln(mul.into());
322 w.set_pllm(prediv.into());
323 w.set_pllr(div.into());
324 if let Some(pll48div) = pll48div {
325 w.set_pllq(pll48div.into());
326 w.set_pllqen(true);
327 }
328 w.set_pllsrc(src.into());
329 });
330
331 // Enable as clock source for USB, RNG if PLL48 divisor is provided
332 if let Some(pll48div) = pll48div {
333 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
334 assert!(freq == 48_000_000);
335 RCC.ccipr1().modify(|w| {
336 w.set_clk48msel(0b10);
337 });
338 }
339
340 if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
341 RCC.pllsai1cfgr().write(move |w| {
342 w.set_pllsai1n(mul.into());
343 w.set_pllsai1m(prediv.into());
344 if let Some(r_div) = r_div {
345 w.set_pllsai1r(r_div.into());
346 w.set_pllsai1ren(true);
347 }
348 if let Some(q_div) = q_div {
349 w.set_pllsai1q(q_div.into());
350 w.set_pllsai1qen(true);
351 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div();
352 if freq == 48_000_000 {
353 RCC.ccipr1().modify(|w| {
354 w.set_clk48msel(0b1);
355 });
356 }
357 }
358 if let Some(p_div) = p_div {
359 w.set_pllsai1pdiv(p_div.into());
360 w.set_pllsai1pen(true);
361 }
362 });
363
364 RCC.cr().modify(|w| w.set_pllsai1on(true));
365 }
366
367 // Enable PLL
368 RCC.cr().modify(|w| w.set_pllon(true));
369 while !RCC.cr().read().pllrdy() {}
370 RCC.pllcfgr().modify(|w| w.set_pllren(true));
371
372 (freq, Sw::PLL)
373 }
374 };
375
376 if config.hsi48 {
377 RCC.crrcr().modify(|w| w.set_hsi48on(true));
378 while !RCC.crrcr().read().hsi48rdy() {}
379
380 // Enable as clock source for USB, RNG and SDMMC
381 RCC.ccipr1().modify(|w| w.set_clk48msel(0));
382 }
383
384 // Set flash wait states
385 // VCORE Range 0 (performance), others TODO
386 FLASH.acr().modify(|w| {
387 w.set_latency(match sys_clk {
388 0..=20_000_000 => 0,
389 0..=40_000_000 => 1,
390 0..=60_000_000 => 2,
391 0..=80_000_000 => 3,
392 0..=100_000_000 => 4,
393 _ => 5,
394 })
395 });
396
397 RCC.cfgr().modify(|w| {
398 w.set_sw(sw);
399 w.set_hpre(config.ahb_pre.into());
400 w.set_ppre1(config.apb1_pre.into());
401 w.set_ppre2(config.apb2_pre.into());
402 });
403
404 let ahb_freq: u32 = match config.ahb_pre {
405 AHBPrescaler::DIV1 => sys_clk,
406 pre => {
407 let pre: Hpre = pre.into();
408 let pre = 1 << (pre.to_bits() as u32 - 7);
409 sys_clk / pre
410 }
411 };
412
413 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
414 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
415 pre => {
416 let pre: Ppre = pre.into();
417 let pre: u8 = 1 << (pre.to_bits() - 3);
418 let freq = ahb_freq / pre as u32;
419 (freq, freq * 2)
420 }
421 };
422
423 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
424 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
425 pre => {
426 let pre: Ppre = pre.into();
427 let pre: u8 = 1 << (pre.to_bits() - 3);
428 let freq = ahb_freq / pre as u32;
429 (freq, freq * 2)
430 }
431 };
432
433 set_freqs(Clocks {
434 sys: Hertz(sys_clk),
435 ahb1: Hertz(ahb_freq),
436 ahb2: Hertz(ahb_freq),
437 ahb3: Hertz(ahb_freq),
438 apb1: Hertz(apb1_freq),
439 apb2: Hertz(apb2_freq),
440 apb1_tim: Hertz(apb1_tim_freq),
441 apb2_tim: Hertz(apb2_tim_freq),
442 });
443}
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index 2453ed821..eaaf8071c 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -4,14 +4,19 @@ use embassy_hal_internal::into_ref;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::sealed::AFType;
6use crate::gpio::Speed; 6use crate::gpio::Speed;
7pub use crate::pac::rcc::vals::{Mco1 as Mco1Source, Mco2 as Mco2Source}; 7#[cfg(not(stm32f1))]
8pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
9#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
10pub use crate::pac::rcc::vals::Mcosel as McoSource;
11#[cfg(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7))]
12pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
8use crate::pac::RCC; 13use crate::pac::RCC;
9use crate::{peripherals, Peripheral}; 14use crate::{peripherals, Peripheral};
10 15
11pub(crate) mod sealed { 16pub(crate) mod sealed {
12 pub trait McoInstance { 17 pub trait McoInstance {
13 type Source; 18 type Source;
14 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8); 19 unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler);
15 } 20 }
16} 21}
17 22
@@ -24,9 +29,15 @@ macro_rules! impl_peri {
24 impl sealed::McoInstance for peripherals::$peri { 29 impl sealed::McoInstance for peripherals::$peri {
25 type Source = $source; 30 type Source = $source;
26 31
27 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) { 32 unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) {
28 RCC.cfgr().modify(|w| { 33 #[cfg(not(any(stm32u5, stm32wba)))]
34 let r = RCC.cfgr();
35 #[cfg(any(stm32u5, stm32wba))]
36 let r = RCC.cfgr1();
37
38 r.modify(|w| {
29 w.$set_source(source); 39 w.$set_source(source);
40 #[cfg(not(stm32f1))]
30 w.$set_prescaler(prescaler); 41 w.$set_prescaler(prescaler);
31 }); 42 });
32 } 43 }
@@ -36,8 +47,16 @@ macro_rules! impl_peri {
36 }; 47 };
37} 48}
38 49
39impl_peri!(MCO1, Mco1Source, set_mco1, set_mco1pre); 50#[cfg(any(rcc_c0, rcc_g0))]
40impl_peri!(MCO2, Mco2Source, set_mco2, set_mco2pre); 51#[allow(unused_imports)]
52use self::{McoSource as Mco1Source, McoSource as Mco2Source};
53
54#[cfg(mco)]
55impl_peri!(MCO, McoSource, set_mcosel, set_mcopre);
56#[cfg(mco1)]
57impl_peri!(MCO1, Mco1Source, set_mco1sel, set_mco1pre);
58#[cfg(mco2)]
59impl_peri!(MCO2, Mco2Source, set_mco2sel, set_mco2pre);
41 60
42pub struct Mco<'d, T: McoInstance> { 61pub struct Mco<'d, T: McoInstance> {
43 phantom: PhantomData<&'d mut T>, 62 phantom: PhantomData<&'d mut T>,
@@ -45,23 +64,20 @@ pub struct Mco<'d, T: McoInstance> {
45 64
46impl<'d, T: McoInstance> Mco<'d, T> { 65impl<'d, T: McoInstance> Mco<'d, T> {
47 /// Create a new MCO instance. 66 /// Create a new MCO instance.
48 ///
49 /// `prescaler` must be between 1 and 15.
50 pub fn new( 67 pub fn new(
51 _peri: impl Peripheral<P = T> + 'd, 68 _peri: impl Peripheral<P = T> + 'd,
52 pin: impl Peripheral<P = impl McoPin<T>> + 'd, 69 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
53 source: T::Source, 70 source: T::Source,
54 prescaler: u8, 71 #[cfg(not(stm32f1))] prescaler: McoPrescaler,
55 ) -> Self { 72 ) -> Self {
56 into_ref!(pin); 73 into_ref!(pin);
57 74
58 assert!(
59 1 <= prescaler && prescaler <= 15,
60 "Mco prescaler must be between 1 and 15. Refer to the reference manual for more information."
61 );
62
63 critical_section::with(|_| unsafe { 75 critical_section::with(|_| unsafe {
64 T::apply_clock_settings(source, prescaler); 76 T::apply_clock_settings(
77 source,
78 #[cfg(not(stm32f1))]
79 prescaler,
80 );
65 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 81 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
66 pin.set_speed(Speed::VeryHigh); 82 pin.set_speed(Speed::VeryHigh);
67 }); 83 });
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 9ccf2ac4f..49174b27f 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -2,38 +2,33 @@
2 2
3use core::mem::MaybeUninit; 3use core::mem::MaybeUninit;
4 4
5pub use crate::rcc::bd::RtcClockSource;
6use crate::time::Hertz; 5use crate::time::Hertz;
7 6
8pub(crate) mod bd; 7mod bd;
9mod bus;
10#[cfg(any(stm32h5, stm32h7))]
11mod mco; 8mod mco;
12#[cfg(any(stm32h5, stm32h7))] 9pub use bd::*;
13pub use mco::*; 10pub use mco::*;
14 11
15#[cfg_attr(rcc_f0, path = "f0.rs")] 12#[cfg_attr(rcc_f0, path = "f0.rs")]
16#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")] 13#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")]
17#[cfg_attr(rcc_f2, path = "f2.rs")] 14#[cfg_attr(rcc_f2, path = "f2.rs")]
18#[cfg_attr(any(rcc_f3, rcc_f3_v2), path = "f3.rs")] 15#[cfg_attr(any(rcc_f3, rcc_f3_v2), path = "f3.rs")]
19#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")] 16#[cfg_attr(any(rcc_f4, rcc_f410, rcc_f7), path = "f4f7.rs")]
20#[cfg_attr(rcc_f7, path = "f7.rs")]
21#[cfg_attr(rcc_c0, path = "c0.rs")] 17#[cfg_attr(rcc_c0, path = "c0.rs")]
22#[cfg_attr(rcc_g0, path = "g0.rs")] 18#[cfg_attr(rcc_g0, path = "g0.rs")]
23#[cfg_attr(rcc_g4, path = "g4.rs")] 19#[cfg_attr(rcc_g4, path = "g4.rs")]
24#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab), path = "h.rs")] 20#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
25#[cfg_attr(rcc_l0, path = "l0.rs")] 21#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")]
26#[cfg_attr(rcc_l1, path = "l1.rs")] 22#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5), path = "l4l5.rs")]
27#[cfg_attr(rcc_l4, path = "l4.rs")]
28#[cfg_attr(rcc_l5, path = "l5.rs")]
29#[cfg_attr(rcc_u5, path = "u5.rs")] 23#[cfg_attr(rcc_u5, path = "u5.rs")]
30#[cfg_attr(rcc_wb, path = "wb.rs")] 24#[cfg_attr(rcc_wb, path = "wb.rs")]
31#[cfg_attr(rcc_wba, path = "wba.rs")] 25#[cfg_attr(rcc_wba, path = "wba.rs")]
32#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")] 26#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
33mod _version; 27mod _version;
34pub use _version::*;
35#[cfg(feature = "low-power")] 28#[cfg(feature = "low-power")]
36use atomic_polyfill::{AtomicU32, Ordering}; 29use core::sync::atomic::{AtomicU32, Ordering};
30
31pub use _version::*;
37 32
38// Model Clock Configuration 33// Model Clock Configuration
39// 34//
@@ -51,44 +46,107 @@ pub struct Clocks {
51 pub sys: Hertz, 46 pub sys: Hertz,
52 47
53 // APB 48 // APB
54 pub apb1: Hertz, 49 pub pclk1: Hertz,
55 pub apb1_tim: Hertz, 50 pub pclk1_tim: Hertz,
56 #[cfg(not(any(rcc_c0, rcc_g0)))] 51 #[cfg(not(any(rcc_c0, rcc_g0)))]
57 pub apb2: Hertz, 52 pub pclk2: Hertz,
58 #[cfg(not(any(rcc_c0, rcc_g0)))] 53 #[cfg(not(any(rcc_c0, rcc_g0)))]
59 pub apb2_tim: Hertz, 54 pub pclk2_tim: Hertz,
60 #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5))] 55 #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))]
61 pub apb3: Hertz, 56 pub pclk3: Hertz,
62 #[cfg(any(rcc_h7, rcc_h7ab))] 57 #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab, stm32h5))]
63 pub apb4: Hertz, 58 pub pclk4: Hertz,
64 #[cfg(any(rcc_wba))] 59 #[cfg(any(rcc_wba))]
65 pub apb7: Hertz, 60 pub pclk7: Hertz,
66 61
67 // AHB 62 // AHB
68 pub ahb1: Hertz, 63 pub hclk1: Hertz,
69 #[cfg(any( 64 #[cfg(any(
70 rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, 65 rcc_l4,
71 rcc_wba, rcc_wl5, rcc_wle 66 rcc_l4plus,
67 rcc_l5,
68 rcc_f2,
69 rcc_f4,
70 rcc_f410,
71 rcc_f7,
72 rcc_h5,
73 rcc_h50,
74 rcc_h7,
75 rcc_h7rm0433,
76 rcc_h7ab,
77 rcc_g4,
78 rcc_u5,
79 rcc_wb,
80 rcc_wba,
81 rcc_wl5,
82 rcc_wle
72 ))] 83 ))]
73 pub ahb2: Hertz, 84 pub hclk2: Hertz,
74 #[cfg(any( 85 #[cfg(any(
75 rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5, 86 rcc_l4,
87 rcc_l4plus,
88 rcc_l5,
89 rcc_f2,
90 rcc_f4,
91 rcc_f410,
92 rcc_f7,
93 rcc_h5,
94 rcc_h50,
95 rcc_h7,
96 rcc_h7rm0433,
97 rcc_h7ab,
98 rcc_u5,
99 rcc_wb,
100 rcc_wl5,
76 rcc_wle 101 rcc_wle
77 ))] 102 ))]
78 pub ahb3: Hertz, 103 pub hclk3: Hertz,
79 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))] 104 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))]
80 pub ahb4: Hertz, 105 pub hclk4: Hertz,
81
82 #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
83 pub pll48: Option<Hertz>,
84 106
85 #[cfg(all(rcc_f4, not(stm32f410)))] 107 #[cfg(all(rcc_f4, not(stm32f410)))]
86 pub plli2s: Option<Hertz>, 108 pub plli2s1_q: Option<Hertz>,
109 #[cfg(all(rcc_f4, not(stm32f410)))]
110 pub plli2s1_r: Option<Hertz>,
87 111
112 #[cfg(rcc_l4)]
113 pub pllsai1_p: Option<Hertz>,
114 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
115 pub pllsai1_q: Option<Hertz>,
88 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 116 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
89 pub pllsai: Option<Hertz>, 117 pub pllsai1_r: Option<Hertz>,
118 #[cfg(rcc_l4)]
119 pub pllsai2_p: Option<Hertz>,
120
121 #[cfg(any(stm32g4, rcc_l4))]
122 pub pll1_p: Option<Hertz>,
123 #[cfg(any(stm32h5, stm32h7, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_l4))]
124 pub pll1_q: Option<Hertz>,
125 #[cfg(any(stm32h5, stm32h7))]
126 pub pll2_p: Option<Hertz>,
127 #[cfg(any(stm32h5, stm32h7))]
128 pub pll2_q: Option<Hertz>,
129 #[cfg(any(stm32h5, stm32h7))]
130 pub pll2_r: Option<Hertz>,
131 #[cfg(any(stm32h5, stm32h7))]
132 pub pll3_p: Option<Hertz>,
133 #[cfg(any(stm32h5, stm32h7))]
134 pub pll3_q: Option<Hertz>,
135 #[cfg(any(stm32h5, stm32h7))]
136 pub pll3_r: Option<Hertz>,
90 137
91 #[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))] 138 #[cfg(any(
139 rcc_f1,
140 rcc_f100,
141 rcc_f1cl,
142 rcc_h5,
143 rcc_h50,
144 rcc_h7,
145 rcc_h7rm0433,
146 rcc_h7ab,
147 rcc_f3,
148 rcc_g4
149 ))]
92 pub adc: Option<Hertz>, 150 pub adc: Option<Hertz>,
93 151
94 #[cfg(any(rcc_f3, rcc_g4))] 152 #[cfg(any(rcc_f3, rcc_g4))]
@@ -97,13 +155,33 @@ pub struct Clocks {
97 #[cfg(stm32f334)] 155 #[cfg(stm32f334)]
98 pub hrtim: Option<Hertz>, 156 pub hrtim: Option<Hertz>,
99 157
100 #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7))]
101 /// Set only if the lsi or lse is configured, indicates stop is supported
102 pub rtc: Option<Hertz>, 158 pub rtc: Option<Hertz>,
103 159
104 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 160 #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))]
105 /// Set if the hse is configured, indicates stop is not supported 161 pub hsi: Option<Hertz>,
106 pub rtc_hse: Option<Hertz>, 162 #[cfg(stm32h5)]
163 pub hsi48: Option<Hertz>,
164 #[cfg(stm32h5)]
165 pub lsi: Option<Hertz>,
166 #[cfg(any(stm32h5, stm32h7))]
167 pub csi: Option<Hertz>,
168
169 #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))]
170 pub lse: Option<Hertz>,
171 #[cfg(any(stm32h5, stm32h7))]
172 pub hse: Option<Hertz>,
173
174 #[cfg(stm32h5)]
175 pub audioclk: Option<Hertz>,
176 #[cfg(any(stm32h5, stm32h7))]
177 pub per: Option<Hertz>,
178
179 #[cfg(stm32h7)]
180 pub rcc_pclk_d3: Option<Hertz>,
181 #[cfg(rcc_l4)]
182 pub sai1_extclk: Option<Hertz>,
183 #[cfg(rcc_l4)]
184 pub sai2_extclk: Option<Hertz>,
107} 185}
108 186
109#[cfg(feature = "low-power")] 187#[cfg(feature = "low-power")]
@@ -111,20 +189,22 @@ static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0);
111 189
112#[cfg(feature = "low-power")] 190#[cfg(feature = "low-power")]
113pub fn low_power_ready() -> bool { 191pub fn low_power_ready() -> bool {
114 trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst)); 192 // trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst));
115
116 CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 193 CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0
117} 194}
118 195
119#[cfg(feature = "low-power")] 196#[cfg(feature = "low-power")]
120pub(crate) fn clock_refcount_add() { 197pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) {
121 // We don't check for overflow because constructing more than u32 peripherals is unlikely 198 // We don't check for overflow because constructing more than u32 peripherals is unlikely
122 CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); 199 let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
200 CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed);
123} 201}
124 202
125#[cfg(feature = "low-power")] 203#[cfg(feature = "low-power")]
126pub(crate) fn clock_refcount_sub() { 204pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) {
127 assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); 205 let n = CLOCK_REFCOUNT.load(Ordering::Relaxed);
206 assert!(n != 0);
207 CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed);
128} 208}
129 209
130/// Frozen clock frequencies 210/// Frozen clock frequencies
@@ -132,14 +212,6 @@ pub(crate) fn clock_refcount_sub() {
132/// The existence of this value indicates that the clock configuration can no longer be changed 212/// The existence of this value indicates that the clock configuration can no longer be changed
133static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); 213static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
134 214
135#[cfg(stm32wb)]
136/// RCC initialization function
137pub(crate) unsafe fn init(config: Config) {
138 set_freqs(compute_clocks(&config));
139
140 configure_clocks(&config);
141}
142
143/// Sets the clock frequencies 215/// Sets the clock frequencies
144/// 216///
145/// Safety: Sets a mutable global. 217/// Safety: Sets a mutable global.
@@ -159,11 +231,19 @@ pub mod low_level {
159} 231}
160 232
161pub(crate) mod sealed { 233pub(crate) mod sealed {
234 use critical_section::CriticalSection;
235
162 pub trait RccPeripheral { 236 pub trait RccPeripheral {
163 fn frequency() -> crate::time::Hertz; 237 fn frequency() -> crate::time::Hertz;
164 fn reset(); 238 fn enable_and_reset_with_cs(cs: CriticalSection);
165 fn enable(); 239 fn disable_with_cs(cs: CriticalSection);
166 fn disable(); 240
241 fn enable_and_reset() {
242 critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
243 }
244 fn disable() {
245 critical_section::with(|cs| Self::disable_with_cs(cs))
246 }
167 } 247 }
168} 248}
169 249
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index d9a531285..aba5ca831 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,121 +1,99 @@
1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; 1pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler};
2 2use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw};
3pub use super::bus::{AHBPrescaler, APBPrescaler}; 3use crate::pac::{FLASH, PWR, RCC};
4use crate::pac::{FLASH, RCC};
5use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 5use crate::time::Hertz;
7 6
8/// HSI speed 7/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(16_000_000); 8pub const HSI_FREQ: Hertz = Hertz(16_000_000);
10 9
11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(32_000);
13
14pub use crate::pac::pwr::vals::Vos as VoltageScale; 10pub use crate::pac::pwr::vals::Vos as VoltageScale;
15 11
16#[derive(Copy, Clone)] 12#[derive(Copy, Clone)]
17pub enum ClockSrc { 13pub enum ClockSrc {
18 MSI(MSIRange), 14 /// Use an internal medium speed oscillator (MSIS) as the system clock.
19 HSE(Hertz), 15 MSI(Msirange),
20 HSI16, 16 /// Use the external high speed clock as the system clock.
21 PLL1R(PllSrc, PllM, PllN, PllClkDiv), 17 ///
22} 18 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
23 19 /// never exceed 50 MHz.
24#[derive(Clone, Copy, Debug)]
25pub enum PllSrc {
26 MSI(MSIRange),
27 HSE(Hertz), 20 HSE(Hertz),
21 /// Use the 16 MHz internal high speed oscillator as the system clock.
28 HSI16, 22 HSI16,
23 /// Use PLL1 as the system clock.
24 PLL1R(PllConfig),
29} 25}
30 26
31impl Into<Pllsrc> for PllSrc { 27impl Default for ClockSrc {
32 fn into(self) -> Pllsrc { 28 fn default() -> Self {
33 match self { 29 // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9
34 PllSrc::MSI(..) => Pllsrc::MSIS, 30 ClockSrc::MSI(Msirange::RANGE_4MHZ)
35 PllSrc::HSE(..) => Pllsrc::HSE,
36 PllSrc::HSI16 => Pllsrc::HSI16,
37 }
38 } 31 }
39} 32}
40 33
41seq_macro::seq!(N in 2..=128 { 34#[derive(Clone, Copy)]
42 #[derive(Copy, Clone, Debug)] 35pub struct PllConfig {
43 pub enum PllClkDiv { 36 /// The clock source for the PLL.
44 NotDivided, 37 pub source: PllSrc,
45 #( 38 /// The PLL prescaler.
46 Div~N = (N-1), 39 ///
47 )* 40 /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
48 } 41 pub m: Pllm,
49 42 /// The PLL multiplier.
50 impl PllClkDiv { 43 ///
51 fn to_div(&self) -> u8 { 44 /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544
52 match self { 45 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`.
53 PllClkDiv::NotDivided => 1, 46 pub n: Plln,
54 #( 47 /// The divider for the R output.
55 PllClkDiv::Div~N => N + 1, 48 ///
56 )* 49 /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r`
57 } 50 /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default
58 } 51 /// `Config { voltage_range }`.
59 } 52 pub r: Plldiv,
60});
61
62impl Into<u8> for PllClkDiv {
63 fn into(self) -> u8 {
64 (self as u8) + 1
65 }
66} 53}
67 54
68seq_macro::seq!(N in 4..=512 { 55impl PllConfig {
69 #[derive(Copy, Clone, Debug)] 56 /// A configuration for HSI16 / 1 * 10 / 1 = 160 MHz
70 pub enum PllN { 57 pub const fn hsi16_160mhz() -> Self {
71 NotMultiplied, 58 PllConfig {
72 #( 59 source: PllSrc::HSI16,
73 Mul~N = N-1, 60 m: Pllm::DIV1,
74 )* 61 n: Plln::MUL10,
75 } 62 r: Plldiv::DIV1,
76
77 impl PllN {
78 fn to_mul(&self) -> u16 {
79 match self {
80 PllN::NotMultiplied => 1,
81 #(
82 PllN::Mul~N => N + 1,
83 )*
84 }
85 } 63 }
86 } 64 }
87});
88 65
89impl Into<u16> for PllN { 66 /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
90 fn into(self) -> u16 { 67 pub const fn msis_160mhz() -> Self {
91 (self as u16) + 1 68 PllConfig {
69 source: PllSrc::MSIS(Msirange::RANGE_48MHZ),
70 m: Pllm::DIV3,
71 n: Plln::MUL10,
72 r: Plldiv::DIV1,
73 }
92 } 74 }
93} 75}
94 76
95// Pre-division 77#[derive(Clone, Copy)]
96#[derive(Copy, Clone, Debug)] 78pub enum PllSrc {
97pub enum PllM { 79 /// Use an internal medium speed oscillator as the PLL source.
98 NotDivided = 0b0000, 80 MSIS(Msirange),
99 Div2 = 0b0001, 81 /// Use the external high speed clock as the system PLL source.
100 Div3 = 0b0010, 82 ///
101 Div4 = 0b0011, 83 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
102 Div5 = 0b0100, 84 /// never exceed 50 MHz.
103 Div6 = 0b0101, 85 HSE(Hertz),
104 Div7 = 0b0110, 86 /// Use the 16 MHz internal high speed oscillator as the PLL source.
105 Div8 = 0b0111, 87 HSI16,
106 Div9 = 0b1000,
107 Div10 = 0b1001,
108 Div11 = 0b1010,
109 Div12 = 0b1011,
110 Div13 = 0b1100,
111 Div14 = 0b1101,
112 Div15 = 0b1110,
113 Div16 = 0b1111,
114} 88}
115 89
116impl Into<Pllm> for PllM { 90impl Into<Pllsrc> for PllSrc {
117 fn into(self) -> Pllm { 91 fn into(self) -> Pllsrc {
118 Pllm::from_bits(self as u8) 92 match self {
93 PllSrc::MSIS(..) => Pllsrc::MSIS,
94 PllSrc::HSE(..) => Pllsrc::HSE,
95 PllSrc::HSI16 => Pllsrc::HSI16,
96 }
119 } 97 }
120} 98}
121 99
@@ -130,153 +108,216 @@ impl Into<Sw> for ClockSrc {
130 } 108 }
131} 109}
132 110
133#[derive(Debug, Copy, Clone)] 111pub struct Config {
134pub enum MSIRange { 112 pub mux: ClockSrc,
135 Range48mhz = 48_000_000, 113 pub ahb_pre: AHBPrescaler,
136 Range24mhz = 24_000_000, 114 pub apb1_pre: APBPrescaler,
137 Range16mhz = 16_000_000, 115 pub apb2_pre: APBPrescaler,
138 Range12mhz = 12_000_000, 116 pub apb3_pre: APBPrescaler,
139 Range4mhz = 4_000_000, 117 pub hsi48: bool,
140 Range2mhz = 2_000_000, 118 /// The voltage range influences the maximum clock frequencies for different parts of the
141 Range1_33mhz = 1_330_000, 119 /// device. In particular, system clocks exceeding 110 MHz require `RANGE1`, and system clocks
142 Range1mhz = 1_000_000, 120 /// exceeding 55 MHz require at least `RANGE2`.
143 Range3_072mhz = 3_072_000, 121 ///
144 Range1_536mhz = 1_536_000, 122 /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits.
145 Range1_024mhz = 1_024_000, 123 pub voltage_range: VoltageScale,
146 Range768khz = 768_000, 124 pub ls: super::LsConfig,
147 Range400khz = 400_000,
148 Range200khz = 200_000,
149 Range133khz = 133_000,
150 Range100khz = 100_000,
151} 125}
152 126
153impl Into<u32> for MSIRange { 127impl Config {
154 fn into(self) -> u32 { 128 unsafe fn init_hsi16(&self) -> Hertz {
155 self as u32 129 RCC.cr().write(|w| w.set_hsion(true));
130 while !RCC.cr().read().hsirdy() {}
131
132 HSI_FREQ
156 } 133 }
157}
158 134
159impl Into<Msirange> for MSIRange { 135 unsafe fn init_hse(&self, frequency: Hertz) -> Hertz {
160 fn into(self) -> Msirange { 136 // Check frequency limits per RM456 § 11.4.10
161 match self { 137 match self.voltage_range {
162 MSIRange::Range48mhz => Msirange::RANGE_48MHZ, 138 VoltageScale::RANGE1 | VoltageScale::RANGE2 | VoltageScale::RANGE3 => {
163 MSIRange::Range24mhz => Msirange::RANGE_24MHZ, 139 assert!(frequency.0 <= 50_000_000);
164 MSIRange::Range16mhz => Msirange::RANGE_16MHZ, 140 }
165 MSIRange::Range12mhz => Msirange::RANGE_12MHZ, 141 VoltageScale::RANGE4 => {
166 MSIRange::Range4mhz => Msirange::RANGE_4MHZ, 142 assert!(frequency.0 <= 25_000_000);
167 MSIRange::Range2mhz => Msirange::RANGE_2MHZ, 143 }
168 MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ,
169 MSIRange::Range1mhz => Msirange::RANGE_1MHZ,
170 MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ,
171 MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ,
172 MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ,
173 MSIRange::Range768khz => Msirange::RANGE_768KHZ,
174 MSIRange::Range400khz => Msirange::RANGE_400KHZ,
175 MSIRange::Range200khz => Msirange::RANGE_200KHZ,
176 MSIRange::Range133khz => Msirange::RANGE_133KHZ,
177 MSIRange::Range100khz => Msirange::RANGE_100KHZ,
178 } 144 }
179 }
180}
181 145
182impl Default for MSIRange { 146 // Enable HSE, and wait for it to stabilize
183 fn default() -> Self { 147 RCC.cr().write(|w| w.set_hseon(true));
184 MSIRange::Range4mhz 148 while !RCC.cr().read().hserdy() {}
149
150 frequency
185 } 151 }
186}
187 152
188#[derive(Copy, Clone)] 153 unsafe fn init_msis(&self, range: Msirange) -> Hertz {
189pub struct Config { 154 // Check MSI output per RM0456 § 11.4.10
190 pub mux: ClockSrc, 155 match self.voltage_range {
191 pub ahb_pre: AHBPrescaler, 156 VoltageScale::RANGE4 => {
192 pub apb1_pre: APBPrescaler, 157 assert!(msirange_to_hertz(range).0 <= 24_000_000);
193 pub apb2_pre: APBPrescaler, 158 }
194 pub apb3_pre: APBPrescaler, 159 _ => {}
195 pub hsi48: bool, 160 }
161
162 // RM0456 § 11.8.2: spin until MSIS is off or MSIS is ready before setting its range
163 loop {
164 let cr = RCC.cr().read();
165 if cr.msison() == false || cr.msisrdy() == true {
166 break;
167 }
168 }
169
170 RCC.icscr1().modify(|w| {
171 w.set_msisrange(range);
172 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
173 });
174 RCC.cr().write(|w| {
175 w.set_msipllen(false);
176 w.set_msison(true);
177 });
178 while !RCC.cr().read().msisrdy() {}
179 msirange_to_hertz(range)
180 }
196} 181}
197 182
198impl Default for Config { 183impl Default for Config {
199 fn default() -> Self { 184 fn default() -> Self {
200 Self { 185 Self {
201 mux: ClockSrc::MSI(MSIRange::default()), 186 mux: ClockSrc::default(),
202 ahb_pre: AHBPrescaler::DIV1, 187 ahb_pre: AHBPrescaler::DIV1,
203 apb1_pre: APBPrescaler::DIV1, 188 apb1_pre: APBPrescaler::DIV1,
204 apb2_pre: APBPrescaler::DIV1, 189 apb2_pre: APBPrescaler::DIV1,
205 apb3_pre: APBPrescaler::DIV1, 190 apb3_pre: APBPrescaler::DIV1,
206 hsi48: false, 191 hsi48: true,
192 voltage_range: VoltageScale::RANGE3,
193 ls: Default::default(),
207 } 194 }
208 } 195 }
209} 196}
210 197
211pub(crate) unsafe fn init(config: Config) { 198pub(crate) unsafe fn init(config: Config) {
199 // Ensure PWR peripheral clock is enabled
200 RCC.ahb3enr().modify(|w| {
201 w.set_pwren(true);
202 });
203 RCC.ahb3enr().read(); // synchronize
204
205 // Set the requested power mode
206 PWR.vosr().modify(|w| {
207 w.set_vos(config.voltage_range);
208 });
209 while !PWR.vosr().read().vosrdy() {}
210
212 let sys_clk = match config.mux { 211 let sys_clk = match config.mux {
213 ClockSrc::MSI(range) => { 212 ClockSrc::MSI(range) => config.init_msis(range),
214 RCC.icscr1().modify(|w| { 213 ClockSrc::HSE(freq) => config.init_hse(freq),
215 let bits: Msirange = range.into(); 214 ClockSrc::HSI16 => config.init_hsi16(),
216 w.set_msisrange(bits); 215 ClockSrc::PLL1R(pll) => {
217 w.set_msirgsel(Msirgsel::RCC_ICSCR1); 216 // Configure the PLL source
218 }); 217 let source_clk = match pll.source {
219 RCC.cr().write(|w| { 218 PllSrc::MSIS(range) => config.init_msis(range),
220 w.set_msipllen(false); 219 PllSrc::HSE(hertz) => config.init_hse(hertz),
221 w.set_msison(true); 220 PllSrc::HSI16 => config.init_hsi16(),
222 }); 221 };
223 while !RCC.cr().read().msisrdy() {}
224 222
225 range.into() 223 // Calculate the reference clock, which is the source divided by m
226 } 224 let reference_clk = source_clk / pll.m;
227 ClockSrc::HSE(freq) => {
228 RCC.cr().write(|w| w.set_hseon(true));
229 while !RCC.cr().read().hserdy() {}
230 225
231 freq.0 226 // Check limits per RM0456 § 11.4.6
232 } 227 assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16));
233 ClockSrc::HSI16 => {
234 RCC.cr().write(|w| w.set_hsion(true));
235 while !RCC.cr().read().hsirdy() {}
236 228
237 HSI_FREQ.0 229 // Calculate the PLL1 VCO clock and PLL1 R output clock
238 } 230 let pll1_clk = reference_clk * pll.n;
239 ClockSrc::PLL1R(src, m, n, div) => { 231 let pll1r_clk = pll1_clk / pll.r;
240 let freq = match src { 232
241 PllSrc::MSI(_) => { 233 // Check system clock per RM0456 § 11.4.9
242 // TODO: enable MSI 234 assert!(pll1r_clk <= Hertz::mhz(160));
243 MSIRange::default().into() 235
236 // Check PLL clocks per RM0456 § 11.4.10
237 match config.voltage_range {
238 VoltageScale::RANGE1 => {
239 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
240 assert!(pll1r_clk <= Hertz::mhz(208));
244 } 241 }
245 PllSrc::HSE(hertz) => { 242 VoltageScale::RANGE2 => {
246 // TODO: enable HSE 243 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
247 hertz.0 244 assert!(pll1r_clk <= Hertz::mhz(110));
248 } 245 }
249 PllSrc::HSI16 => { 246 VoltageScale::RANGE3 => {
250 RCC.cr().write(|w| w.set_hsion(true)); 247 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(330));
251 while !RCC.cr().read().hsirdy() {} 248 assert!(pll1r_clk <= Hertz::mhz(55));
249 }
250 VoltageScale::RANGE4 => {
251 panic!("PLL is unavailable in voltage range 4");
252 }
253 }
252 254
253 HSI_FREQ.0 255 // § 10.5.4: if we're targeting >= 55 MHz, we must configure PLL1MBOOST to a prescaler
256 // value that results in an output between 4 and 16 MHz for the PWR EPOD boost
257 let mboost = if pll1r_clk >= Hertz::mhz(55) {
258 // source_clk can be up to 50 MHz, so there's just a few cases:
259 if source_clk > Hertz::mhz(32) {
260 // Divide by 4, giving EPOD 8-12.5 MHz
261 Pllmboost::DIV4
262 } else if source_clk > Hertz::mhz(16) {
263 // Divide by 2, giving EPOD 8-16 MHz
264 Pllmboost::DIV2
265 } else {
266 // Bypass, giving EPOD 4-16 MHz
267 Pllmboost::DIV1
254 } 268 }
269 } else {
270 // Nothing to do
271 Pllmboost::DIV1
255 }; 272 };
256 273
257 // disable 274 // Disable the PLL, and wait for it to disable
258 RCC.cr().modify(|w| w.set_pllon(0, false)); 275 RCC.cr().modify(|w| w.set_pllon(0, false));
259 while RCC.cr().read().pllrdy(0) {} 276 while RCC.cr().read().pllrdy(0) {}
260 277
261 let vco = freq * n as u8 as u32; 278 // Configure the PLL
262 let pll_ck = vco / (div as u8 as u32 + 1);
263
264 RCC.pll1cfgr().write(|w| { 279 RCC.pll1cfgr().write(|w| {
265 w.set_pllm(m.into()); 280 // Configure PLL1 source and prescaler
266 w.set_pllsrc(src.into()); 281 w.set_pllsrc(pll.source.into());
282 w.set_pllm(pll.m);
283
284 // Configure PLL1 input frequncy range
285 let input_range = if reference_clk <= Hertz::mhz(8) {
286 Pllrge::FREQ_4TO8MHZ
287 } else {
288 Pllrge::FREQ_8TO16MHZ
289 };
290 w.set_pllrge(input_range);
291
292 // Set the prescaler for PWR EPOD
293 w.set_pllmboost(mboost);
294
295 // Enable PLL1R output
267 w.set_pllren(true); 296 w.set_pllren(true);
268 }); 297 });
269 298
299 // Configure the PLL divisors
270 RCC.pll1divr().modify(|w| { 300 RCC.pll1divr().modify(|w| {
271 w.set_pllr(div.to_div()); 301 // Set the VCO multiplier
272 w.set_plln(n.to_mul()); 302 w.set_plln(pll.n);
303 // Set the R output divisor
304 w.set_pllr(pll.r);
273 }); 305 });
274 306
275 // Enable PLL 307 // Do we need the EPOD booster to reach the target clock speed per § 10.5.4?
308 if pll1r_clk >= Hertz::mhz(55) {
309 // Enable the booster
310 PWR.vosr().modify(|w| {
311 w.set_boosten(true);
312 });
313 while !PWR.vosr().read().boostrdy() {}
314 }
315
316 // Enable the PLL
276 RCC.cr().modify(|w| w.set_pllon(0, true)); 317 RCC.cr().modify(|w| w.set_pllon(0, true));
277 while !RCC.cr().read().pllrdy(0) {} 318 while !RCC.cr().read().pllrdy(0) {}
278 319
279 pll_ck 320 pll1r_clk
280 } 321 }
281 }; 322 };
282 323
@@ -285,20 +326,18 @@ pub(crate) unsafe fn init(config: Config) {
285 while !RCC.cr().read().hsi48rdy() {} 326 while !RCC.cr().read().hsi48rdy() {}
286 } 327 }
287 328
288 // TODO make configurable 329 // The clock source is ready
289 let power_vos = VoltageScale::RANGE3; 330 // Calculate and set the flash wait states
290 331 let wait_states = match config.voltage_range {
291 // states and programming delay
292 let wait_states = match power_vos {
293 // VOS 1 range VCORE 1.26V - 1.40V 332 // VOS 1 range VCORE 1.26V - 1.40V
294 VoltageScale::RANGE1 => { 333 VoltageScale::RANGE1 => {
295 if sys_clk < 32_000_000 { 334 if sys_clk.0 < 32_000_000 {
296 0 335 0
297 } else if sys_clk < 64_000_000 { 336 } else if sys_clk.0 < 64_000_000 {
298 1 337 1
299 } else if sys_clk < 96_000_000 { 338 } else if sys_clk.0 < 96_000_000 {
300 2 339 2
301 } else if sys_clk < 128_000_000 { 340 } else if sys_clk.0 < 128_000_000 {
302 3 341 3
303 } else { 342 } else {
304 4 343 4
@@ -306,11 +345,11 @@ pub(crate) unsafe fn init(config: Config) {
306 } 345 }
307 // VOS 2 range VCORE 1.15V - 1.26V 346 // VOS 2 range VCORE 1.15V - 1.26V
308 VoltageScale::RANGE2 => { 347 VoltageScale::RANGE2 => {
309 if sys_clk < 30_000_000 { 348 if sys_clk.0 < 30_000_000 {
310 0 349 0
311 } else if sys_clk < 60_000_000 { 350 } else if sys_clk.0 < 60_000_000 {
312 1 351 1
313 } else if sys_clk < 90_000_000 { 352 } else if sys_clk.0 < 90_000_000 {
314 2 353 2
315 } else { 354 } else {
316 3 355 3
@@ -318,9 +357,9 @@ pub(crate) unsafe fn init(config: Config) {
318 } 357 }
319 // VOS 3 range VCORE 1.05V - 1.15V 358 // VOS 3 range VCORE 1.05V - 1.15V
320 VoltageScale::RANGE3 => { 359 VoltageScale::RANGE3 => {
321 if sys_clk < 24_000_000 { 360 if sys_clk.0 < 24_000_000 {
322 0 361 0
323 } else if sys_clk < 48_000_000 { 362 } else if sys_clk.0 < 48_000_000 {
324 1 363 1
325 } else { 364 } else {
326 2 365 2
@@ -328,80 +367,104 @@ pub(crate) unsafe fn init(config: Config) {
328 } 367 }
329 // VOS 4 range VCORE 0.95V - 1.05V 368 // VOS 4 range VCORE 0.95V - 1.05V
330 VoltageScale::RANGE4 => { 369 VoltageScale::RANGE4 => {
331 if sys_clk < 12_000_000 { 370 if sys_clk.0 < 12_000_000 {
332 0 371 0
333 } else { 372 } else {
334 1 373 1
335 } 374 }
336 } 375 }
337 }; 376 };
338
339 FLASH.acr().modify(|w| { 377 FLASH.acr().modify(|w| {
340 w.set_latency(wait_states); 378 w.set_latency(wait_states);
341 }); 379 });
342 380
381 // Switch the system clock source
343 RCC.cfgr1().modify(|w| { 382 RCC.cfgr1().modify(|w| {
344 w.set_sw(config.mux.into()); 383 w.set_sw(config.mux.into());
345 }); 384 });
346 385
386 // RM0456 § 11.4.9 specifies maximum bus frequencies per voltage range, but the maximum bus
387 // frequency for each voltage range exactly matches the maximum permitted PLL output frequency.
388 // Given that:
389 //
390 // 1. Any bus frequency can never exceed the system clock frequency;
391 // 2. We checked the PLL output frequency if we're using it as a system clock;
392 // 3. The maximum HSE frequencies at each voltage range are lower than the bus limits, and
393 // we checked the HSE frequency if configured as a system clock; and
394 // 4. The maximum frequencies from the other clock sources are lower than the lowest bus
395 // frequency limit
396 //
397 // ...then we do not need to perform additional bus-related frequency checks.
398
399 // Configure the bus prescalers
347 RCC.cfgr2().modify(|w| { 400 RCC.cfgr2().modify(|w| {
348 w.set_hpre(config.ahb_pre.into()); 401 w.set_hpre(config.ahb_pre);
349 w.set_ppre1(config.apb1_pre.into()); 402 w.set_ppre1(config.apb1_pre);
350 w.set_ppre2(config.apb2_pre.into()); 403 w.set_ppre2(config.apb2_pre);
351 }); 404 });
352
353 RCC.cfgr3().modify(|w| { 405 RCC.cfgr3().modify(|w| {
354 w.set_ppre3(config.apb3_pre.into()); 406 w.set_ppre3(config.apb3_pre);
355 }); 407 });
356 408
357 let ahb_freq: u32 = match config.ahb_pre { 409 let ahb_freq = sys_clk / config.ahb_pre;
358 AHBPrescaler::DIV1 => sys_clk,
359 pre => {
360 let pre: u8 = pre.into();
361 let pre = 1 << (pre as u32 - 7);
362 sys_clk / pre
363 }
364 };
365 410
366 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 411 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
367 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 412 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
368 pre => { 413 pre => {
369 let pre: u8 = pre.into(); 414 let freq = ahb_freq / pre;
370 let pre: u8 = 1 << (pre - 3); 415 (freq, freq * 2u32)
371 let freq = ahb_freq / pre as u32;
372 (freq, freq * 2)
373 } 416 }
374 }; 417 };
375 418
376 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 419 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
377 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 420 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
378 pre => { 421 pre => {
379 let pre: u8 = pre.into(); 422 let freq = ahb_freq / pre;
380 let pre: u8 = 1 << (pre - 3); 423 (freq, freq * 2u32)
381 let freq = ahb_freq / pre as u32;
382 (freq, freq * 2)
383 } 424 }
384 }; 425 };
385 426
386 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre { 427 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre {
387 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 428 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
388 pre => { 429 pre => {
389 let pre: u8 = pre.into(); 430 let freq = ahb_freq / pre;
390 let pre: u8 = 1 << (pre - 3); 431 (freq, freq * 2u32)
391 let freq = ahb_freq / pre as u32;
392 (freq, freq * 2)
393 } 432 }
394 }; 433 };
395 434
435 let rtc = config.ls.init();
436
396 set_freqs(Clocks { 437 set_freqs(Clocks {
397 sys: Hertz(sys_clk), 438 sys: sys_clk,
398 ahb1: Hertz(ahb_freq), 439 hclk1: ahb_freq,
399 ahb2: Hertz(ahb_freq), 440 hclk2: ahb_freq,
400 ahb3: Hertz(ahb_freq), 441 hclk3: ahb_freq,
401 apb1: Hertz(apb1_freq), 442 pclk1: apb1_freq,
402 apb2: Hertz(apb2_freq), 443 pclk2: apb2_freq,
403 apb3: Hertz(apb3_freq), 444 pclk3: apb3_freq,
404 apb1_tim: Hertz(apb1_tim_freq), 445 pclk1_tim: apb1_tim_freq,
405 apb2_tim: Hertz(apb2_tim_freq), 446 pclk2_tim: apb2_tim_freq,
447 rtc,
406 }); 448 });
407} 449}
450
451fn msirange_to_hertz(range: Msirange) -> Hertz {
452 match range {
453 Msirange::RANGE_48MHZ => Hertz(48_000_000),
454 Msirange::RANGE_24MHZ => Hertz(24_000_000),
455 Msirange::RANGE_16MHZ => Hertz(16_000_000),
456 Msirange::RANGE_12MHZ => Hertz(12_000_000),
457 Msirange::RANGE_4MHZ => Hertz(4_000_000),
458 Msirange::RANGE_2MHZ => Hertz(2_000_000),
459 Msirange::RANGE_1_33MHZ => Hertz(1_330_000),
460 Msirange::RANGE_1MHZ => Hertz(1_000_000),
461 Msirange::RANGE_3_072MHZ => Hertz(3_072_000),
462 Msirange::RANGE_1_536MHZ => Hertz(1_536_000),
463 Msirange::RANGE_1_024MHZ => Hertz(1_024_000),
464 Msirange::RANGE_768KHZ => Hertz(768_000),
465 Msirange::RANGE_400KHZ => Hertz(400_000),
466 Msirange::RANGE_200KHZ => Hertz(200_000),
467 Msirange::RANGE_133KHZ => Hertz(133_000),
468 Msirange::RANGE_100KHZ => Hertz(100_000),
469 }
470}
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index ee45a342b..64173fea8 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -1,118 +1,46 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler}; 1pub use crate::pac::rcc::vals::{
2use crate::rcc::bd::{BackupDomain, RtcClockSource}; 2 Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource,
3use crate::rcc::Clocks; 3 Ppre as APBPrescaler, Sw as Sysclk,
4use crate::time::{khz, mhz, Hertz}; 4};
5 5use crate::rcc::{set_freqs, Clocks};
6/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 6use crate::time::{mhz, Hertz};
7/// and with the addition of the init function to configure a system clock.
8
9/// Only the basic setup using the HSE and HSI clocks are supported as of now.
10 7
11/// HSI speed 8/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000); 9pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13 10
14/// LSI speed
15pub const LSI_FREQ: Hertz = Hertz(32_000);
16
17#[derive(Clone, Copy)]
18pub enum HsePrescaler {
19 NotDivided,
20 Div2,
21}
22
23impl From<HsePrescaler> for bool {
24 fn from(value: HsePrescaler) -> Self {
25 match value {
26 HsePrescaler::NotDivided => false,
27 HsePrescaler::Div2 => true,
28 }
29 }
30}
31
32pub struct Hse { 11pub struct Hse {
33 pub prediv: HsePrescaler, 12 pub prediv: HsePrescaler,
34 13
35 pub frequency: Hertz, 14 pub frequency: Hertz,
36} 15}
37 16
38/// System clock mux source
39#[derive(Clone, Copy, PartialEq)]
40pub enum Sysclk {
41 /// MSI selected as sysclk
42 MSI,
43 /// HSI selected as sysclk
44 HSI,
45 /// HSE selected as sysclk
46 HSE,
47 /// PLL selected as sysclk
48 Pll,
49}
50
51impl From<Sysclk> for u8 {
52 fn from(value: Sysclk) -> Self {
53 match value {
54 Sysclk::MSI => 0b00,
55 Sysclk::HSI => 0b01,
56 Sysclk::HSE => 0b10,
57 Sysclk::Pll => 0b11,
58 }
59 }
60}
61
62#[derive(Clone, Copy, PartialEq)]
63pub enum PllSource {
64 Hsi,
65 Msi,
66 Hse,
67}
68
69impl From<PllSource> for u8 {
70 fn from(value: PllSource) -> Self {
71 match value {
72 PllSource::Msi => 0b01,
73 PllSource::Hsi => 0b10,
74 PllSource::Hse => 0b11,
75 }
76 }
77}
78
79pub enum Pll48Source {
80 PllSai,
81 Pll,
82 Msi,
83 Hsi48,
84}
85
86pub struct PllMux { 17pub struct PllMux {
87 /// Source clock selection. 18 /// Source clock selection.
88 pub source: PllSource, 19 pub source: PllSource,
89 20
90 /// PLL pre-divider (DIVM). Must be between 1 and 63. 21 /// PLL pre-divider (DIVM). Must be between 1 and 63.
91 pub prediv: u8, 22 pub prediv: Pllm,
92} 23}
93 24
94pub struct Pll { 25pub struct Pll {
95 /// PLL multiplication factor. Must be between 4 and 512. 26 /// PLL multiplication factor. Must be between 4 and 512.
96 pub mul: u16, 27 pub mul: Plln,
97 28
98 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. 29 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
99 /// On PLL1, it must be even (in particular, it cannot be 1.) 30 /// On PLL1, it must be even (in particular, it cannot be 1.)
100 pub divp: Option<u16>, 31 pub divp: Option<Pllp>,
101 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. 32 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
102 pub divq: Option<u16>, 33 pub divq: Option<Pllq>,
103 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. 34 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
104 pub divr: Option<u16>, 35 pub divr: Option<Pllr>,
105} 36}
106 37
107/// Clocks configutation 38/// Clocks configutation
108pub struct Config { 39pub struct Config {
109 pub hse: Option<Hse>, 40 pub hse: Option<Hse>,
110 pub lse: Option<Hertz>,
111 pub lsi: bool,
112 pub sys: Sysclk, 41 pub sys: Sysclk,
113 pub mux: Option<PllMux>, 42 pub mux: Option<PllMux>,
114 pub pll48: Option<Pll48Source>, 43 pub hsi48: bool,
115 pub rtc: Option<RtcClockSource>,
116 44
117 pub pll: Option<Pll>, 45 pub pll: Option<Pll>,
118 pub pllsai: Option<Pll>, 46 pub pllsai: Option<Pll>,
@@ -122,28 +50,29 @@ pub struct Config {
122 pub ahb3_pre: AHBPrescaler, 50 pub ahb3_pre: AHBPrescaler,
123 pub apb1_pre: APBPrescaler, 51 pub apb1_pre: APBPrescaler,
124 pub apb2_pre: APBPrescaler, 52 pub apb2_pre: APBPrescaler,
53
54 pub ls: super::LsConfig,
125} 55}
126 56
127pub const WPAN_DEFAULT: Config = Config { 57pub const WPAN_DEFAULT: Config = Config {
128 hse: Some(Hse { 58 hse: Some(Hse {
129 frequency: mhz(32), 59 frequency: mhz(32),
130 prediv: HsePrescaler::NotDivided, 60 prediv: HsePrescaler::DIV1,
131 }), 61 }),
132 lse: Some(khz(32)), 62 sys: Sysclk::PLL,
133 sys: Sysclk::Pll,
134 mux: Some(PllMux { 63 mux: Some(PllMux {
135 source: PllSource::Hse, 64 source: PllSource::HSE,
136 prediv: 2, 65 prediv: Pllm::DIV2,
137 }), 66 }),
138 pll48: None, 67 hsi48: true,
139 rtc: Some(RtcClockSource::LSE), 68
140 lsi: false, 69 ls: super::LsConfig::default_lse(),
141 70
142 pll: Some(Pll { 71 pll: Some(Pll {
143 mul: 12, 72 mul: Plln::MUL12,
144 divp: Some(3), 73 divp: Some(Pllp::DIV3),
145 divq: Some(4), 74 divq: Some(Pllq::DIV4),
146 divr: Some(3), 75 divr: Some(Pllr::DIV3),
147 }), 76 }),
148 pllsai: None, 77 pllsai: None,
149 78
@@ -159,14 +88,13 @@ impl Default for Config {
159 fn default() -> Config { 88 fn default() -> Config {
160 Config { 89 Config {
161 hse: None, 90 hse: None,
162 lse: None, 91 sys: Sysclk::HSI16,
163 sys: Sysclk::HSI,
164 mux: None, 92 mux: None,
165 pll48: None,
166 pll: None, 93 pll: None,
167 pllsai: None, 94 pllsai: None,
168 rtc: None, 95 hsi48: true,
169 lsi: false, 96
97 ls: Default::default(),
170 98
171 ahb1_pre: AHBPrescaler::DIV1, 99 ahb1_pre: AHBPrescaler::DIV1,
172 ahb2_pre: AHBPrescaler::DIV1, 100 ahb2_pre: AHBPrescaler::DIV1,
@@ -177,16 +105,15 @@ impl Default for Config {
177 } 105 }
178} 106}
179 107
180pub(crate) fn compute_clocks(config: &Config) -> Clocks { 108#[cfg(stm32wb)]
181 let hse_clk = config.hse.as_ref().map(|hse| match hse.prediv { 109/// RCC initialization function
182 HsePrescaler::NotDivided => hse.frequency, 110pub(crate) unsafe fn init(config: Config) {
183 HsePrescaler::Div2 => hse.frequency / 2u32, 111 let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv);
184 });
185 112
186 let mux_clk = config.mux.as_ref().map(|pll_mux| { 113 let mux_clk = config.mux.as_ref().map(|pll_mux| {
187 (match pll_mux.source { 114 (match pll_mux.source {
188 PllSource::Hse => hse_clk.unwrap(), 115 PllSource::HSE => hse_clk.unwrap(),
189 PllSource::Hsi => HSI_FREQ, 116 PllSource::HSI16 => HSI_FREQ,
190 _ => unreachable!(), 117 _ => unreachable!(),
191 } / pll_mux.prediv) 118 } / pll_mux.prediv)
192 }); 119 });
@@ -206,44 +133,19 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
206 133
207 let sys_clk = match config.sys { 134 let sys_clk = match config.sys {
208 Sysclk::HSE => hse_clk.unwrap(), 135 Sysclk::HSE => hse_clk.unwrap(),
209 Sysclk::HSI => HSI_FREQ, 136 Sysclk::HSI16 => HSI_FREQ,
210 Sysclk::Pll => pll_r.unwrap(), 137 Sysclk::PLL => pll_r.unwrap(),
211 _ => unreachable!(), 138 _ => unreachable!(),
212 }; 139 };
213 140
214 let ahb1_clk = match config.ahb1_pre { 141 let ahb1_clk = sys_clk / config.ahb1_pre;
215 AHBPrescaler::DIV1 => sys_clk, 142 let ahb2_clk = sys_clk / config.ahb2_pre;
216 pre => { 143 let ahb3_clk = sys_clk / config.ahb3_pre;
217 let pre: u8 = pre.into();
218 let pre = 1u32 << (pre as u32 - 7);
219 sys_clk / pre
220 }
221 };
222
223 let ahb2_clk = match config.ahb2_pre {
224 AHBPrescaler::DIV1 => sys_clk,
225 pre => {
226 let pre: u8 = pre.into();
227 let pre = 1u32 << (pre as u32 - 7);
228 sys_clk / pre
229 }
230 };
231
232 let ahb3_clk = match config.ahb3_pre {
233 AHBPrescaler::DIV1 => sys_clk,
234 pre => {
235 let pre: u8 = pre.into();
236 let pre = 1u32 << (pre as u32 - 7);
237 sys_clk / pre
238 }
239 };
240 144
241 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre { 145 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
242 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), 146 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
243 pre => { 147 pre => {
244 let pre: u8 = pre.into(); 148 let freq = ahb1_clk / pre;
245 let pre: u8 = 1 << (pre - 3);
246 let freq = ahb1_clk / pre as u32;
247 (freq, freq * 2u32) 149 (freq, freq * 2u32)
248 } 150 }
249 }; 151 };
@@ -251,43 +153,20 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
251 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre { 153 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
252 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), 154 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
253 pre => { 155 pre => {
254 let pre: u8 = pre.into(); 156 let freq = ahb1_clk / pre;
255 let pre: u8 = 1 << (pre - 3);
256 let freq = ahb1_clk / pre as u32;
257 (freq, freq * 2u32) 157 (freq, freq * 2u32)
258 } 158 }
259 }; 159 };
260 160
261 let rtc_clk = match config.rtc {
262 Some(RtcClockSource::LSI) => Some(LSI_FREQ),
263 Some(RtcClockSource::LSE) => Some(config.lse.unwrap()),
264 _ => None,
265 };
266
267 Clocks {
268 sys: sys_clk,
269 ahb1: ahb1_clk,
270 ahb2: ahb2_clk,
271 ahb3: ahb3_clk,
272 apb1: apb1_clk,
273 apb2: apb2_clk,
274 apb1_tim: apb1_tim_clk,
275 apb2_tim: apb2_tim_clk,
276 rtc: rtc_clk,
277 rtc_hse: None,
278 }
279}
280
281pub(crate) fn configure_clocks(config: &Config) {
282 let rcc = crate::pac::RCC; 161 let rcc = crate::pac::RCC;
283 162
284 let needs_hsi = if let Some(pll_mux) = &config.mux { 163 let needs_hsi = if let Some(pll_mux) = &config.mux {
285 pll_mux.source == PllSource::Hsi 164 pll_mux.source == PllSource::HSI16
286 } else { 165 } else {
287 false 166 false
288 }; 167 };
289 168
290 if needs_hsi || config.sys == Sysclk::HSI { 169 if needs_hsi || config.sys == Sysclk::HSI16 {
291 rcc.cr().modify(|w| { 170 rcc.cr().modify(|w| {
292 w.set_hsion(true); 171 w.set_hsion(true);
293 }); 172 });
@@ -297,16 +176,12 @@ pub(crate) fn configure_clocks(config: &Config) {
297 176
298 rcc.cfgr().modify(|w| w.set_stopwuck(true)); 177 rcc.cfgr().modify(|w| w.set_stopwuck(true));
299 178
300 BackupDomain::configure_ls( 179 let rtc = config.ls.init();
301 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
302 config.lsi,
303 config.lse.map(|_| Default::default()),
304 );
305 180
306 match &config.hse { 181 match &config.hse {
307 Some(hse) => { 182 Some(hse) => {
308 rcc.cr().modify(|w| { 183 rcc.cr().modify(|w| {
309 w.set_hsepre(hse.prediv.into()); 184 w.set_hsepre(hse.prediv);
310 w.set_hseon(true); 185 w.set_hseon(true);
311 }); 186 });
312 187
@@ -328,18 +203,18 @@ pub(crate) fn configure_clocks(config: &Config) {
328 match &config.pll { 203 match &config.pll {
329 Some(pll) => { 204 Some(pll) => {
330 rcc.pllcfgr().modify(|w| { 205 rcc.pllcfgr().modify(|w| {
331 w.set_plln(pll.mul as u8); 206 w.set_plln(pll.mul);
332 pll.divp.map(|divp| { 207 pll.divp.map(|divp| {
333 w.set_pllpen(true); 208 w.set_pllpen(true);
334 w.set_pllp((divp - 1) as u8) 209 w.set_pllp(divp)
335 }); 210 });
336 pll.divq.map(|divq| { 211 pll.divq.map(|divq| {
337 w.set_pllqen(true); 212 w.set_pllqen(true);
338 w.set_pllq((divq - 1) as u8) 213 w.set_pllq(divq)
339 }); 214 });
340 pll.divr.map(|divr| { 215 pll.divr.map(|divr| {
341 // w.set_pllren(true); 216 w.set_pllren(true);
342 w.set_pllr((divr - 1) as u8); 217 w.set_pllr(divr);
343 }); 218 });
344 }); 219 });
345 220
@@ -350,15 +225,34 @@ pub(crate) fn configure_clocks(config: &Config) {
350 _ => {} 225 _ => {}
351 } 226 }
352 227
228 let _hsi48 = config.hsi48.then(|| {
229 rcc.crrcr().modify(|w| w.set_hsi48on(true));
230 while !rcc.crrcr().read().hsi48rdy() {}
231
232 Hertz(48_000_000)
233 });
234
353 rcc.cfgr().modify(|w| { 235 rcc.cfgr().modify(|w| {
354 w.set_sw(config.sys.into()); 236 w.set_sw(config.sys.into());
355 w.set_hpre(config.ahb1_pre.into()); 237 w.set_hpre(config.ahb1_pre);
356 w.set_ppre1(config.apb1_pre.into()); 238 w.set_ppre1(config.apb1_pre);
357 w.set_ppre2(config.apb2_pre.into()); 239 w.set_ppre2(config.apb2_pre);
358 }); 240 });
359 241
360 rcc.extcfgr().modify(|w| { 242 rcc.extcfgr().modify(|w| {
361 w.set_c2hpre(config.ahb2_pre.into()); 243 w.set_c2hpre(config.ahb2_pre);
362 w.set_shdhpre(config.ahb3_pre.into()); 244 w.set_shdhpre(config.ahb3_pre);
363 }); 245 });
246
247 set_freqs(Clocks {
248 sys: sys_clk,
249 hclk1: ahb1_clk,
250 hclk2: ahb2_clk,
251 hclk3: ahb3_clk,
252 pclk1: apb1_clk,
253 pclk2: apb2_clk,
254 pclk1_tim: apb1_tim_clk,
255 pclk2_tim: apb2_tim_clk,
256 rtc,
257 })
364} 258}
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index c5d7ab62f..72f653617 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -7,9 +7,6 @@ use crate::time::Hertz;
7/// HSI speed 7/// HSI speed
8pub const HSI_FREQ: Hertz = Hertz(16_000_000); 8pub const HSI_FREQ: Hertz = Hertz(16_000_000);
9 9
10/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(32_000);
12
13pub use crate::pac::pwr::vals::Vos as VoltageScale; 10pub use crate::pac::pwr::vals::Vos as VoltageScale;
14pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 11pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
15 12
@@ -28,7 +25,7 @@ pub enum PllSrc {
28impl Into<Pllsrc> for PllSrc { 25impl Into<Pllsrc> for PllSrc {
29 fn into(self) -> Pllsrc { 26 fn into(self) -> Pllsrc {
30 match self { 27 match self {
31 PllSrc::HSE(..) => Pllsrc::HSE32, 28 PllSrc::HSE(..) => Pllsrc::HSE,
32 PllSrc::HSI16 => Pllsrc::HSI16, 29 PllSrc::HSI16 => Pllsrc::HSI16,
33 } 30 }
34 } 31 }
@@ -37,19 +34,19 @@ impl Into<Pllsrc> for PllSrc {
37impl Into<Sw> for ClockSrc { 34impl Into<Sw> for ClockSrc {
38 fn into(self) -> Sw { 35 fn into(self) -> Sw {
39 match self { 36 match self {
40 ClockSrc::HSE(..) => Sw::HSE32, 37 ClockSrc::HSE(..) => Sw::HSE,
41 ClockSrc::HSI16 => Sw::HSI16, 38 ClockSrc::HSI16 => Sw::HSI16,
42 } 39 }
43 } 40 }
44} 41}
45 42
46#[derive(Copy, Clone)]
47pub struct Config { 43pub struct Config {
48 pub mux: ClockSrc, 44 pub mux: ClockSrc,
49 pub ahb_pre: AHBPrescaler, 45 pub ahb_pre: AHBPrescaler,
50 pub apb1_pre: APBPrescaler, 46 pub apb1_pre: APBPrescaler,
51 pub apb2_pre: APBPrescaler, 47 pub apb2_pre: APBPrescaler,
52 pub apb7_pre: APBPrescaler, 48 pub apb7_pre: APBPrescaler,
49 pub ls: super::LsConfig,
53} 50}
54 51
55impl Default for Config { 52impl Default for Config {
@@ -60,6 +57,7 @@ impl Default for Config {
60 apb1_pre: APBPrescaler::DIV1, 57 apb1_pre: APBPrescaler::DIV1,
61 apb2_pre: APBPrescaler::DIV1, 58 apb2_pre: APBPrescaler::DIV1,
62 apb7_pre: APBPrescaler::DIV1, 59 apb7_pre: APBPrescaler::DIV1,
60 ls: Default::default(),
63 } 61 }
64 } 62 }
65} 63}
@@ -108,13 +106,13 @@ pub(crate) unsafe fn init(config: Config) {
108 }); 106 });
109 107
110 RCC.cfgr2().modify(|w| { 108 RCC.cfgr2().modify(|w| {
111 w.set_hpre(config.ahb_pre.into()); 109 w.set_hpre(config.ahb_pre);
112 w.set_ppre1(config.apb1_pre.into()); 110 w.set_ppre1(config.apb1_pre);
113 w.set_ppre2(config.apb2_pre.into()); 111 w.set_ppre2(config.apb2_pre);
114 }); 112 });
115 113
116 RCC.cfgr3().modify(|w| { 114 RCC.cfgr3().modify(|w| {
117 w.set_ppre7(config.apb7_pre.into()); 115 w.set_ppre7(config.apb7_pre);
118 }); 116 });
119 117
120 let ahb_freq = sys_clk / config.ahb_pre; 118 let ahb_freq = sys_clk / config.ahb_pre;
@@ -140,15 +138,18 @@ pub(crate) unsafe fn init(config: Config) {
140 } 138 }
141 }; 139 };
142 140
141 let rtc = config.ls.init();
142
143 set_freqs(Clocks { 143 set_freqs(Clocks {
144 sys: sys_clk, 144 sys: sys_clk,
145 ahb1: ahb_freq, 145 hclk1: ahb_freq,
146 ahb2: ahb_freq, 146 hclk2: ahb_freq,
147 ahb4: ahb_freq, 147 hclk4: ahb_freq,
148 apb1: apb1_freq, 148 pclk1: apb1_freq,
149 apb2: apb2_freq, 149 pclk2: apb2_freq,
150 apb7: apb7_freq, 150 pclk7: apb7_freq,
151 apb1_tim: apb1_tim_freq, 151 pclk1_tim: apb1_tim_freq,
152 apb2_tim: apb2_tim_freq, 152 pclk2_tim: apb2_tim_freq,
153 rtc,
153 }); 154 });
154} 155}
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
index 6643d278a..c1f6a6b1e 100644
--- a/embassy-stm32/src/rcc/wl.rs
+++ b/embassy-stm32/src/rcc/wl.rs
@@ -1,136 +1,27 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler};
2pub use crate::pac::pwr::vals::Vos as VoltageScale; 1pub use crate::pac::pwr::vals::Vos as VoltageScale;
3use crate::pac::rcc::vals::Adcsel; 2use crate::pac::rcc::vals::Sw;
3pub use crate::pac::rcc::vals::{
4 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
5 Pllsrc as PllSource, Ppre as APBPrescaler,
6};
4use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
5use crate::rcc::bd::{BackupDomain, RtcClockSource};
6use crate::rcc::{set_freqs, Clocks}; 8use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz; 9use crate::time::Hertz;
8 10
9/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
10/// and with the addition of the init function to configure a system clock.
11
12/// Only the basic setup using the HSE and HSI clocks are supported as of now.
13
14/// HSI speed 11/// HSI speed
15pub const HSI_FREQ: Hertz = Hertz(16_000_000); 12pub const HSI_FREQ: Hertz = Hertz(16_000_000);
16 13
17/// LSI speed 14/// HSE speed
18pub const LSI_FREQ: Hertz = Hertz(32_000); 15pub const HSE_FREQ: Hertz = Hertz(32_000_000);
19
20/// HSE32 speed
21pub const HSE32_FREQ: Hertz = Hertz(32_000_000);
22 16
23/// System clock mux source 17/// System clock mux source
24#[derive(Clone, Copy)] 18#[derive(Clone, Copy)]
25pub enum ClockSrc { 19pub enum ClockSrc {
26 MSI(MSIRange), 20 MSI(MSIRange),
27 HSE32, 21 HSE,
28 HSI16, 22 HSI16,
29} 23}
30 24
31#[derive(Clone, Copy, PartialOrd, PartialEq)]
32pub enum MSIRange {
33 /// Around 100 kHz
34 Range0,
35 /// Around 200 kHz
36 Range1,
37 /// Around 400 kHz
38 Range2,
39 /// Around 800 kHz
40 Range3,
41 /// Around 1 MHz
42 Range4,
43 /// Around 2 MHz
44 Range5,
45 /// Around 4 MHz (reset value)
46 Range6,
47 /// Around 8 MHz
48 Range7,
49 /// Around 16 MHz
50 Range8,
51 /// Around 24 MHz
52 Range9,
53 /// Around 32 MHz
54 Range10,
55 /// Around 48 MHz
56 Range11,
57}
58
59impl MSIRange {
60 fn freq(&self) -> u32 {
61 match self {
62 MSIRange::Range0 => 100_000,
63 MSIRange::Range1 => 200_000,
64 MSIRange::Range2 => 400_000,
65 MSIRange::Range3 => 800_000,
66 MSIRange::Range4 => 1_000_000,
67 MSIRange::Range5 => 2_000_000,
68 MSIRange::Range6 => 4_000_000,
69 MSIRange::Range7 => 8_000_000,
70 MSIRange::Range8 => 16_000_000,
71 MSIRange::Range9 => 24_000_000,
72 MSIRange::Range10 => 32_000_000,
73 MSIRange::Range11 => 48_000_000,
74 }
75 }
76
77 fn vos(&self) -> VoltageScale {
78 if self > &MSIRange::Range8 {
79 VoltageScale::RANGE1
80 } else {
81 VoltageScale::RANGE2
82 }
83 }
84}
85
86impl Default for MSIRange {
87 fn default() -> MSIRange {
88 MSIRange::Range6
89 }
90}
91
92impl Into<u8> for MSIRange {
93 fn into(self) -> u8 {
94 match self {
95 MSIRange::Range0 => 0b0000,
96 MSIRange::Range1 => 0b0001,
97 MSIRange::Range2 => 0b0010,
98 MSIRange::Range3 => 0b0011,
99 MSIRange::Range4 => 0b0100,
100 MSIRange::Range5 => 0b0101,
101 MSIRange::Range6 => 0b0110,
102 MSIRange::Range7 => 0b0111,
103 MSIRange::Range8 => 0b1000,
104 MSIRange::Range9 => 0b1001,
105 MSIRange::Range10 => 0b1010,
106 MSIRange::Range11 => 0b1011,
107 }
108 }
109}
110
111#[derive(Clone, Copy)]
112pub enum AdcClockSource {
113 HSI16,
114 PLLPCLK,
115 SYSCLK,
116}
117
118impl AdcClockSource {
119 pub fn adcsel(&self) -> Adcsel {
120 match self {
121 AdcClockSource::HSI16 => Adcsel::HSI16,
122 AdcClockSource::PLLPCLK => Adcsel::PLLPCLK,
123 AdcClockSource::SYSCLK => Adcsel::SYSCLK,
124 }
125 }
126}
127
128impl Default for AdcClockSource {
129 fn default() -> Self {
130 Self::HSI16
131 }
132}
133
134/// Clocks configutation 25/// Clocks configutation
135pub struct Config { 26pub struct Config {
136 pub mux: ClockSrc, 27 pub mux: ClockSrc,
@@ -138,91 +29,60 @@ pub struct Config {
138 pub shd_ahb_pre: AHBPrescaler, 29 pub shd_ahb_pre: AHBPrescaler,
139 pub apb1_pre: APBPrescaler, 30 pub apb1_pre: APBPrescaler,
140 pub apb2_pre: APBPrescaler, 31 pub apb2_pre: APBPrescaler,
141 pub rtc_mux: RtcClockSource,
142 pub lse: Option<Hertz>,
143 pub lsi: bool,
144 pub adc_clock_source: AdcClockSource, 32 pub adc_clock_source: AdcClockSource,
33 pub ls: super::LsConfig,
145} 34}
146 35
147impl Default for Config { 36impl Default for Config {
148 #[inline] 37 #[inline]
149 fn default() -> Config { 38 fn default() -> Config {
150 Config { 39 Config {
151 mux: ClockSrc::MSI(MSIRange::default()), 40 mux: ClockSrc::MSI(MSIRange::RANGE4M),
152 ahb_pre: AHBPrescaler::DIV1, 41 ahb_pre: AHBPrescaler::DIV1,
153 shd_ahb_pre: AHBPrescaler::DIV1, 42 shd_ahb_pre: AHBPrescaler::DIV1,
154 apb1_pre: APBPrescaler::DIV1, 43 apb1_pre: APBPrescaler::DIV1,
155 apb2_pre: APBPrescaler::DIV1, 44 apb2_pre: APBPrescaler::DIV1,
156 rtc_mux: RtcClockSource::LSI, 45 adc_clock_source: AdcClockSource::HSI16,
157 lsi: true, 46 ls: Default::default(),
158 lse: None,
159 adc_clock_source: AdcClockSource::default(),
160 } 47 }
161 } 48 }
162} 49}
163 50
164#[repr(u8)]
165pub enum Lsedrv {
166 Low = 0,
167 MediumLow = 1,
168 MediumHigh = 2,
169 High = 3,
170}
171
172pub(crate) unsafe fn init(config: Config) { 51pub(crate) unsafe fn init(config: Config) {
173 let (sys_clk, sw, vos) = match config.mux { 52 let (sys_clk, sw, vos) = match config.mux {
174 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::RANGE2), 53 ClockSrc::HSI16 => (HSI_FREQ, Sw::HSI16, VoltageScale::RANGE2),
175 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::RANGE1), 54 ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1),
176 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), 55 ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
177 };
178
179 let ahb_freq: u32 = match config.ahb_pre {
180 AHBPrescaler::DIV1 => sys_clk,
181 pre => {
182 let pre: u8 = pre.into();
183 let pre = 1 << (pre as u32 - 7);
184 sys_clk / pre
185 }
186 }; 56 };
187 57
188 let shd_ahb_freq: u32 = match config.shd_ahb_pre { 58 let ahb_freq = sys_clk / config.ahb_pre;
189 AHBPrescaler::DIV1 => sys_clk, 59 let shd_ahb_freq = sys_clk / config.shd_ahb_pre;
190 pre => {
191 let pre: u8 = pre.into();
192 let pre = 1 << (pre as u32 - 7);
193 sys_clk / pre
194 }
195 };
196 60
197 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 61 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
198 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 62 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
199 pre => { 63 pre => {
200 let pre: u8 = pre.into(); 64 let freq = ahb_freq / pre;
201 let pre: u8 = 1 << (pre - 3); 65 (freq, freq * 2u32)
202 let freq = ahb_freq / pre as u32;
203 (freq, freq * 2)
204 } 66 }
205 }; 67 };
206 68
207 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 69 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
208 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 70 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
209 pre => { 71 pre => {
210 let pre: u8 = pre.into(); 72 let freq = ahb_freq / pre;
211 let pre: u8 = 1 << (pre - 3); 73 (freq, freq * 2u32)
212 let freq = ahb_freq / pre as u32;
213 (freq, freq * 2)
214 } 74 }
215 }; 75 };
216 76
217 // Adjust flash latency 77 // Adjust flash latency
218 let flash_clk_src_freq: u32 = shd_ahb_freq; 78 let flash_clk_src_freq = shd_ahb_freq;
219 let ws = match vos { 79 let ws = match vos {
220 VoltageScale::RANGE1 => match flash_clk_src_freq { 80 VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
221 0..=18_000_000 => 0b000, 81 0..=18_000_000 => 0b000,
222 18_000_001..=36_000_000 => 0b001, 82 18_000_001..=36_000_000 => 0b001,
223 _ => 0b010, 83 _ => 0b010,
224 }, 84 },
225 VoltageScale::RANGE2 => match flash_clk_src_freq { 85 VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
226 0..=6_000_000 => 0b000, 86 0..=6_000_000 => 0b000,
227 6_000_001..=12_000_000 => 0b001, 87 6_000_001..=12_000_000 => 0b001,
228 _ => 0b010, 88 _ => 0b010,
@@ -236,17 +96,14 @@ pub(crate) unsafe fn init(config: Config) {
236 96
237 while FLASH.acr().read().latency() != ws {} 97 while FLASH.acr().read().latency() != ws {}
238 98
239 // Enables the LSI if configured
240 BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default()));
241
242 match config.mux { 99 match config.mux {
243 ClockSrc::HSI16 => { 100 ClockSrc::HSI16 => {
244 // Enable HSI16 101 // Enable HSI16
245 RCC.cr().write(|w| w.set_hsion(true)); 102 RCC.cr().write(|w| w.set_hsion(true));
246 while !RCC.cr().read().hsirdy() {} 103 while !RCC.cr().read().hsirdy() {}
247 } 104 }
248 ClockSrc::HSE32 => { 105 ClockSrc::HSE => {
249 // Enable HSE32 106 // Enable HSE
250 RCC.cr().write(|w| { 107 RCC.cr().write(|w| {
251 w.set_hsebyppwr(true); 108 w.set_hsebyppwr(true);
252 w.set_hseon(true); 109 w.set_hseon(true);
@@ -258,49 +115,70 @@ pub(crate) unsafe fn init(config: Config) {
258 assert!(!cr.msion() || cr.msirdy()); 115 assert!(!cr.msion() || cr.msirdy());
259 RCC.cr().write(|w| { 116 RCC.cr().write(|w| {
260 w.set_msirgsel(true); 117 w.set_msirgsel(true);
261 w.set_msirange(range.into()); 118 w.set_msirange(range);
262 w.set_msion(true); 119 w.set_msion(true);
263 120
264 if let RtcClockSource::LSE = config.rtc_mux { 121 // If LSE is enabled, enable calibration of MSI
265 // If LSE is enabled, enable calibration of MSI 122 w.set_msipllen(config.ls.lse.is_some());
266 w.set_msipllen(true);
267 } else {
268 w.set_msipllen(false);
269 }
270 }); 123 });
271 while !RCC.cr().read().msirdy() {} 124 while !RCC.cr().read().msirdy() {}
272 } 125 }
273 } 126 }
274 127
275 RCC.extcfgr().modify(|w| { 128 RCC.extcfgr().modify(|w| {
276 if config.shd_ahb_pre == AHBPrescaler::DIV1 { 129 w.set_shdhpre(config.shd_ahb_pre);
277 w.set_shdhpre(0);
278 } else {
279 w.set_shdhpre(config.shd_ahb_pre.into());
280 }
281 }); 130 });
282 131
283 RCC.cfgr().modify(|w| { 132 RCC.cfgr().modify(|w| {
284 w.set_sw(sw.into()); 133 w.set_sw(sw.into());
285 w.set_hpre(config.ahb_pre); 134 w.set_hpre(config.ahb_pre);
286 w.set_ppre1(config.apb1_pre.into()); 135 w.set_ppre1(config.apb1_pre);
287 w.set_ppre2(config.apb2_pre.into()); 136 w.set_ppre2(config.apb2_pre);
288 }); 137 });
289 138
290 // ADC clock MUX 139 // ADC clock MUX
291 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel())); 140 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
292 141
293 // TODO: switch voltage range 142 // TODO: switch voltage range
294 143
144 let rtc = config.ls.init();
145
295 set_freqs(Clocks { 146 set_freqs(Clocks {
296 sys: Hertz(sys_clk), 147 sys: sys_clk,
297 ahb1: Hertz(ahb_freq), 148 hclk1: ahb_freq,
298 ahb2: Hertz(ahb_freq), 149 hclk2: ahb_freq,
299 ahb3: Hertz(shd_ahb_freq), 150 hclk3: shd_ahb_freq,
300 apb1: Hertz(apb1_freq), 151 pclk1: apb1_freq,
301 apb2: Hertz(apb2_freq), 152 pclk2: apb2_freq,
302 apb3: Hertz(shd_ahb_freq), 153 pclk3: shd_ahb_freq,
303 apb1_tim: Hertz(apb1_tim_freq), 154 pclk1_tim: apb1_tim_freq,
304 apb2_tim: Hertz(apb2_tim_freq), 155 pclk2_tim: apb2_tim_freq,
156 rtc,
305 }); 157 });
306} 158}
159
160fn msirange_to_hertz(range: MSIRange) -> Hertz {
161 match range {
162 MSIRange::RANGE100K => Hertz(100_000),
163 MSIRange::RANGE200K => Hertz(200_000),
164 MSIRange::RANGE400K => Hertz(400_000),
165 MSIRange::RANGE800K => Hertz(800_000),
166 MSIRange::RANGE1M => Hertz(1_000_000),
167 MSIRange::RANGE2M => Hertz(2_000_000),
168 MSIRange::RANGE4M => Hertz(4_000_000),
169 MSIRange::RANGE8M => Hertz(8_000_000),
170 MSIRange::RANGE16M => Hertz(16_000_000),
171 MSIRange::RANGE24M => Hertz(24_000_000),
172 MSIRange::RANGE32M => Hertz(32_000_000),
173 MSIRange::RANGE48M => Hertz(48_000_000),
174 _ => unreachable!(),
175 }
176}
177
178fn msirange_to_vos(range: MSIRange) -> VoltageScale {
179 if range.to_bits() > MSIRange::RANGE16M.to_bits() {
180 VoltageScale::RANGE1
181 } else {
182 VoltageScale::RANGE2
183 }
184}
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 0979dce8c..5e6922e9b 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -13,6 +13,7 @@ use crate::{interrupt, pac, peripherals, Peripheral};
13 13
14static RNG_WAKER: AtomicWaker = AtomicWaker::new(); 14static RNG_WAKER: AtomicWaker = AtomicWaker::new();
15 15
16#[derive(Debug, PartialEq, Eq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))] 17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub enum Error { 18pub enum Error {
18 SeedError, 19 SeedError,
@@ -42,8 +43,7 @@ impl<'d, T: Instance> Rng<'d, T> {
42 inner: impl Peripheral<P = T> + 'd, 43 inner: impl Peripheral<P = T> + 'd,
43 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 44 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
44 ) -> Self { 45 ) -> Self {
45 T::enable(); 46 T::enable_and_reset();
46 T::reset();
47 into_ref!(inner); 47 into_ref!(inner);
48 let mut random = Self { _inner: inner }; 48 let mut random = Self { _inner: inner };
49 random.reset(); 49 random.reset();
@@ -85,7 +85,7 @@ impl<'d, T: Instance> Rng<'d, T> {
85 reg.set_ie(false); 85 reg.set_ie(false);
86 reg.set_rngen(true); 86 reg.set_rngen(true);
87 }); 87 });
88 T::regs().cr().write(|reg| { 88 T::regs().cr().modify(|reg| {
89 reg.set_ced(false); 89 reg.set_ced(false);
90 }); 90 });
91 // wait for CONDRST to be set 91 // wait for CONDRST to be set
@@ -164,7 +164,7 @@ impl<'d, T: Instance> Rng<'d, T> {
164 return Err(Error::SeedError); 164 return Err(Error::SeedError);
165 } 165 }
166 // write bytes to chunk 166 // write bytes to chunk
167 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) { 167 for (dest, src) in chunk.iter_mut().zip(random_word.to_ne_bytes().iter()) {
168 *dest = *src 168 *dest = *src
169 } 169 }
170 } 170 }
@@ -195,7 +195,7 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> {
195 fn fill_bytes(&mut self, dest: &mut [u8]) { 195 fn fill_bytes(&mut self, dest: &mut [u8]) {
196 for chunk in dest.chunks_mut(4) { 196 for chunk in dest.chunks_mut(4) {
197 let rand = self.next_u32(); 197 let rand = self.next_u32();
198 for (slot, num) in chunk.iter_mut().zip(rand.to_be_bytes().iter()) { 198 for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) {
199 *slot = *num 199 *slot = *num
200 } 200 }
201 } 201 }
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 73b78f253..552dcc76f 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
10use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11 11
12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
13pub use crate::rcc::RtcClockSource;
14use crate::time::Hertz; 13use crate::time::Hertz;
15 14
16/// refer to AN4759 to compare features of RTC2 and RTC3 15/// refer to AN4759 to compare features of RTC2 and RTC3
@@ -93,21 +92,50 @@ impl RtcTimeProvider {
93 /// 92 ///
94 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. 93 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
95 pub fn now(&self) -> Result<DateTime, RtcError> { 94 pub fn now(&self) -> Result<DateTime, RtcError> {
96 let r = RTC::regs(); 95 // For RM0433 we use BYPSHAD=1 to work around errata ES0392 2.19.1
97 let tr = r.tr().read(); 96 #[cfg(rcc_h7rm0433)]
98 let second = bcd2_to_byte((tr.st(), tr.su())); 97 loop {
99 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 98 let r = RTC::regs();
100 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 99 let ss = r.ssr().read().ss();
101 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order 100 let dr = r.dr().read();
102 // calendar shadow registers until RTC_DR is read. 101 let tr = r.tr().read();
103 let dr = r.dr().read(); 102
104 103 // If an RTCCLK edge occurs during read we may see inconsistent values
105 let weekday = dr.wdu(); 104 // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9)
106 let day = bcd2_to_byte((dr.dt(), dr.du())); 105 let ss_after = r.ssr().read().ss();
107 let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); 106 if ss == ss_after {
108 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; 107 let second = bcd2_to_byte((tr.st(), tr.su()));
109 108 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
110 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) 109 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
110
111 let weekday = dr.wdu();
112 let day = bcd2_to_byte((dr.dt(), dr.du()));
113 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
114 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
115
116 return self::datetime::datetime(year, month, day, weekday, hour, minute, second)
117 .map_err(RtcError::InvalidDateTime);
118 }
119 }
120
121 #[cfg(not(rcc_h7rm0433))]
122 {
123 let r = RTC::regs();
124 let tr = r.tr().read();
125 let second = bcd2_to_byte((tr.st(), tr.su()));
126 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
127 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
128 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order
129 // calendar shadow registers until RTC_DR is read.
130 let dr = r.dr().read();
131
132 let weekday = dr.wdu();
133 let day = bcd2_to_byte((dr.dt(), dr.du()));
134 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
135 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
136
137 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
138 }
111 } 139 }
112} 140}
113 141
@@ -155,8 +183,8 @@ impl Default for RtcCalibrationCyclePeriod {
155 183
156impl Rtc { 184impl Rtc {
157 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 185 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
158 #[cfg(any(rcc_wle, rcc_wl5, rcc_g4, rcc_g0, rtc_v2l4, rtc_v2wb))] 186 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
159 <RTC as crate::rcc::sealed::RccPeripheral>::enable(); 187 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
160 188
161 let mut this = Self { 189 let mut this = Self {
162 #[cfg(feature = "low-power")] 190 #[cfg(feature = "low-power")]
@@ -175,19 +203,8 @@ impl Rtc {
175 } 203 }
176 204
177 fn frequency() -> Hertz { 205 fn frequency() -> Hertz {
178 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
179 let freqs = unsafe { crate::rcc::get_freqs() }; 206 let freqs = unsafe { crate::rcc::get_freqs() };
180 207 freqs.rtc.unwrap()
181 // Load the clock frequency from the rcc mod, if supported
182 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
183 match freqs.rtc {
184 Some(hertz) => hertz,
185 None => freqs.rtc_hse.unwrap(),
186 }
187
188 // Assume the default value, if not supported
189 #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))]
190 Hertz(32_768)
191 } 208 }
192 209
193 /// Acquire a [`RtcTimeProvider`] instance. 210 /// Acquire a [`RtcTimeProvider`] instance.
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 4608d3114..eeb23e1f1 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -112,25 +112,26 @@ impl super::Rtc {
112 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { 112 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
113 use crate::interrupt::typelevel::Interrupt; 113 use crate::interrupt::typelevel::Interrupt;
114 114
115 trace!("rtc: stop wakeup alarm at {}", self.instant()); 115 if RTC::regs().cr().read().wute() {
116 trace!("rtc: stop wakeup alarm at {}", self.instant());
116 117
117 self.write(false, |regs| { 118 self.write(false, |regs| {
118 regs.cr().modify(|w| w.set_wutie(false)); 119 regs.cr().modify(|w| w.set_wutie(false));
119 regs.cr().modify(|w| w.set_wute(false)); 120 regs.cr().modify(|w| w.set_wute(false));
120 regs.isr().modify(|w| w.set_wutf(false)); 121 regs.isr().modify(|w| w.set_wutf(false));
121 122
122 crate::pac::EXTI 123 crate::pac::EXTI
123 .pr(0) 124 .pr(0)
124 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); 125 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
125
126 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
127 });
128 126
129 if let Some(stop_time) = self.stop_time.borrow(cs).take() { 127 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
130 Some(self.instant() - stop_time) 128 });
131 } else {
132 None
133 } 129 }
130
131 self.stop_time
132 .borrow(cs)
133 .take()
134 .map(|stop_time| self.instant() - stop_time)
134 } 135 }
135 136
136 #[cfg(feature = "low-power")] 137 #[cfg(feature = "low-power")]
@@ -156,6 +157,8 @@ impl super::Rtc {
156 w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); 157 w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR);
157 w.set_osel(Osel::DISABLED); 158 w.set_osel(Osel::DISABLED);
158 w.set_pol(Pol::HIGH); 159 w.set_pol(Pol::HIGH);
160 #[cfg(rcc_h7rm0433)]
161 w.set_bypshad(true);
159 }); 162 });
160 163
161 rtc.prer().modify(|w| { 164 rtc.prer().modify(|w| {
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 4ffa6e9ce..a0b4ddac7 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -4,14 +4,14 @@ use embassy_embedded_hal::SetConfig;
4use embassy_hal_internal::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
5 5
6pub use crate::dma::word; 6pub use crate::dma::word;
7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; 7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
8use crate::gpio::sealed::{AFType, Pin as _}; 8use crate::gpio::sealed::{AFType, Pin as _};
9use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
10use crate::pac::sai::{vals, Sai as Regs}; 10use crate::pac::sai::{vals, Sai as Regs};
11use crate::rcc::RccPeripheral; 11use crate::rcc::RccPeripheral;
12use crate::{peripherals, Peripheral}; 12use crate::{peripherals, Peripheral};
13 13
14#[derive(Debug)] 14#[derive(Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))] 15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error { 16pub enum Error {
17 NotATransmitter, 17 NotATransmitter,
@@ -48,8 +48,8 @@ pub enum Mode {
48} 48}
49 49
50#[derive(Copy, Clone)] 50#[derive(Copy, Clone)]
51enum TxRx { 51pub enum TxRx {
52 Transmiter, 52 Transmitter,
53 Receiver, 53 Receiver,
54} 54}
55 55
@@ -57,7 +57,7 @@ impl Mode {
57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode { 58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
59 match tx_rx { 59 match tx_rx {
60 TxRx::Transmiter => match self { 60 TxRx::Transmitter => match self {
61 Mode::Master => vals::Mode::MASTERTX, 61 Mode::Master => vals::Mode::MASTERTX,
62 Mode::Slave => vals::Mode::SLAVETX, 62 Mode::Slave => vals::Mode::SLAVETX,
63 }, 63 },
@@ -206,12 +206,13 @@ impl Protocol {
206 } 206 }
207} 207}
208 208
209#[derive(Copy, Clone)] 209#[derive(Copy, Clone, PartialEq)]
210pub enum SyncEnable { 210pub enum SyncEnable {
211 Asynchronous, 211 Asynchronous,
212 /// Syncs with the other A/B sub-block within the SAI unit 212 /// Syncs with the other A/B sub-block within the SAI unit
213 Internal, 213 Internal,
214 /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input() 214 /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input()
215 #[cfg(any(sai_v4))]
215 External, 216 External,
216} 217}
217 218
@@ -221,6 +222,7 @@ impl SyncEnable {
221 match self { 222 match self {
222 SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, 223 SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS,
223 SyncEnable::Internal => vals::Syncen::INTERNAL, 224 SyncEnable::Internal => vals::Syncen::INTERNAL,
225 #[cfg(any(sai_v4))]
224 SyncEnable::External => vals::Syncen::EXTERNAL, 226 SyncEnable::External => vals::Syncen::EXTERNAL,
225 } 227 }
226 } 228 }
@@ -425,6 +427,7 @@ impl MasterClockDivider {
425#[derive(Copy, Clone)] 427#[derive(Copy, Clone)]
426pub struct Config { 428pub struct Config {
427 pub mode: Mode, 429 pub mode: Mode,
430 pub tx_rx: TxRx,
428 pub sync_enable: SyncEnable, 431 pub sync_enable: SyncEnable,
429 pub is_sync_output: bool, 432 pub is_sync_output: bool,
430 pub protocol: Protocol, 433 pub protocol: Protocol,
@@ -455,6 +458,7 @@ impl Default for Config {
455 fn default() -> Self { 458 fn default() -> Self {
456 Self { 459 Self {
457 mode: Mode::Master, 460 mode: Mode::Master,
461 tx_rx: TxRx::Transmitter,
458 is_sync_output: false, 462 is_sync_output: false,
459 sync_enable: SyncEnable::Asynchronous, 463 sync_enable: SyncEnable::Asynchronous,
460 protocol: Protocol::Free, 464 protocol: Protocol::Free,
@@ -498,43 +502,130 @@ impl Config {
498} 502}
499 503
500#[derive(Copy, Clone)] 504#[derive(Copy, Clone)]
501pub enum SubBlock { 505enum WhichSubBlock {
502 A = 0, 506 A = 0,
503 B = 1, 507 B = 1,
504} 508}
505 509
506enum RingBuffer<'d, C: Channel, W: word::Word> { 510enum RingBuffer<'d, C: Channel, W: word::Word> {
507 Writable(WritableRingBuffer<'d, C, W>), 511 Writable(WritableRingBuffer<'d, C, W>),
508 #[allow(dead_code)] // remove this after implementing new_* functions for receiver
509 Readable(ReadableRingBuffer<'d, C, W>), 512 Readable(ReadableRingBuffer<'d, C, W>),
510} 513}
511 514
512#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 515#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
513fn wdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { 516fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut W {
514 let ch = w.ch(sub_block as usize); 517 let ch = w.ch(sub_block as usize);
515 ch.dr().as_ptr() as _ 518 ch.dr().as_ptr() as _
516} 519}
517 520
518pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { 521pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> {
519 _peri: PeripheralRef<'d, T>, 522 _peri: PeripheralRef<'d, T>,
520 sd: Option<PeripheralRef<'d, AnyPin>>, 523 sd: Option<PeripheralRef<'d, AnyPin>>,
521 fs: Option<PeripheralRef<'d, AnyPin>>, 524 fs: Option<PeripheralRef<'d, AnyPin>>,
522 sck: Option<PeripheralRef<'d, AnyPin>>, 525 sck: Option<PeripheralRef<'d, AnyPin>>,
523 mclk: Option<PeripheralRef<'d, AnyPin>>, 526 mclk: Option<PeripheralRef<'d, AnyPin>>,
524 ring_buffer: RingBuffer<'d, C, W>, 527 ring_buffer: RingBuffer<'d, C, W>,
525 sub_block: SubBlock, 528 sub_block: WhichSubBlock,
529}
530
531pub struct SubBlockA {}
532pub struct SubBlockB {}
533
534pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>);
535pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>);
536
537pub struct Sai<'d, T: Instance> {
538 _peri: PeripheralRef<'d, T>,
539 sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>,
540 sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>,
526} 541}
527 542
528impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { 543// return the type for (sd, sck)
529 fn get_transmitter_af_types(mode: Mode) -> (AFType, AFType) { 544fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
545 (
546 //sd is defined by tx/rx mode
547 match tx_rx {
548 TxRx::Transmitter => AFType::OutputPushPull,
549 TxRx::Receiver => AFType::Input,
550 },
551 //clocks (mclk, sck and fs) are defined by master/slave
530 match mode { 552 match mode {
531 Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull), 553 Mode::Master => AFType::OutputPushPull,
532 Mode::Slave => (AFType::OutputPushPull, AFType::Input), 554 Mode::Slave => AFType::Input,
555 },
556 )
557}
558
559fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>(
560 dma: impl Peripheral<P = C> + 'd,
561 dma_buf: &'d mut [W],
562 request: Request,
563 sub_block: WhichSubBlock,
564 tx_rx: TxRx,
565) -> RingBuffer<'d, C, W> {
566 let opts = TransferOptions {
567 half_transfer_ir: true,
568 //the new_write() and new_read() always use circular mode
569 ..Default::default()
570 };
571 match tx_rx {
572 TxRx::Transmitter => RingBuffer::Writable(unsafe {
573 WritableRingBuffer::new_write(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
574 }),
575 TxRx::Receiver => RingBuffer::Readable(unsafe {
576 ReadableRingBuffer::new_read(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
577 }),
578 }
579}
580
581impl<'d, T: Instance> Sai<'d, T> {
582 pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self {
583 T::enable_and_reset();
584
585 Self {
586 _peri: unsafe { peri.clone_unchecked().into_ref() },
587 sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })),
588 sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())),
533 } 589 }
534 } 590 }
535 591
536 pub fn new_asynchronous_transmitter_with_mclk_a( 592 pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> {
537 peri: impl Peripheral<P = T> + 'd, 593 if self.sub_block_a_peri.is_some() {
594 self.sub_block_a_peri.take()
595 } else {
596 None
597 }
598 }
599
600 pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> {
601 if self.sub_block_b_peri.is_some() {
602 self.sub_block_b_peri.take()
603 } else {
604 None
605 }
606 }
607}
608
609fn update_synchronous_config(config: &mut Config) {
610 config.mode = Mode::Slave;
611 config.is_sync_output = false;
612
613 #[cfg(any(sai_v1, sai_v2, sai_v3))]
614 {
615 config.sync_enable = SyncEnable::Internal;
616 }
617
618 #[cfg(any(sai_v4))]
619 {
620 //this must either be Internal or External
621 //The asynchronous sub-block on the same SAI needs to enable is_sync_output
622 assert!(config.sync_enable != SyncEnable::Asynchronous);
623 }
624}
625
626impl SubBlockA {
627 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>(
628 peri: SubBlockAPeripheral<'d, T>,
538 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 629 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
539 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 630 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
540 fs: impl Peripheral<P = impl FsAPin<T>> + 'd, 631 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
@@ -542,37 +633,40 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
542 dma: impl Peripheral<P = C> + 'd, 633 dma: impl Peripheral<P = C> + 'd,
543 dma_buf: &'d mut [W], 634 dma_buf: &'d mut [W],
544 mut config: Config, 635 mut config: Config,
545 ) -> Self 636 ) -> SubBlock<'d, T, C, W>
546 where 637 where
547 C: Channel + DmaA<T>, 638 C: Channel + DmaA<T>,
548 { 639 {
549 into_ref!(mclk); 640 into_ref!(mclk);
550 641
551 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); 642 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
643
644 mclk.set_as_af(mclk.af_num(), ck_af_type);
552 mclk.set_speed(crate::gpio::Speed::VeryHigh); 645 mclk.set_speed(crate::gpio::Speed::VeryHigh);
553 646
554 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { 647 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
555 config.master_clock_divider = MasterClockDivider::Div1; 648 config.master_clock_divider = MasterClockDivider::Div1;
556 } 649 }
557 650
558 Self::new_asynchronous_transmitter_a(peri, sck, sd, fs, dma, dma_buf, config) 651 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
559 } 652 }
560 653
561 pub fn new_asynchronous_transmitter_a( 654 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
562 peri: impl Peripheral<P = T> + 'd, 655 peri: SubBlockAPeripheral<'d, T>,
563 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 656 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
564 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 657 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
565 fs: impl Peripheral<P = impl FsAPin<T>> + 'd, 658 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
566 dma: impl Peripheral<P = C> + 'd, 659 dma: impl Peripheral<P = C> + 'd,
567 dma_buf: &'d mut [W], 660 dma_buf: &'d mut [W],
568 config: Config, 661 config: Config,
569 ) -> Self 662 ) -> SubBlock<'d, T, C, W>
570 where 663 where
571 C: Channel + DmaA<T>, 664 C: Channel + DmaA<T>,
572 { 665 {
666 let peri = peri.0;
573 into_ref!(peri, dma, sck, sd, fs); 667 into_ref!(peri, dma, sck, sd, fs);
574 668
575 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); 669 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
576 sd.set_as_af(sd.af_num(), sd_af_type); 670 sd.set_as_af(sd.af_num(), sd_af_type);
577 sd.set_speed(crate::gpio::Speed::VeryHigh); 671 sd.set_speed(crate::gpio::Speed::VeryHigh);
578 672
@@ -581,31 +675,60 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
581 fs.set_as_af(fs.af_num(), ck_af_type); 675 fs.set_as_af(fs.af_num(), ck_af_type);
582 fs.set_speed(crate::gpio::Speed::VeryHigh); 676 fs.set_speed(crate::gpio::Speed::VeryHigh);
583 677
678 let sub_block = WhichSubBlock::A;
584 let request = dma.request(); 679 let request = dma.request();
585 let opts = TransferOptions {
586 half_transfer_ir: true,
587 circular: true,
588 ..Default::default()
589 };
590
591 let sub_block = SubBlock::A;
592 680
593 Self::new_inner( 681 SubBlock::new_inner(
594 peri, 682 peri,
595 sub_block, 683 sub_block,
596 Some(sck.map_into()), 684 Some(sck.map_into()),
597 None, 685 None,
598 Some(sd.map_into()), 686 Some(sd.map_into()),
599 Some(fs.map_into()), 687 Some(fs.map_into()),
600 RingBuffer::Writable(unsafe { 688 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
601 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts)
602 }),
603 config, 689 config,
604 ) 690 )
605 } 691 }
606 692
607 pub fn new_asynchronous_transmitter_with_mclk_b( 693 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
608 peri: impl Peripheral<P = T> + 'd, 694 peri: SubBlockAPeripheral<'d, T>,
695 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
696 dma: impl Peripheral<P = C> + 'd,
697 dma_buf: &'d mut [W],
698 mut config: Config,
699 ) -> SubBlock<'d, T, C, W>
700 where
701 C: Channel + DmaA<T>,
702 {
703 update_synchronous_config(&mut config);
704
705 let peri = peri.0;
706 into_ref!(dma, peri, sd);
707
708 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
709
710 sd.set_as_af(sd.af_num(), sd_af_type);
711 sd.set_speed(crate::gpio::Speed::VeryHigh);
712
713 let sub_block = WhichSubBlock::A;
714 let request = dma.request();
715
716 SubBlock::new_inner(
717 peri,
718 sub_block,
719 None,
720 None,
721 Some(sd.map_into()),
722 None,
723 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
724 config,
725 )
726 }
727}
728
729impl SubBlockB {
730 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>(
731 peri: SubBlockBPeripheral<'d, T>,
609 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 732 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
610 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 733 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
611 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 734 fs: impl Peripheral<P = impl FsBPin<T>> + 'd,
@@ -613,37 +736,40 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
613 dma: impl Peripheral<P = C> + 'd, 736 dma: impl Peripheral<P = C> + 'd,
614 dma_buf: &'d mut [W], 737 dma_buf: &'d mut [W],
615 mut config: Config, 738 mut config: Config,
616 ) -> Self 739 ) -> SubBlock<'d, T, C, W>
617 where 740 where
618 C: Channel + DmaB<T>, 741 C: Channel + DmaB<T>,
619 { 742 {
620 into_ref!(mclk); 743 into_ref!(mclk);
621 744
622 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); 745 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
746
747 mclk.set_as_af(mclk.af_num(), ck_af_type);
623 mclk.set_speed(crate::gpio::Speed::VeryHigh); 748 mclk.set_speed(crate::gpio::Speed::VeryHigh);
624 749
625 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { 750 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
626 config.master_clock_divider = MasterClockDivider::Div1; 751 config.master_clock_divider = MasterClockDivider::Div1;
627 } 752 }
628 753
629 Self::new_asynchronous_transmitter_b(peri, sck, sd, fs, dma, dma_buf, config) 754 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
630 } 755 }
631 756
632 pub fn new_asynchronous_transmitter_b( 757 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
633 peri: impl Peripheral<P = T> + 'd, 758 peri: SubBlockBPeripheral<'d, T>,
634 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 759 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
635 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 760 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
636 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 761 fs: impl Peripheral<P = impl FsBPin<T>> + 'd,
637 dma: impl Peripheral<P = C> + 'd, 762 dma: impl Peripheral<P = C> + 'd,
638 dma_buf: &'d mut [W], 763 dma_buf: &'d mut [W],
639 config: Config, 764 config: Config,
640 ) -> Self 765 ) -> SubBlock<'d, T, C, W>
641 where 766 where
642 C: Channel + DmaB<T>, 767 C: Channel + DmaB<T>,
643 { 768 {
769 let peri = peri.0;
644 into_ref!(dma, peri, sck, sd, fs); 770 into_ref!(dma, peri, sck, sd, fs);
645 771
646 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); 772 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
647 773
648 sd.set_as_af(sd.af_num(), sd_af_type); 774 sd.set_as_af(sd.af_num(), sd_af_type);
649 sd.set_speed(crate::gpio::Speed::VeryHigh); 775 sd.set_speed(crate::gpio::Speed::VeryHigh);
@@ -653,28 +779,57 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
653 fs.set_as_af(fs.af_num(), ck_af_type); 779 fs.set_as_af(fs.af_num(), ck_af_type);
654 fs.set_speed(crate::gpio::Speed::VeryHigh); 780 fs.set_speed(crate::gpio::Speed::VeryHigh);
655 781
782 let sub_block = WhichSubBlock::B;
656 let request = dma.request(); 783 let request = dma.request();
657 let opts = TransferOptions {
658 half_transfer_ir: true,
659 ..Default::default()
660 };
661
662 let sub_block = SubBlock::B;
663 784
664 Self::new_inner( 785 SubBlock::new_inner(
665 peri, 786 peri,
666 sub_block, 787 sub_block,
667 Some(sck.map_into()), 788 Some(sck.map_into()),
668 None, 789 None,
669 Some(sd.map_into()), 790 Some(sd.map_into()),
670 Some(fs.map_into()), 791 Some(fs.map_into()),
671 RingBuffer::Writable(unsafe { 792 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
672 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) 793 config,
673 }), 794 )
795 }
796
797 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
798 peri: SubBlockBPeripheral<'d, T>,
799 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
800 dma: impl Peripheral<P = C> + 'd,
801 dma_buf: &'d mut [W],
802 mut config: Config,
803 ) -> SubBlock<'d, T, C, W>
804 where
805 C: Channel + DmaB<T>,
806 {
807 update_synchronous_config(&mut config);
808 let peri = peri.0;
809 into_ref!(dma, peri, sd);
810
811 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
812
813 sd.set_as_af(sd.af_num(), sd_af_type);
814 sd.set_speed(crate::gpio::Speed::VeryHigh);
815
816 let sub_block = WhichSubBlock::B;
817 let request = dma.request();
818
819 SubBlock::new_inner(
820 peri,
821 sub_block,
822 None,
823 None,
824 Some(sd.map_into()),
825 None,
826 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
674 config, 827 config,
675 ) 828 )
676 } 829 }
830}
677 831
832impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
678 pub fn start(self: &mut Self) { 833 pub fn start(self: &mut Self) {
679 match self.ring_buffer { 834 match self.ring_buffer {
680 RingBuffer::Writable(ref mut rb) => { 835 RingBuffer::Writable(ref mut rb) => {
@@ -695,7 +850,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
695 850
696 fn new_inner( 851 fn new_inner(
697 peri: impl Peripheral<P = T> + 'd, 852 peri: impl Peripheral<P = T> + 'd,
698 sub_block: SubBlock, 853 sub_block: WhichSubBlock,
699 sck: Option<PeripheralRef<'d, AnyPin>>, 854 sck: Option<PeripheralRef<'d, AnyPin>>,
700 mclk: Option<PeripheralRef<'d, AnyPin>>, 855 mclk: Option<PeripheralRef<'d, AnyPin>>,
701 sd: Option<PeripheralRef<'d, AnyPin>>, 856 sd: Option<PeripheralRef<'d, AnyPin>>,
@@ -703,13 +858,18 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
703 ring_buffer: RingBuffer<'d, C, W>, 858 ring_buffer: RingBuffer<'d, C, W>,
704 config: Config, 859 config: Config,
705 ) -> Self { 860 ) -> Self {
706 T::enable(); 861 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
707 T::reset(); 862 {
863 let ch = T::REGS.ch(sub_block as usize);
864 ch.cr1().modify(|w| w.set_saien(false));
865 }
708 866
709 #[cfg(any(sai_v4))] 867 #[cfg(any(sai_v4))]
710 { 868 {
711 // Not totally clear from the datasheet if this is right 869 // Not totally clear from the datasheet if this is right
712 // This is only used if using SyncEnable::External 870 // This is only used if using SyncEnable::External on the other SAI unit
871 // Syncing from SAIX subblock A to subblock B does not require this
872 // Only syncing from SAI1 subblock A/B to SAI2 subblock A/B
713 let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { 873 let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() {
714 1 //this is SAI1, so sync with SAI2 874 1 //this is SAI1, so sync with SAI2
715 } else { 875 } else {
@@ -721,8 +881,8 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
721 881
722 if config.is_sync_output { 882 if config.is_sync_output {
723 let syncout: u8 = match sub_block { 883 let syncout: u8 = match sub_block {
724 SubBlock::A => 0b01, 884 WhichSubBlock::A => 0b01,
725 SubBlock::B => 0b10, 885 WhichSubBlock::B => 0b10,
726 }; 886 };
727 T::REGS.gcr().modify(|w| { 887 T::REGS.gcr().modify(|w| {
728 w.set_syncout(syncout); 888 w.set_syncout(syncout);
@@ -735,7 +895,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
735 let ch = T::REGS.ch(sub_block as usize); 895 let ch = T::REGS.ch(sub_block as usize);
736 ch.cr1().modify(|w| { 896 ch.cr1().modify(|w| {
737 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { 897 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) {
738 TxRx::Transmiter 898 TxRx::Transmitter
739 } else { 899 } else {
740 TxRx::Receiver 900 TxRx::Receiver
741 })); 901 }));
@@ -770,7 +930,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
770 w.set_fsoff(config.frame_sync_offset.fsoff()); 930 w.set_fsoff(config.frame_sync_offset.fsoff());
771 w.set_fspol(config.frame_sync_polarity.fspol()); 931 w.set_fspol(config.frame_sync_polarity.fspol());
772 w.set_fsdef(config.frame_sync_definition.fsdef()); 932 w.set_fsdef(config.frame_sync_definition.fsdef());
773 w.set_fsall(config.frame_sync_active_level_length.0 as u8); 933 w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1);
774 w.set_frl(config.frame_length - 1); 934 w.set_frl(config.frame_length - 1);
775 }); 935 });
776 936
@@ -782,6 +942,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
782 }); 942 });
783 943
784 ch.cr1().modify(|w| w.set_saien(true)); 944 ch.cr1().modify(|w| w.set_saien(true));
945
946 if ch.cr1().read().saien() == false {
947 panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)");
948 }
785 } 949 }
786 950
787 Self { 951 Self {
@@ -795,6 +959,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
795 } 959 }
796 } 960 }
797 961
962 pub fn reset() {
963 T::enable_and_reset();
964 }
965
798 pub fn flush(&mut self) { 966 pub fn flush(&mut self) {
799 let ch = T::REGS.ch(self.sub_block as usize); 967 let ch = T::REGS.ch(self.sub_block as usize);
800 ch.cr1().modify(|w| w.set_saien(false)); 968 ch.cr1().modify(|w| w.set_saien(false));
@@ -814,8 +982,9 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
814 ch.cr2().modify(|w| w.set_mute(value)); 982 ch.cr2().modify(|w| w.set_mute(value));
815 } 983 }
816 984
985 #[allow(dead_code)]
817 /// Reconfigures it with the supplied config. 986 /// Reconfigures it with the supplied config.
818 pub fn reconfigure(&mut self, _config: Config) {} 987 fn reconfigure(&mut self, _config: Config) {}
819 988
820 pub fn get_current_config(&self) -> Config { 989 pub fn get_current_config(&self) -> Config {
821 Config::default() 990 Config::default()
@@ -842,7 +1011,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
842 } 1011 }
843} 1012}
844 1013
845impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> { 1014impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> {
846 fn drop(&mut self) { 1015 fn drop(&mut self) {
847 let ch = T::REGS.ch(self.sub_block as usize); 1016 let ch = T::REGS.ch(self.sub_block as usize);
848 ch.cr1().modify(|w| w.set_saien(false)); 1017 ch.cr1().modify(|w| w.set_saien(false));
@@ -886,9 +1055,12 @@ foreach_peripheral!(
886 }; 1055 };
887); 1056);
888 1057
889impl<'d, T: Instance, C: Channel, W: word::Word> SetConfig for Sai<'d, T, C, W> { 1058impl<'d, T: Instance> SetConfig for Sai<'d, T> {
890 type Config = Config; 1059 type Config = Config;
891 fn set_config(&mut self, config: &Self::Config) { 1060 type ConfigError = ();
892 self.reconfigure(*config); 1061 fn set_config(&mut self, _config: &Self::Config) -> Result<(), ()> {
1062 // self.reconfigure(*config);
1063
1064 Ok(())
893 } 1065 }
894} 1066}
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 9fb380fd6..11ff24645 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -452,8 +452,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
452 ) -> Self { 452 ) -> Self {
453 into_ref!(sdmmc, dma); 453 into_ref!(sdmmc, dma);
454 454
455 T::enable(); 455 T::enable_and_reset();
456 T::reset();
457 456
458 T::Interrupt::unpend(); 457 T::Interrupt::unpend();
459 unsafe { T::Interrupt::enable() }; 458 unsafe { T::Interrupt::enable() };
@@ -1458,7 +1457,7 @@ cfg_if::cfg_if! {
1458 macro_rules! kernel_clk { 1457 macro_rules! kernel_clk {
1459 ($inst:ident) => { 1458 ($inst:ident) => {
1460 critical_section::with(|_| unsafe { 1459 critical_section::with(|_| unsafe {
1461 crate::rcc::get_freqs().pll48 1460 crate::rcc::get_freqs().pll1_q
1462 }).expect("PLL48 is required for SDIO") 1461 }).expect("PLL48 is required for SDIO")
1463 } 1462 }
1464 } 1463 }
@@ -1470,7 +1469,7 @@ cfg_if::cfg_if! {
1470 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK { 1469 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
1471 crate::rcc::get_freqs().sys 1470 crate::rcc::get_freqs().sys
1472 } else { 1471 } else {
1473 crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC") 1472 crate::rcc::get_freqs().pll1_q.expect("PLL48 is required for SDMMC")
1474 } 1473 }
1475 }) 1474 })
1476 }; 1475 };
@@ -1480,7 +1479,7 @@ cfg_if::cfg_if! {
1480 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK { 1479 if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYSCLK {
1481 crate::rcc::get_freqs().sys 1480 crate::rcc::get_freqs().sys
1482 } else { 1481 } else {
1483 crate::rcc::get_freqs().pll48.expect("PLL48 is required for SDMMC") 1482 crate::rcc::get_freqs().pll1_q.expect("PLL48 is required for SDMMC")
1484 } 1483 }
1485 }) 1484 })
1486 }; 1485 };
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index f40bce784..c391e0a5a 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -15,7 +15,7 @@ use crate::rcc::RccPeripheral;
15use crate::time::Hertz; 15use crate::time::Hertz;
16use crate::{peripherals, Peripheral}; 16use crate::{peripherals, Peripheral};
17 17
18#[derive(Debug)] 18#[derive(Debug, PartialEq, Eq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))] 19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum Error { 20pub enum Error {
21 Framing, 21 Framing,
@@ -230,8 +230,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
230 230
231 let lsbfirst = config.raw_byte_order(); 231 let lsbfirst = config.raw_byte_order();
232 232
233 T::enable(); 233 T::enable_and_reset();
234 T::reset();
235 234
236 #[cfg(any(spi_v1, spi_f1))] 235 #[cfg(any(spi_v1, spi_f1))]
237 { 236 {
@@ -323,7 +322,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
323 } 322 }
324 323
325 /// Reconfigures it with the supplied config. 324 /// Reconfigures it with the supplied config.
326 pub fn set_config(&mut self, config: Config) { 325 pub fn set_config(&mut self, config: &Config) -> Result<(), ()> {
327 let cpha = config.raw_phase(); 326 let cpha = config.raw_phase();
328 let cpol = config.raw_polarity(); 327 let cpol = config.raw_polarity();
329 328
@@ -352,6 +351,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
352 w.set_mbr(br); 351 w.set_mbr(br);
353 }); 352 });
354 } 353 }
354 Ok(())
355 } 355 }
356 356
357 pub fn get_current_config(&self) -> Config { 357 pub fn get_current_config(&self) -> Config {
@@ -1061,7 +1061,8 @@ foreach_peripheral!(
1061 1061
1062impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> { 1062impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> {
1063 type Config = Config; 1063 type Config = Config;
1064 fn set_config(&mut self, config: &Self::Config) { 1064 type ConfigError = ();
1065 self.set_config(*config); 1065 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
1066 self.set_config(config)
1066 } 1067 }
1067} 1068}
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index 604503e61..a0bc33944 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -77,3 +77,10 @@ impl Div<u8> for Hertz {
77 self / (rhs as u32) 77 self / (rhs as u32)
78 } 78 }
79} 79}
80
81impl Div<Hertz> for Hertz {
82 type Output = u32;
83 fn div(self, rhs: Hertz) -> Self::Output {
84 self.0 / rhs.0
85 }
86}
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 5b01937f5..add8be831 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -1,9 +1,8 @@
1use core::cell::Cell; 1use core::cell::Cell;
2use core::convert::TryInto; 2use core::convert::TryInto;
3use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
4use core::{mem, ptr}; 4use core::{mem, ptr};
5 5
6use atomic_polyfill::{AtomicU32, AtomicU8};
7use critical_section::CriticalSection; 6use critical_section::CriticalSection;
8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9use embassy_sync::blocking_mutex::Mutex; 8use embassy_sync::blocking_mutex::Mutex;
@@ -153,46 +152,43 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
153}); 152});
154 153
155impl RtcDriver { 154impl RtcDriver {
156 fn init(&'static self) { 155 fn init(&'static self, cs: critical_section::CriticalSection) {
157 let r = T::regs_gp16(); 156 let r = T::regs_gp16();
158 157
159 <T as RccPeripheral>::enable(); 158 <T as RccPeripheral>::enable_and_reset_with_cs(cs);
160 <T as RccPeripheral>::reset();
161 159
162 let timer_freq = T::frequency(); 160 let timer_freq = T::frequency();
163 161
164 critical_section::with(|_| { 162 r.cr1().modify(|w| w.set_cen(false));
165 r.cr1().modify(|w| w.set_cen(false)); 163 r.cnt().write(|w| w.set_cnt(0));
166 r.cnt().write(|w| w.set_cnt(0));
167 164
168 let psc = timer_freq.0 / TICK_HZ as u32 - 1; 165 let psc = timer_freq.0 / TICK_HZ as u32 - 1;
169 let psc: u16 = match psc.try_into() { 166 let psc: u16 = match psc.try_into() {
170 Err(_) => panic!("psc division overflow: {}", psc), 167 Err(_) => panic!("psc division overflow: {}", psc),
171 Ok(n) => n, 168 Ok(n) => n,
172 }; 169 };
173 170
174 r.psc().write(|w| w.set_psc(psc)); 171 r.psc().write(|w| w.set_psc(psc));
175 r.arr().write(|w| w.set_arr(u16::MAX)); 172 r.arr().write(|w| w.set_arr(u16::MAX));
176 173
177 // Set URS, generate update and clear URS 174 // Set URS, generate update and clear URS
178 r.cr1().modify(|w| w.set_urs(vals::Urs::COUNTERONLY)); 175 r.cr1().modify(|w| w.set_urs(vals::Urs::COUNTERONLY));
179 r.egr().write(|w| w.set_ug(true)); 176 r.egr().write(|w| w.set_ug(true));
180 r.cr1().modify(|w| w.set_urs(vals::Urs::ANYEVENT)); 177 r.cr1().modify(|w| w.set_urs(vals::Urs::ANYEVENT));
181 178
182 // Mid-way point 179 // Mid-way point
183 r.ccr(0).write(|w| w.set_ccr(0x8000)); 180 r.ccr(0).write(|w| w.set_ccr(0x8000));
184 181
185 // Enable overflow and half-overflow interrupts 182 // Enable overflow and half-overflow interrupts
186 r.dier().write(|w| { 183 r.dier().write(|w| {
187 w.set_uie(true); 184 w.set_uie(true);
188 w.set_ccie(0, true); 185 w.set_ccie(0, true);
189 }); 186 });
190 187
191 <T as BasicInstance>::Interrupt::unpend(); 188 <T as BasicInstance>::Interrupt::unpend();
192 unsafe { <T as BasicInstance>::Interrupt::enable() }; 189 unsafe { <T as BasicInstance>::Interrupt::enable() };
193 190
194 r.cr1().modify(|w| w.set_cen(true)); 191 r.cr1().modify(|w| w.set_cen(true));
195 })
196 } 192 }
197 193
198 fn on_interrupt(&self) { 194 fn on_interrupt(&self) {
@@ -229,7 +225,9 @@ impl RtcDriver {
229 fn next_period(&self) { 225 fn next_period(&self) {
230 let r = T::regs_gp16(); 226 let r = T::regs_gp16();
231 227
232 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; 228 // We only modify the period from the timer interrupt, so we know this can't race.
229 let period = self.period.load(Ordering::Relaxed) + 1;
230 self.period.store(period, Ordering::Relaxed);
233 let t = (period as u64) << 15; 231 let t = (period as u64) << 15;
234 232
235 critical_section::with(move |cs| { 233 critical_section::with(move |cs| {
@@ -340,7 +338,11 @@ impl RtcDriver {
340 #[cfg(feature = "low-power")] 338 #[cfg(feature = "low-power")]
341 /// Set the rtc but panic if it's already been set 339 /// Set the rtc but panic if it's already been set
342 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { 340 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) {
343 critical_section::with(|cs| assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none())); 341 critical_section::with(|cs| {
342 rtc.stop_wakeup_alarm(cs);
343
344 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none())
345 });
344 } 346 }
345 347
346 #[cfg(feature = "low-power")] 348 #[cfg(feature = "low-power")]
@@ -399,18 +401,15 @@ impl Driver for RtcDriver {
399 } 401 }
400 402
401 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> { 403 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
402 let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { 404 critical_section::with(|_| {
403 if x < ALARM_COUNT as u8 { 405 let id = self.alarm_count.load(Ordering::Relaxed);
404 Some(x + 1) 406 if id < ALARM_COUNT as u8 {
407 self.alarm_count.store(id + 1, Ordering::Relaxed);
408 Some(AlarmHandle::new(id))
405 } else { 409 } else {
406 None 410 None
407 } 411 }
408 }); 412 })
409
410 match id {
411 Ok(id) => Some(AlarmHandle::new(id)),
412 Err(_) => None,
413 }
414 } 413 }
415 414
416 fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { 415 fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
@@ -461,6 +460,6 @@ pub(crate) fn get_driver() -> &'static RtcDriver {
461 &DRIVER 460 &DRIVER
462} 461}
463 462
464pub(crate) fn init() { 463pub(crate) fn init(cs: CriticalSection) {
465 DRIVER.init() 464 DRIVER.init(cs)
466} 465}
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 72ff84b63..6654366cd 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -65,8 +65,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
65 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { 65 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
66 into_ref!(tim); 66 into_ref!(tim);
67 67
68 T::enable(); 68 T::enable_and_reset();
69 <T as crate::rcc::sealed::RccPeripheral>::reset();
70 69
71 let mut this = Self { inner: tim }; 70 let mut this = Self { inner: tim };
72 71
@@ -74,7 +73,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
74 this.set_freq(freq); 73 this.set_freq(freq);
75 this.inner.start(); 74 this.inner.start();
76 75
77 this.inner.enable_outputs(true); 76 this.inner.enable_outputs();
78 77
79 this.inner 78 this.inner
80 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 79 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
@@ -129,6 +128,46 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
129 } 128 }
130} 129}
131 130
131impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
132 type Channel = Channel;
133 type Time = Hertz;
134 type Duty = u16;
135
136 fn disable(&mut self, channel: Self::Channel) {
137 self.inner.enable_complementary_channel(channel, false);
138 self.inner.enable_channel(channel, false);
139 }
140
141 fn enable(&mut self, channel: Self::Channel) {
142 self.inner.enable_channel(channel, true);
143 self.inner.enable_complementary_channel(channel, true);
144 }
145
146 fn get_period(&self) -> Self::Time {
147 self.inner.get_frequency().into()
148 }
149
150 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
151 self.inner.get_compare_value(channel)
152 }
153
154 fn get_max_duty(&self) -> Self::Duty {
155 self.inner.get_max_compare_value() + 1
156 }
157
158 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
159 assert!(duty <= self.get_max_duty());
160 self.inner.set_compare_value(channel, duty)
161 }
162
163 fn set_period<P>(&mut self, period: P)
164 where
165 P: Into<Self::Time>,
166 {
167 self.inner.set_frequency(period.into());
168 }
169}
170
132fn compute_dead_time_value(value: u16) -> (Ckd, u8) { 171fn compute_dead_time_value(value: u16) -> (Ckd, u8) {
133 /* 172 /*
134 Dead-time = T_clk * T_dts * T_dtg 173 Dead-time = T_clk * T_dts * T_dtg
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 15eaf3536..913bfed2b 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -77,6 +77,16 @@ pub(crate) mod sealed {
77 fn set_autoreload_preload(&mut self, enable: vals::Arpe) { 77 fn set_autoreload_preload(&mut self, enable: vals::Arpe) {
78 Self::regs().cr1().modify(|r| r.set_arpe(enable)); 78 Self::regs().cr1().modify(|r| r.set_arpe(enable));
79 } 79 }
80
81 fn get_frequency(&self) -> Hertz {
82 let timer_f = Self::frequency();
83
84 let regs = Self::regs();
85 let arr = regs.arr().read().arr();
86 let psc = regs.psc().read().psc();
87
88 timer_f / arr / (psc + 1)
89 }
80 } 90 }
81 91
82 pub trait GeneralPurpose16bitInstance: Basic16bitInstance { 92 pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
@@ -123,6 +133,16 @@ pub(crate) mod sealed {
123 regs.egr().write(|r| r.set_ug(true)); 133 regs.egr().write(|r| r.set_ug(true));
124 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); 134 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
125 } 135 }
136
137 fn get_frequency(&self) -> Hertz {
138 let timer_f = Self::frequency();
139
140 let regs = Self::regs_gp32();
141 let arr = regs.arr().read().arr();
142 let psc = regs.psc().read().psc();
143
144 timer_f / arr / (psc + 1)
145 }
126 } 146 }
127 147
128 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { 148 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
@@ -173,7 +193,7 @@ pub(crate) mod sealed {
173 } 193 }
174 }); 194 });
175 } 195 }
176 fn enable_outputs(&mut self, _enable: bool) {} 196 fn enable_outputs(&mut self);
177 197
178 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { 198 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
179 let r = Self::regs_gp16(); 199 let r = Self::regs_gp16();
@@ -203,6 +223,10 @@ pub(crate) mod sealed {
203 fn get_max_compare_value(&self) -> u16 { 223 fn get_max_compare_value(&self) -> u16 {
204 Self::regs_gp16().arr().read().arr() 224 Self::regs_gp16().arr().read().arr()
205 } 225 }
226
227 fn get_compare_value(&self, channel: Channel) -> u16 {
228 Self::regs_gp16().ccr(channel.raw()).read().ccr()
229 }
206 } 230 }
207 231
208 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { 232 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
@@ -239,6 +263,10 @@ pub(crate) mod sealed {
239 fn get_max_compare_value(&self) -> u32 { 263 fn get_max_compare_value(&self) -> u32 {
240 Self::regs_gp32().arr().read().arr() 264 Self::regs_gp32().arr().read().arr()
241 } 265 }
266
267 fn get_compare_value(&self, channel: Channel) -> u32 {
268 Self::regs_gp32().ccr(channel.raw()).read().ccr()
269 }
242 } 270 }
243} 271}
244 272
@@ -460,7 +488,9 @@ macro_rules! impl_32bit_timer {
460#[allow(unused)] 488#[allow(unused)]
461macro_rules! impl_compare_capable_16bit { 489macro_rules! impl_compare_capable_16bit {
462 ($inst:ident) => { 490 ($inst:ident) => {
463 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {} 491 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
492 fn enable_outputs(&mut self) {}
493 }
464 }; 494 };
465} 495}
466 496
@@ -509,7 +539,13 @@ foreach_interrupt! {
509 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 539 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
510 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} 540 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
511 impl AdvancedControlInstance for crate::peripherals::$inst {} 541 impl AdvancedControlInstance for crate::peripherals::$inst {}
512 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {} 542 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
543 fn enable_outputs(&mut self) {
544 use crate::timer::sealed::AdvancedControlInstance;
545 let r = Self::regs_advanced();
546 r.bdtr().modify(|w| w.set_moe(true));
547 }
548 }
513 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} 549 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
514 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 550 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
515 fn regs_gp16() -> crate::pac::timer::TimGp16 { 551 fn regs_gp16() -> crate::pac::timer::TimGp16 {
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 15f2c3a79..01d028bf9 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -55,8 +55,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
55 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { 55 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
56 into_ref!(tim); 56 into_ref!(tim);
57 57
58 T::enable(); 58 T::enable_and_reset();
59 <T as crate::rcc::sealed::RccPeripheral>::reset();
60 59
61 // Configure TxC1 and TxC2 as captures 60 // Configure TxC1 and TxC2 as captures
62 T::regs_gp16().ccmr_input(0).modify(|w| { 61 T::regs_gp16().ccmr_input(0).modify(|w| {
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index b54f8cb07..1cf0ad728 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -64,8 +64,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
64 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self { 64 fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
65 into_ref!(tim); 65 into_ref!(tim);
66 66
67 T::enable(); 67 T::enable_and_reset();
68 <T as crate::rcc::sealed::RccPeripheral>::reset();
69 68
70 let mut this = Self { inner: tim }; 69 let mut this = Self { inner: tim };
71 70
@@ -73,7 +72,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
73 this.set_freq(freq); 72 this.set_freq(freq);
74 this.inner.start(); 73 this.inner.start();
75 74
76 this.inner.enable_outputs(true); 75 this.inner.enable_outputs();
77 76
78 this.inner 77 this.inner
79 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 78 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
@@ -116,3 +115,41 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
116 self.inner.set_output_polarity(channel, polarity); 115 self.inner.set_output_polarity(channel, polarity);
117 } 116 }
118} 117}
118
119impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
120 type Channel = Channel;
121 type Time = Hertz;
122 type Duty = u16;
123
124 fn disable(&mut self, channel: Self::Channel) {
125 self.inner.enable_channel(channel, false);
126 }
127
128 fn enable(&mut self, channel: Self::Channel) {
129 self.inner.enable_channel(channel, true);
130 }
131
132 fn get_period(&self) -> Self::Time {
133 self.inner.get_frequency().into()
134 }
135
136 fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
137 self.inner.get_compare_value(channel)
138 }
139
140 fn get_max_duty(&self) -> Self::Duty {
141 self.inner.get_max_compare_value() + 1
142 }
143
144 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
145 assert!(duty <= self.get_max_duty());
146 self.inner.set_compare_value(channel, duty)
147 }
148
149 fn set_period<P>(&mut self, period: P)
150 where
151 P: Into<Self::Time>,
152 {
153 self.inner.set_frequency(period.into());
154 }
155}
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index e2d6e42af..cbc13a342 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -116,25 +116,28 @@ pub struct BufferedUartRx<'d, T: BasicInstance> {
116 116
117impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> { 117impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> {
118 type Config = Config; 118 type Config = Config;
119 type ConfigError = ();
119 120
120 fn set_config(&mut self, config: &Self::Config) { 121 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
121 unwrap!(self.set_config(config)) 122 self.set_config(config).map_err(|_| ())
122 } 123 }
123} 124}
124 125
125impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> { 126impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> {
126 type Config = Config; 127 type Config = Config;
128 type ConfigError = ();
127 129
128 fn set_config(&mut self, config: &Self::Config) { 130 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
129 unwrap!(self.set_config(config)) 131 self.set_config(config).map_err(|_| ())
130 } 132 }
131} 133}
132 134
133impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> { 135impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
134 type Config = Config; 136 type Config = Config;
137 type ConfigError = ();
135 138
136 fn set_config(&mut self, config: &Self::Config) { 139 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
137 unwrap!(self.set_config(config)) 140 self.set_config(config).map_err(|_| ())
138 } 141 }
139} 142}
140 143
@@ -149,9 +152,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
149 config: Config, 152 config: Config,
150 ) -> Result<Self, ConfigError> { 153 ) -> Result<Self, ConfigError> {
151 // UartRx and UartTx have one refcount ea. 154 // UartRx and UartTx have one refcount ea.
152 T::enable(); 155 T::enable_and_reset();
153 T::enable(); 156 T::enable_and_reset();
154 T::reset();
155 157
156 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 158 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
157 } 159 }
@@ -170,9 +172,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
170 into_ref!(cts, rts); 172 into_ref!(cts, rts);
171 173
172 // UartRx and UartTx have one refcount ea. 174 // UartRx and UartTx have one refcount ea.
173 T::enable(); 175 T::enable_and_reset();
174 T::enable(); 176 T::enable_and_reset();
175 T::reset();
176 177
177 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 178 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
178 cts.set_as_af(cts.af_num(), AFType::Input); 179 cts.set_as_af(cts.af_num(), AFType::Input);
@@ -198,9 +199,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
198 into_ref!(de); 199 into_ref!(de);
199 200
200 // UartRx and UartTx have one refcount ea. 201 // UartRx and UartTx have one refcount ea.
201 T::enable(); 202 T::enable_and_reset();
202 T::enable(); 203 T::enable_and_reset();
203 T::reset();
204 204
205 de.set_as_af(de.af_num(), AFType::OutputPushPull); 205 de.set_as_af(de.af_num(), AFType::OutputPushPull);
206 T::regs().cr3().write(|w| { 206 T::regs().cr3().write(|w| {
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 9835f1ace..880ca4162 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -181,10 +181,11 @@ pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
181 181
182impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> { 182impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> {
183 type Config = Config; 183 type Config = Config;
184 type ConfigError = ();
184 185
185 fn set_config(&mut self, config: &Self::Config) { 186 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
186 unwrap!(self.tx.set_config(config)); 187 self.tx.set_config(config).map_err(|_| ())?;
187 unwrap!(self.rx.set_config(config)); 188 self.rx.set_config(config).map_err(|_| ())
188 } 189 }
189} 190}
190 191
@@ -195,9 +196,10 @@ pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
195 196
196impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { 197impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
197 type Config = Config; 198 type Config = Config;
199 type ConfigError = ();
198 200
199 fn set_config(&mut self, config: &Self::Config) { 201 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
200 unwrap!(self.set_config(config)); 202 self.set_config(config).map_err(|_| ())
201 } 203 }
202} 204}
203 205
@@ -211,9 +213,10 @@ pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
211 213
212impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> { 214impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> {
213 type Config = Config; 215 type Config = Config;
216 type ConfigError = ();
214 217
215 fn set_config(&mut self, config: &Self::Config) { 218 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
216 unwrap!(self.set_config(config)); 219 self.set_config(config).map_err(|_| ())
217 } 220 }
218} 221}
219 222
@@ -225,8 +228,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
225 tx_dma: impl Peripheral<P = TxDma> + 'd, 228 tx_dma: impl Peripheral<P = TxDma> + 'd,
226 config: Config, 229 config: Config,
227 ) -> Result<Self, ConfigError> { 230 ) -> Result<Self, ConfigError> {
228 T::enable(); 231 T::enable_and_reset();
229 T::reset();
230 232
231 Self::new_inner(peri, tx, tx_dma, config) 233 Self::new_inner(peri, tx, tx_dma, config)
232 } 234 }
@@ -240,8 +242,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
240 ) -> Result<Self, ConfigError> { 242 ) -> Result<Self, ConfigError> {
241 into_ref!(cts); 243 into_ref!(cts);
242 244
243 T::enable(); 245 T::enable_and_reset();
244 T::reset();
245 246
246 cts.set_as_af(cts.af_num(), AFType::Input); 247 cts.set_as_af(cts.af_num(), AFType::Input);
247 T::regs().cr3().write(|w| { 248 T::regs().cr3().write(|w| {
@@ -318,8 +319,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
318 rx_dma: impl Peripheral<P = RxDma> + 'd, 319 rx_dma: impl Peripheral<P = RxDma> + 'd,
319 config: Config, 320 config: Config,
320 ) -> Result<Self, ConfigError> { 321 ) -> Result<Self, ConfigError> {
321 T::enable(); 322 T::enable_and_reset();
322 T::reset();
323 323
324 Self::new_inner(peri, rx, rx_dma, config) 324 Self::new_inner(peri, rx, rx_dma, config)
325 } 325 }
@@ -334,8 +334,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
334 ) -> Result<Self, ConfigError> { 334 ) -> Result<Self, ConfigError> {
335 into_ref!(rts); 335 into_ref!(rts);
336 336
337 T::enable(); 337 T::enable_and_reset();
338 T::reset();
339 338
340 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 339 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
341 T::regs().cr3().write(|w| { 340 T::regs().cr3().write(|w| {
@@ -692,9 +691,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
692 config: Config, 691 config: Config,
693 ) -> Result<Self, ConfigError> { 692 ) -> Result<Self, ConfigError> {
694 // UartRx and UartTx have one refcount ea. 693 // UartRx and UartTx have one refcount ea.
695 T::enable(); 694 T::enable_and_reset();
696 T::enable(); 695 T::enable_and_reset();
697 T::reset();
698 696
699 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) 697 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
700 } 698 }
@@ -713,9 +711,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
713 into_ref!(cts, rts); 711 into_ref!(cts, rts);
714 712
715 // UartRx and UartTx have one refcount ea. 713 // UartRx and UartTx have one refcount ea.
716 T::enable(); 714 T::enable_and_reset();
717 T::enable(); 715 T::enable_and_reset();
718 T::reset();
719 716
720 rts.set_as_af(rts.af_num(), AFType::OutputPushPull); 717 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
721 cts.set_as_af(cts.af_num(), AFType::Input); 718 cts.set_as_af(cts.af_num(), AFType::Input);
@@ -740,9 +737,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
740 into_ref!(de); 737 into_ref!(de);
741 738
742 // UartRx and UartTx have one refcount ea. 739 // UartRx and UartTx have one refcount ea.
743 T::enable(); 740 T::enable_and_reset();
744 T::enable(); 741 T::enable_and_reset();
745 T::reset();
746 742
747 de.set_as_af(de.af_num(), AFType::OutputPushPull); 743 de.set_as_af(de.af_num(), AFType::OutputPushPull);
748 T::regs().cr3().write(|w| { 744 T::regs().cr3().write(|w| {
@@ -803,10 +799,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
803 }) 799 })
804 } 800 }
805 801
806 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
807 reconfigure::<T>(config)
808 }
809
810 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 802 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
811 where 803 where
812 TxDma: crate::usart::TxDma<T>, 804 TxDma: crate::usart::TxDma<T>,
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index 347aae7c9..55489f2e0 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -18,9 +18,10 @@ pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
18 18
19impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUartRx<'d, T, RxDma> { 19impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUartRx<'d, T, RxDma> {
20 type Config = Config; 20 type Config = Config;
21 type ConfigError = ();
21 22
22 fn set_config(&mut self, config: &Self::Config) { 23 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
23 unwrap!(self.set_config(config)); 24 self.set_config(config).map_err(|_| ())
24 } 25 }
25} 26}
26 27
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index b24fc74eb..9269ddd88 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -269,8 +269,7 @@ impl<'d, T: Instance> Driver<'d, T> {
269 #[cfg(pwr_h5)] 269 #[cfg(pwr_h5)]
270 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); 270 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true));
271 271
272 <T as RccPeripheral>::enable(); 272 <T as RccPeripheral>::enable_and_reset();
273 <T as RccPeripheral>::reset();
274 273
275 regs.cntr().write(|w| { 274 regs.cntr().write(|w| {
276 w.set_pdwn(false); 275 w.set_pdwn(false);
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index 1fe010bbb..e45e4ac43 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -632,8 +632,7 @@ impl<'d, T: Instance> Bus<'d, T> {
632 }); 632 });
633 } 633 }
634 634
635 <T as RccPeripheral>::enable(); 635 <T as RccPeripheral>::enable_and_reset();
636 <T as RccPeripheral>::reset();
637 636
638 T::Interrupt::unpend(); 637 T::Interrupt::unpend();
639 unsafe { T::Interrupt::enable() }; 638 unsafe { T::Interrupt::enable() };
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index f7739f305..7d3d2c589 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -35,7 +35,7 @@ futures-util = { version = "0.3.17", default-features = false }
35critical-section = "1.1" 35critical-section = "1.1"
36heapless = "0.7.5" 36heapless = "0.7.5"
37cfg-if = "1.0.0" 37cfg-if = "1.0.0"
38embedded-io-async = { version = "0.5.0", optional = true } 38embedded-io-async = { version = "0.6.0", optional = true }
39 39
40[dev-dependencies] 40[dev-dependencies]
41futures-executor = { version = "0.3.17", features = [ "thread-pool" ] } 41futures-executor = { version = "0.3.17", features = [ "thread-pool" ] }
diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs
index 8a9f841ee..aca6ff38f 100644
--- a/embassy-sync/src/lib.rs
+++ b/embassy-sync/src/lib.rs
@@ -1,5 +1,5 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] 2#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
3#![allow(clippy::new_without_default)] 3#![allow(clippy::new_without_default)]
4#![doc = include_str!("../README.md")] 4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)] 5#![warn(missing_docs)]
diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md
index e3b38455c..6e79addf6 100644
--- a/embassy-time/CHANGELOG.md
+++ b/embassy-time/CHANGELOG.md
@@ -5,7 +5,14 @@ All notable changes to this project will be documented in this file.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
8## 0.1.4 - ??? 8## 0.1.5 - 2023-10-16
9
10- Added `links` key to Cargo.toml, to prevent multiple copies of this crate in the same binary.
11 Needed because different copies might get different tick rates, causing
12 wrong delays if the time driver is using one copy and user code is using another.
13 This is especially common when mixing crates from crates.io and git.
14
15## 0.1.4 - 2023-10-12
9 16
10- Added more tick rates 17- Added more tick rates
11 18
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index 8f034a9de..87b57d1e1 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2name = "embassy-time" 2name = "embassy-time"
3version = "0.1.4" 3version = "0.1.5"
4edition = "2021" 4edition = "2021"
5description = "Instant and Duration for embedded no-std systems, with async timer support" 5description = "Instant and Duration for embedded no-std systems, with async timer support"
6repository = "https://github.com/embassy-rs/embassy" 6repository = "https://github.com/embassy-rs/embassy"
@@ -13,6 +13,12 @@ categories = [
13 "asynchronous", 13 "asynchronous",
14] 14]
15 15
16# Prevent multiple copies of this crate in the same binary.
17# Needed because different copies might get different tick rates, causing
18# wrong delays if the time driver is using one copy and user code is using another.
19# This is especially common when mixing crates from crates.io and git.
20links = "embassy-time"
21
16[package.metadata.embassy_docs] 22[package.metadata.embassy_docs]
17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/" 23src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/"
18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time/src/" 24src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time/src/"
@@ -218,7 +224,6 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional =
218embedded-hal-async = { version = "=1.0.0-rc.1", optional = true} 224embedded-hal-async = { version = "=1.0.0-rc.1", optional = true}
219 225
220futures-util = { version = "0.3.17", default-features = false } 226futures-util = { version = "0.3.17", default-features = false }
221atomic-polyfill = "1.0.1"
222critical-section = "1.1" 227critical-section = "1.1"
223cfg-if = "1.0.0" 228cfg-if = "1.0.0"
224heapless = "0.7" 229heapless = "0.7"
diff --git a/embassy-time/build.rs b/embassy-time/build.rs
new file mode 100644
index 000000000..5b0095661
--- /dev/null
+++ b/embassy-time/build.rs
@@ -0,0 +1,3 @@
1// empty, needed to be able to use `links` in Cargo.toml.
2
3fn main() {}
diff --git a/embassy-time/src/delay.rs b/embassy-time/src/delay.rs
index cf1918724..be962747c 100644
--- a/embassy-time/src/delay.rs
+++ b/embassy-time/src/delay.rs
@@ -36,11 +36,11 @@ mod eha {
36 36
37 impl embedded_hal_async::delay::DelayUs for Delay { 37 impl embedded_hal_async::delay::DelayUs for Delay {
38 async fn delay_us(&mut self, micros: u32) { 38 async fn delay_us(&mut self, micros: u32) {
39 Timer::after(Duration::from_micros(micros as _)).await 39 Timer::after_micros(micros as _).await
40 } 40 }
41 41
42 async fn delay_ms(&mut self, millis: u32) { 42 async fn delay_ms(&mut self, millis: u32) {
43 Timer::after(Duration::from_millis(millis as _)).await 43 Timer::after_millis(millis as _).await
44 } 44 }
45 } 45 }
46} 46}
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs
index 07ddf473f..ee2423daf 100644
--- a/embassy-time/src/timer.rs
+++ b/embassy-time/src/timer.rs
@@ -64,6 +64,42 @@ impl Timer {
64 yielded_once: false, 64 yielded_once: false,
65 } 65 }
66 } 66 }
67
68 /// Expire after the specified number of ticks.
69 ///
70 /// This method is a convenience wrapper for calling `Timer::after(Duration::from_ticks())`.
71 /// For more details, refer to [`Timer::after()`] and [`Duration::from_ticks()`].
72 #[inline]
73 pub fn after_ticks(ticks: u64) -> Self {
74 Self::after(Duration::from_ticks(ticks))
75 }
76
77 /// Expire after the specified number of microseconds.
78 ///
79 /// This method is a convenience wrapper for calling `Timer::after(Duration::from_micros())`.
80 /// For more details, refer to [`Timer::after()`] and [`Duration::from_micros()`].
81 #[inline]
82 pub fn after_micros(micros: u64) -> Self {
83 Self::after(Duration::from_micros(micros))
84 }
85
86 /// Expire after the specified number of milliseconds.
87 ///
88 /// This method is a convenience wrapper for calling `Timer::after(Duration::from_millis())`.
89 /// For more details, refer to [`Timer::after`] and [`Duration::from_millis()`].
90 #[inline]
91 pub fn after_millis(millis: u64) -> Self {
92 Self::after(Duration::from_millis(millis))
93 }
94
95 /// Expire after the specified number of seconds.
96 ///
97 /// This method is a convenience wrapper for calling `Timer::after(Duration::from_secs())`.
98 /// For more details, refer to [`Timer::after`] and [`Duration::from_secs()`].
99 #[inline]
100 pub fn after_secs(secs: u64) -> Self {
101 Self::after(Duration::from_secs(secs))
102 }
67} 103}
68 104
69impl Unpin for Timer {} 105impl Unpin for Timer {}
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml
index 0e7e0e708..9ae144992 100644
--- a/embassy-usb/Cargo.toml
+++ b/embassy-usb/Cargo.toml
@@ -42,7 +42,7 @@ max-handler-count-8 = []
42embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 42embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
43embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } 43embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" }
44embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 44embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
45embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } 45embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
46 46
47defmt = { version = "0.3", optional = true } 47defmt = { version = "0.3", optional = true }
48log = { version = "0.4.14", optional = true } 48log = { version = "0.4.14", optional = true }
diff --git a/embassy-usb/build.rs b/embassy-usb/build.rs
index 33d32f7d3..5e3bec485 100644
--- a/embassy-usb/build.rs
+++ b/embassy-usb/build.rs
@@ -70,9 +70,11 @@ fn main() {
70 70
71 // envvars take priority. 71 // envvars take priority.
72 if !cfg.seen_env { 72 if !cfg.seen_env {
73 if cfg.seen_feature { 73 assert!(
74 panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value); 74 !cfg.seen_feature,
75 } 75 "multiple values set for feature {}: {} and {}",
76 name, cfg.value, value
77 );
76 78
77 cfg.value = value; 79 cfg.value = value;
78 cfg.seen_feature = true; 80 cfg.seen_feature = true;
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 6b68bcd7b..b4ddccd71 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -1,17 +1,17 @@
1use heapless::Vec; 1use heapless::Vec;
2 2
3use crate::config::*; 3use crate::config::MAX_HANDLER_COUNT;
4use crate::descriptor::{BosWriter, DescriptorWriter}; 4use crate::descriptor::{BosWriter, DescriptorWriter};
5use crate::driver::{Driver, Endpoint, EndpointType}; 5use crate::driver::{Driver, Endpoint, EndpointType};
6#[cfg(feature = "msos-descriptor")] 6#[cfg(feature = "msos-descriptor")]
7use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; 7use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
8use crate::types::*; 8use crate::types::{InterfaceNumber, StringIndex};
9use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; 9use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
10 10
11#[derive(Debug, Copy, Clone)] 11#[derive(Debug, Copy, Clone)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))] 12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13#[non_exhaustive] 13#[non_exhaustive]
14/// Configuration used when creating [UsbDevice]. 14/// Configuration used when creating [`UsbDevice`].
15pub struct Config<'a> { 15pub struct Config<'a> {
16 pub(crate) vendor_id: u16, 16 pub(crate) vendor_id: u16,
17 pub(crate) product_id: u16, 17 pub(crate) product_id: u16,
@@ -99,7 +99,7 @@ pub struct Config<'a> {
99 99
100impl<'a> Config<'a> { 100impl<'a> Config<'a> {
101 /// Create default configuration with the provided vid and pid values. 101 /// Create default configuration with the provided vid and pid values.
102 pub fn new(vid: u16, pid: u16) -> Self { 102 pub const fn new(vid: u16, pid: u16) -> Self {
103 Self { 103 Self {
104 device_class: 0x00, 104 device_class: 0x00,
105 device_sub_class: 0x00, 105 device_sub_class: 0x00,
@@ -159,9 +159,10 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
159 panic!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01"); 159 panic!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01");
160 } 160 }
161 161
162 if config.max_power > 500 { 162 assert!(
163 panic!("The maximum allowed value for `max_power` is 500mA"); 163 config.max_power <= 500,
164 } 164 "The maximum allowed value for `max_power` is 500mA"
165 );
165 166
166 match config.max_packet_size_0 { 167 match config.max_packet_size_0 {
167 8 | 16 | 32 | 64 => {} 168 8 | 16 | 32 | 64 => {}
@@ -260,12 +261,11 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
260 /// The Handler is called on some USB bus events, and to handle all control requests not already 261 /// The Handler is called on some USB bus events, and to handle all control requests not already
261 /// handled by the USB stack. 262 /// handled by the USB stack.
262 pub fn handler(&mut self, handler: &'d mut dyn Handler) { 263 pub fn handler(&mut self, handler: &'d mut dyn Handler) {
263 if self.handlers.push(handler).is_err() { 264 assert!(
264 panic!( 265 self.handlers.push(handler).is_ok(),
265 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}", 266 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}",
266 MAX_HANDLER_COUNT 267 MAX_HANDLER_COUNT
267 ) 268 );
268 }
269 } 269 }
270 270
271 /// Allocates a new string index. 271 /// Allocates a new string index.
@@ -332,12 +332,10 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
332 num_alt_settings: 0, 332 num_alt_settings: 0,
333 }; 333 };
334 334
335 if self.builder.interfaces.push(iface).is_err() { 335 assert!(self.builder.interfaces.push(iface).is_ok(),
336 panic!( 336 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}",
337 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}", 337 MAX_INTERFACE_COUNT
338 MAX_INTERFACE_COUNT 338 );
339 )
340 }
341 339
342 InterfaceBuilder { 340 InterfaceBuilder {
343 builder: self.builder, 341 builder: self.builder,
@@ -371,7 +369,7 @@ pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> {
371 369
372impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { 370impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
373 /// Get the interface number. 371 /// Get the interface number.
374 pub fn interface_number(&self) -> InterfaceNumber { 372 pub const fn interface_number(&self) -> InterfaceNumber {
375 self.interface_number 373 self.interface_number
376 } 374 }
377 375
@@ -422,12 +420,12 @@ pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> {
422 420
423impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { 421impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
424 /// Get the interface number. 422 /// Get the interface number.
425 pub fn interface_number(&self) -> InterfaceNumber { 423 pub const fn interface_number(&self) -> InterfaceNumber {
426 self.interface_number 424 self.interface_number
427 } 425 }
428 426
429 /// Get the alternate setting number. 427 /// Get the alternate setting number.
430 pub fn alt_setting_number(&self) -> u8 { 428 pub const fn alt_setting_number(&self) -> u8 {
431 self.alt_setting_number 429 self.alt_setting_number
432 } 430 }
433 431
@@ -436,7 +434,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
436 /// Descriptors are written in the order builder functions are called. Note that some 434 /// Descriptors are written in the order builder functions are called. Note that some
437 /// classes care about the order. 435 /// classes care about the order.
438 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) { 436 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
439 self.builder.config_descriptor.write(descriptor_type, descriptor) 437 self.builder.config_descriptor.write(descriptor_type, descriptor);
440 } 438 }
441 439
442 fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { 440 fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs
index a341e10da..f1066d2f2 100644
--- a/embassy-usb/src/class/cdc_acm.rs
+++ b/embassy-usb/src/class/cdc_acm.rs
@@ -1,14 +1,17 @@
1//! CDC-ACM class implementation, aka Serial over USB. 1//! CDC-ACM class implementation, aka Serial over USB.
2 2
3use core::cell::Cell; 3use core::cell::{Cell, RefCell};
4use core::future::poll_fn;
4use core::mem::{self, MaybeUninit}; 5use core::mem::{self, MaybeUninit};
5use core::sync::atomic::{AtomicBool, Ordering}; 6use core::sync::atomic::{AtomicBool, Ordering};
7use core::task::Poll;
6 8
7use embassy_sync::blocking_mutex::CriticalSectionMutex; 9use embassy_sync::blocking_mutex::CriticalSectionMutex;
10use embassy_sync::waitqueue::WakerRegistration;
8 11
9use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; 12use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
10use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 13use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
11use crate::types::*; 14use crate::types::InterfaceNumber;
12use crate::{Builder, Handler}; 15use crate::{Builder, Handler};
13 16
14/// This should be used as `device_class` when building the `UsbDevice`. 17/// This should be used as `device_class` when building the `UsbDevice`.
@@ -36,12 +39,18 @@ pub struct State<'a> {
36 shared: ControlShared, 39 shared: ControlShared,
37} 40}
38 41
42impl<'a> Default for State<'a> {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
39impl<'a> State<'a> { 48impl<'a> State<'a> {
40 /// Create a new `State`. 49 /// Create a new `State`.
41 pub fn new() -> Self { 50 pub fn new() -> Self {
42 Self { 51 Self {
43 control: MaybeUninit::uninit(), 52 control: MaybeUninit::uninit(),
44 shared: Default::default(), 53 shared: ControlShared::default(),
45 } 54 }
46 } 55 }
47} 56}
@@ -52,9 +61,9 @@ impl<'a> State<'a> {
52/// writing USB packets with no intermediate buffers, but it will not act like a stream-like serial 61/// writing USB packets with no intermediate buffers, but it will not act like a stream-like serial
53/// port. The following constraints must be followed if you use this class directly: 62/// port. The following constraints must be followed if you use this class directly:
54/// 63///
55/// - `read_packet` must be called with a buffer large enough to hold max_packet_size bytes. 64/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes.
56/// - `write_packet` must not be called with a buffer larger than max_packet_size bytes. 65/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes.
57/// - If you write a packet that is exactly max_packet_size bytes long, it won't be processed by the 66/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the
58/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP) 67/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP)
59/// can be sent if there is no other data to send. This is because USB bulk transactions must be 68/// can be sent if there is no other data to send. This is because USB bulk transactions must be
60/// terminated with a short packet, even if the bulk endpoint is used for stream-like data. 69/// terminated with a short packet, even if the bulk endpoint is used for stream-like data.
@@ -76,6 +85,9 @@ struct ControlShared {
76 line_coding: CriticalSectionMutex<Cell<LineCoding>>, 85 line_coding: CriticalSectionMutex<Cell<LineCoding>>,
77 dtr: AtomicBool, 86 dtr: AtomicBool,
78 rts: AtomicBool, 87 rts: AtomicBool,
88
89 waker: RefCell<WakerRegistration>,
90 changed: AtomicBool,
79} 91}
80 92
81impl Default for ControlShared { 93impl Default for ControlShared {
@@ -89,10 +101,27 @@ impl Default for ControlShared {
89 parity_type: ParityType::None, 101 parity_type: ParityType::None,
90 data_rate: 8_000, 102 data_rate: 8_000,
91 })), 103 })),
104 waker: RefCell::new(WakerRegistration::new()),
105 changed: AtomicBool::new(false),
92 } 106 }
93 } 107 }
94} 108}
95 109
110impl ControlShared {
111 async fn changed(&self) {
112 poll_fn(|cx| {
113 if self.changed.load(Ordering::Relaxed) {
114 self.changed.store(false, Ordering::Relaxed);
115 Poll::Ready(())
116 } else {
117 self.waker.borrow_mut().register(cx.waker());
118 Poll::Pending
119 }
120 })
121 .await;
122 }
123}
124
96impl<'a> Control<'a> { 125impl<'a> Control<'a> {
97 fn shared(&mut self) -> &'a ControlShared { 126 fn shared(&mut self) -> &'a ControlShared {
98 self.shared 127 self.shared
@@ -105,6 +134,9 @@ impl<'d> Handler for Control<'d> {
105 shared.line_coding.lock(|x| x.set(LineCoding::default())); 134 shared.line_coding.lock(|x| x.set(LineCoding::default()));
106 shared.dtr.store(false, Ordering::Relaxed); 135 shared.dtr.store(false, Ordering::Relaxed);
107 shared.rts.store(false, Ordering::Relaxed); 136 shared.rts.store(false, Ordering::Relaxed);
137
138 shared.changed.store(true, Ordering::Relaxed);
139 shared.waker.borrow_mut().wake();
108 } 140 }
109 141
110 fn control_out(&mut self, req: control::Request, data: &[u8]) -> Option<OutResponse> { 142 fn control_out(&mut self, req: control::Request, data: &[u8]) -> Option<OutResponse> {
@@ -127,9 +159,13 @@ impl<'d> Handler for Control<'d> {
127 parity_type: data[5].into(), 159 parity_type: data[5].into(),
128 data_bits: data[6], 160 data_bits: data[6],
129 }; 161 };
130 self.shared().line_coding.lock(|x| x.set(coding)); 162 let shared = self.shared();
163 shared.line_coding.lock(|x| x.set(coding));
131 debug!("Set line coding to: {:?}", coding); 164 debug!("Set line coding to: {:?}", coding);
132 165
166 shared.changed.store(true, Ordering::Relaxed);
167 shared.waker.borrow_mut().wake();
168
133 Some(OutResponse::Accepted) 169 Some(OutResponse::Accepted)
134 } 170 }
135 REQ_SET_CONTROL_LINE_STATE => { 171 REQ_SET_CONTROL_LINE_STATE => {
@@ -141,6 +177,9 @@ impl<'d> Handler for Control<'d> {
141 shared.rts.store(rts, Ordering::Relaxed); 177 shared.rts.store(rts, Ordering::Relaxed);
142 debug!("Set dtr {}, rts {}", dtr, rts); 178 debug!("Set dtr {}, rts {}", dtr, rts);
143 179
180 shared.changed.store(true, Ordering::Relaxed);
181 shared.waker.borrow_mut().wake();
182
144 Some(OutResponse::Accepted) 183 Some(OutResponse::Accepted)
145 } 184 }
146 _ => Some(OutResponse::Rejected), 185 _ => Some(OutResponse::Rejected),
@@ -158,7 +197,7 @@ impl<'d> Handler for Control<'d> {
158 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. 197 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below.
159 REQ_GET_LINE_CODING if req.length == 7 => { 198 REQ_GET_LINE_CODING if req.length == 7 => {
160 debug!("Sending line coding"); 199 debug!("Sending line coding");
161 let coding = self.shared().line_coding.lock(|x| x.get()); 200 let coding = self.shared().line_coding.lock(Cell::get);
162 assert!(buf.len() >= 7); 201 assert!(buf.len() >= 7);
163 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes()); 202 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes());
164 buf[4] = coding.stop_bits as u8; 203 buf[4] = coding.stop_bits as u8;
@@ -172,8 +211,8 @@ impl<'d> Handler for Control<'d> {
172} 211}
173 212
174impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { 213impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
175 /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For 214 /// Creates a new CdcAcmClass with the provided UsbBus and `max_packet_size` in bytes. For
176 /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. 215 /// full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64.
177 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self { 216 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
178 assert!(builder.control_buf_len() >= 7); 217 assert!(builder.control_buf_len() >= 7);
179 218
@@ -208,7 +247,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
208 &[ 247 &[
209 CDC_TYPE_UNION, // bDescriptorSubtype 248 CDC_TYPE_UNION, // bDescriptorSubtype
210 comm_if.into(), // bControlInterface 249 comm_if.into(), // bControlInterface
211 data_if.into(), // bSubordinateInterface 250 data_if, // bSubordinateInterface
212 ], 251 ],
213 ); 252 );
214 253
@@ -249,7 +288,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
249 /// Gets the current line coding. The line coding contains information that's mainly relevant 288 /// Gets the current line coding. The line coding contains information that's mainly relevant
250 /// for USB to UART serial port emulators, and can be ignored if not relevant. 289 /// for USB to UART serial port emulators, and can be ignored if not relevant.
251 pub fn line_coding(&self) -> LineCoding { 290 pub fn line_coding(&self) -> LineCoding {
252 self.control.line_coding.lock(|x| x.get()) 291 self.control.line_coding.lock(Cell::get)
253 } 292 }
254 293
255 /// Gets the DTR (data terminal ready) state 294 /// Gets the DTR (data terminal ready) state
@@ -274,7 +313,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
274 313
275 /// Waits for the USB host to enable this interface 314 /// Waits for the USB host to enable this interface
276 pub async fn wait_connection(&mut self) { 315 pub async fn wait_connection(&mut self) {
277 self.read_ep.wait_enabled().await 316 self.read_ep.wait_enabled().await;
278 } 317 }
279 318
280 /// Split the class into a sender and receiver. 319 /// Split the class into a sender and receiver.
@@ -292,6 +331,38 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
292 }, 331 },
293 ) 332 )
294 } 333 }
334
335 /// Split the class into sender, receiver and control
336 ///
337 /// Allows concurrently sending and receiving packets whilst monitoring for
338 /// control changes (dtr, rts)
339 pub fn split_with_control(self) -> (Sender<'d, D>, Receiver<'d, D>, ControlChanged<'d>) {
340 (
341 Sender {
342 write_ep: self.write_ep,
343 control: self.control,
344 },
345 Receiver {
346 read_ep: self.read_ep,
347 control: self.control,
348 },
349 ControlChanged { control: self.control },
350 )
351 }
352}
353
354/// CDC ACM Control status change monitor
355///
356/// You can obtain a `ControlChanged` with [`CdcAcmClass::split_with_control`]
357pub struct ControlChanged<'d> {
358 control: &'d ControlShared,
359}
360
361impl<'d> ControlChanged<'d> {
362 /// Return a future for when the control settings change
363 pub async fn control_changed(&self) {
364 self.control.changed().await;
365 }
295} 366}
296 367
297/// CDC ACM class packet sender. 368/// CDC ACM class packet sender.
@@ -312,7 +383,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
312 /// Gets the current line coding. The line coding contains information that's mainly relevant 383 /// Gets the current line coding. The line coding contains information that's mainly relevant
313 /// for USB to UART serial port emulators, and can be ignored if not relevant. 384 /// for USB to UART serial port emulators, and can be ignored if not relevant.
314 pub fn line_coding(&self) -> LineCoding { 385 pub fn line_coding(&self) -> LineCoding {
315 self.control.line_coding.lock(|x| x.get()) 386 self.control.line_coding.lock(Cell::get)
316 } 387 }
317 388
318 /// Gets the DTR (data terminal ready) state 389 /// Gets the DTR (data terminal ready) state
@@ -332,7 +403,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
332 403
333 /// Waits for the USB host to enable this interface 404 /// Waits for the USB host to enable this interface
334 pub async fn wait_connection(&mut self) { 405 pub async fn wait_connection(&mut self) {
335 self.write_ep.wait_enabled().await 406 self.write_ep.wait_enabled().await;
336 } 407 }
337} 408}
338 409
@@ -354,7 +425,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
354 /// Gets the current line coding. The line coding contains information that's mainly relevant 425 /// Gets the current line coding. The line coding contains information that's mainly relevant
355 /// for USB to UART serial port emulators, and can be ignored if not relevant. 426 /// for USB to UART serial port emulators, and can be ignored if not relevant.
356 pub fn line_coding(&self) -> LineCoding { 427 pub fn line_coding(&self) -> LineCoding {
357 self.control.line_coding.lock(|x| x.get()) 428 self.control.line_coding.lock(Cell::get)
358 } 429 }
359 430
360 /// Gets the DTR (data terminal ready) state 431 /// Gets the DTR (data terminal ready) state
@@ -374,7 +445,7 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
374 445
375 /// Waits for the USB host to enable this interface 446 /// Waits for the USB host to enable this interface
376 pub async fn wait_connection(&mut self) { 447 pub async fn wait_connection(&mut self) {
377 self.read_ep.wait_enabled().await 448 self.read_ep.wait_enabled().await;
378 } 449 }
379} 450}
380 451
@@ -448,17 +519,17 @@ impl LineCoding {
448 } 519 }
449 520
450 /// Gets the number of data bits for UART communication. 521 /// Gets the number of data bits for UART communication.
451 pub fn data_bits(&self) -> u8 { 522 pub const fn data_bits(&self) -> u8 {
452 self.data_bits 523 self.data_bits
453 } 524 }
454 525
455 /// Gets the parity type for UART communication. 526 /// Gets the parity type for UART communication.
456 pub fn parity_type(&self) -> ParityType { 527 pub const fn parity_type(&self) -> ParityType {
457 self.parity_type 528 self.parity_type
458 } 529 }
459 530
460 /// Gets the data rate in bits per second for UART communication. 531 /// Gets the data rate in bits per second for UART communication.
461 pub fn data_rate(&self) -> u32 { 532 pub const fn data_rate(&self) -> u32 {
462 self.data_rate 533 self.data_rate
463 } 534 }
464} 535}
diff --git a/embassy-usb/src/class/cdc_ncm/mod.rs b/embassy-usb/src/class/cdc_ncm/mod.rs
index 830e9b768..bea9dac27 100644
--- a/embassy-usb/src/class/cdc_ncm/mod.rs
+++ b/embassy-usb/src/class/cdc_ncm/mod.rs
@@ -16,10 +16,11 @@
16 16
17use core::intrinsics::copy_nonoverlapping; 17use core::intrinsics::copy_nonoverlapping;
18use core::mem::{size_of, MaybeUninit}; 18use core::mem::{size_of, MaybeUninit};
19use core::ptr::addr_of;
19 20
20use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType}; 21use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
21use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 22use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
22use crate::types::*; 23use crate::types::{InterfaceNumber, StringIndex};
23use crate::{Builder, Handler}; 24use crate::{Builder, Handler};
24 25
25pub mod embassy_net; 26pub mod embassy_net;
@@ -62,9 +63,9 @@ const REQ_SET_NTB_INPUT_SIZE: u8 = 0x86;
62//const NOTIF_POLL_INTERVAL: u8 = 20; 63//const NOTIF_POLL_INTERVAL: u8 = 20;
63 64
64const NTB_MAX_SIZE: usize = 2048; 65const NTB_MAX_SIZE: usize = 2048;
65const SIG_NTH: u32 = 0x484d434e; 66const SIG_NTH: u32 = 0x484d_434e;
66const SIG_NDP_NO_FCS: u32 = 0x304d434e; 67const SIG_NDP_NO_FCS: u32 = 0x304d_434e;
67const SIG_NDP_WITH_FCS: u32 = 0x314d434e; 68const SIG_NDP_WITH_FCS: u32 = 0x314d_434e;
68 69
69const ALTERNATE_SETTING_DISABLED: u8 = 0x00; 70const ALTERNATE_SETTING_DISABLED: u8 = 0x00;
70const ALTERNATE_SETTING_ENABLED: u8 = 0x01; 71const ALTERNATE_SETTING_ENABLED: u8 = 0x01;
@@ -111,7 +112,7 @@ struct NtbParametersDir {
111 112
112fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] { 113fn byteify<T>(buf: &mut [u8], data: T) -> &[u8] {
113 let len = size_of::<T>(); 114 let len = size_of::<T>();
114 unsafe { copy_nonoverlapping(&data as *const _ as *const u8, buf.as_mut_ptr(), len) } 115 unsafe { copy_nonoverlapping(addr_of!(data).cast(), buf.as_mut_ptr(), len) }
115 &buf[..len] 116 &buf[..len]
116} 117}
117 118
@@ -121,27 +122,28 @@ pub struct State<'a> {
121 shared: ControlShared, 122 shared: ControlShared,
122} 123}
123 124
125impl<'a> Default for State<'a> {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
124impl<'a> State<'a> { 131impl<'a> State<'a> {
125 /// Create a new `State`. 132 /// Create a new `State`.
126 pub fn new() -> Self { 133 pub fn new() -> Self {
127 Self { 134 Self {
128 control: MaybeUninit::uninit(), 135 control: MaybeUninit::uninit(),
129 shared: Default::default(), 136 shared: ControlShared::default(),
130 } 137 }
131 } 138 }
132} 139}
133 140
134/// Shared data between Control and CdcAcmClass 141/// Shared data between Control and `CdcAcmClass`
142#[derive(Default)]
135struct ControlShared { 143struct ControlShared {
136 mac_addr: [u8; 6], 144 mac_addr: [u8; 6],
137} 145}
138 146
139impl Default for ControlShared {
140 fn default() -> Self {
141 ControlShared { mac_addr: [0; 6] }
142 }
143}
144
145struct Control<'a> { 147struct Control<'a> {
146 mac_addr_string: StringIndex, 148 mac_addr_string: StringIndex,
147 shared: &'a ControlShared, 149 shared: &'a ControlShared,
@@ -377,12 +379,12 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
377 /// 379 ///
378 /// This waits until the packet is successfully stored in the CDC-NCM endpoint buffers. 380 /// This waits until the packet is successfully stored in the CDC-NCM endpoint buffers.
379 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> { 381 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
380 let seq = self.seq;
381 self.seq = self.seq.wrapping_add(1);
382
383 const OUT_HEADER_LEN: usize = 28; 382 const OUT_HEADER_LEN: usize = 28;
384 const ABS_MAX_PACKET_SIZE: usize = 512; 383 const ABS_MAX_PACKET_SIZE: usize = 512;
385 384
385 let seq = self.seq;
386 self.seq = self.seq.wrapping_add(1);
387
386 let header = NtbOutHeader { 388 let header = NtbOutHeader {
387 nth_sig: SIG_NTH, 389 nth_sig: SIG_NTH,
388 nth_len: 0x0c, 390 nth_len: 0x0c,
@@ -416,7 +418,7 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
416 self.write_ep.write(&buf[..self.max_packet_size]).await?; 418 self.write_ep.write(&buf[..self.max_packet_size]).await?;
417 419
418 for chunk in d2.chunks(self.max_packet_size) { 420 for chunk in d2.chunks(self.max_packet_size) {
419 self.write_ep.write(&chunk).await?; 421 self.write_ep.write(chunk).await?;
420 } 422 }
421 423
422 // Send ZLP if needed. 424 // Send ZLP if needed.
@@ -459,12 +461,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
459 let ntb = &ntb[..pos]; 461 let ntb = &ntb[..pos];
460 462
461 // Process NTB header (NTH) 463 // Process NTB header (NTH)
462 let nth = match ntb.get(..12) { 464 let Some(nth) = ntb.get(..12) else {
463 Some(x) => x, 465 warn!("Received too short NTB");
464 None => { 466 continue;
465 warn!("Received too short NTB");
466 continue;
467 }
468 }; 467 };
469 let sig = u32::from_le_bytes(nth[0..4].try_into().unwrap()); 468 let sig = u32::from_le_bytes(nth[0..4].try_into().unwrap());
470 if sig != SIG_NTH { 469 if sig != SIG_NTH {
@@ -474,12 +473,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
474 let ndp_idx = u16::from_le_bytes(nth[10..12].try_into().unwrap()) as usize; 473 let ndp_idx = u16::from_le_bytes(nth[10..12].try_into().unwrap()) as usize;
475 474
476 // Process NTB Datagram Pointer (NDP) 475 // Process NTB Datagram Pointer (NDP)
477 let ndp = match ntb.get(ndp_idx..ndp_idx + 12) { 476 let Some(ndp) = ntb.get(ndp_idx..ndp_idx + 12) else {
478 Some(x) => x, 477 warn!("NTH has an NDP pointer out of range.");
479 None => { 478 continue;
480 warn!("NTH has an NDP pointer out of range.");
481 continue;
482 }
483 }; 479 };
484 let sig = u32::from_le_bytes(ndp[0..4].try_into().unwrap()); 480 let sig = u32::from_le_bytes(ndp[0..4].try_into().unwrap());
485 if sig != SIG_NDP_NO_FCS && sig != SIG_NDP_WITH_FCS { 481 if sig != SIG_NDP_NO_FCS && sig != SIG_NDP_WITH_FCS {
@@ -495,12 +491,9 @@ impl<'d, D: Driver<'d>> Receiver<'d, D> {
495 } 491 }
496 492
497 // Process actual datagram, finally. 493 // Process actual datagram, finally.
498 let datagram = match ntb.get(datagram_index..datagram_index + datagram_len) { 494 let Some(datagram) = ntb.get(datagram_index..datagram_index + datagram_len) else {
499 Some(x) => x, 495 warn!("NDP has a datagram pointer out of range.");
500 None => { 496 continue;
501 warn!("NDP has a datagram pointer out of range.");
502 continue;
503 }
504 }; 497 };
505 buf[..datagram_len].copy_from_slice(datagram); 498 buf[..datagram_len].copy_from_slice(datagram);
506 499
diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs
index 889d66ec5..0000b5b2b 100644
--- a/embassy-usb/src/class/hid.rs
+++ b/embassy-usb/src/class/hid.rs
@@ -63,7 +63,7 @@ pub enum ReportId {
63} 63}
64 64
65impl ReportId { 65impl ReportId {
66 fn try_from(value: u16) -> Result<Self, ()> { 66 const fn try_from(value: u16) -> Result<Self, ()> {
67 match value >> 8 { 67 match value >> 8 {
68 1 => Ok(ReportId::In(value as u8)), 68 1 => Ok(ReportId::In(value as u8)),
69 2 => Ok(ReportId::Out(value as u8)), 69 2 => Ok(ReportId::Out(value as u8)),
@@ -79,9 +79,15 @@ pub struct State<'d> {
79 out_report_offset: AtomicUsize, 79 out_report_offset: AtomicUsize,
80} 80}
81 81
82impl<'d> Default for State<'d> {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
82impl<'d> State<'d> { 88impl<'d> State<'d> {
83 /// Create a new `State`. 89 /// Create a new `State`.
84 pub fn new() -> Self { 90 pub const fn new() -> Self {
85 State { 91 State {
86 control: MaybeUninit::uninit(), 92 control: MaybeUninit::uninit(),
87 out_report_offset: AtomicUsize::new(0), 93 out_report_offset: AtomicUsize::new(0),
@@ -148,7 +154,7 @@ fn build<'d, D: Driver<'d>>(
148} 154}
149 155
150impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> { 156impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWriter<'d, D, READ_N, WRITE_N> {
151 /// Creates a new HidReaderWriter. 157 /// Creates a new `HidReaderWriter`.
152 /// 158 ///
153 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) 159 /// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
154 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. 160 /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
@@ -171,7 +177,7 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWrit
171 } 177 }
172 178
173 /// Waits for both IN and OUT endpoints to be enabled. 179 /// Waits for both IN and OUT endpoints to be enabled.
174 pub async fn ready(&mut self) -> () { 180 pub async fn ready(&mut self) {
175 self.reader.ready().await; 181 self.reader.ready().await;
176 self.writer.ready().await; 182 self.writer.ready().await;
177 } 183 }
@@ -224,7 +230,7 @@ pub enum ReadError {
224 230
225impl From<EndpointError> for ReadError { 231impl From<EndpointError> for ReadError {
226 fn from(val: EndpointError) -> Self { 232 fn from(val: EndpointError) -> Self {
227 use EndpointError::*; 233 use EndpointError::{BufferOverflow, Disabled};
228 match val { 234 match val {
229 BufferOverflow => ReadError::BufferOverflow, 235 BufferOverflow => ReadError::BufferOverflow,
230 Disabled => ReadError::Disabled, 236 Disabled => ReadError::Disabled,
@@ -251,17 +257,16 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
251 } 257 }
252 258
253 /// Waits for the interrupt in endpoint to be enabled. 259 /// Waits for the interrupt in endpoint to be enabled.
254 pub async fn ready(&mut self) -> () { 260 pub async fn ready(&mut self) {
255 self.ep_in.wait_enabled().await 261 self.ep_in.wait_enabled().await;
256 } 262 }
257 263
258 /// Writes an input report by serializing the given report structure. 264 /// Writes an input report by serializing the given report structure.
259 #[cfg(feature = "usbd-hid")] 265 #[cfg(feature = "usbd-hid")]
260 pub async fn write_serialize<IR: AsInputReport>(&mut self, r: &IR) -> Result<(), EndpointError> { 266 pub async fn write_serialize<IR: AsInputReport>(&mut self, r: &IR) -> Result<(), EndpointError> {
261 let mut buf: [u8; N] = [0; N]; 267 let mut buf: [u8; N] = [0; N];
262 let size = match serialize(&mut buf, r) { 268 let Ok(size) = serialize(&mut buf, r) else {
263 Ok(size) => size, 269 return Err(EndpointError::BufferOverflow);
264 Err(_) => return Err(EndpointError::BufferOverflow),
265 }; 270 };
266 self.write(&buf[0..size]).await 271 self.write(&buf[0..size]).await
267 } 272 }
@@ -286,8 +291,8 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
286 291
287impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> { 292impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> {
288 /// Waits for the interrupt out endpoint to be enabled. 293 /// Waits for the interrupt out endpoint to be enabled.
289 pub async fn ready(&mut self) -> () { 294 pub async fn ready(&mut self) {
290 self.ep_out.wait_enabled().await 295 self.ep_out.wait_enabled().await;
291 } 296 }
292 297
293 /// Delivers output reports from the Interrupt Out pipe to `handler`. 298 /// Delivers output reports from the Interrupt Out pipe to `handler`.
@@ -344,9 +349,8 @@ impl<'d, D: Driver<'d>, const N: usize> HidReader<'d, D, N> {
344 if size < max_packet_size || total == N { 349 if size < max_packet_size || total == N {
345 self.offset.store(0, Ordering::Release); 350 self.offset.store(0, Ordering::Release);
346 break; 351 break;
347 } else {
348 self.offset.store(total, Ordering::Release);
349 } 352 }
353 self.offset.store(total, Ordering::Release);
350 } 354 }
351 Err(err) => { 355 Err(err) => {
352 self.offset.store(0, Ordering::Release); 356 self.offset.store(0, Ordering::Release);
@@ -466,7 +470,7 @@ impl<'d> Handler for Control<'d> {
466 HID_REQ_SET_IDLE => { 470 HID_REQ_SET_IDLE => {
467 if let Some(handler) = self.request_handler { 471 if let Some(handler) = self.request_handler {
468 let id = req.value as u8; 472 let id = req.value as u8;
469 let id = (id != 0).then(|| ReportId::In(id)); 473 let id = (id != 0).then_some(ReportId::In(id));
470 let dur = u32::from(req.value >> 8); 474 let dur = u32::from(req.value >> 8);
471 let dur = if dur == 0 { u32::MAX } else { 4 * dur }; 475 let dur = if dur == 0 { u32::MAX } else { 4 * dur };
472 handler.set_idle_ms(id, dur); 476 handler.set_idle_ms(id, dur);
@@ -522,7 +526,7 @@ impl<'d> Handler for Control<'d> {
522 HID_REQ_GET_IDLE => { 526 HID_REQ_GET_IDLE => {
523 if let Some(handler) = self.request_handler { 527 if let Some(handler) = self.request_handler {
524 let id = req.value as u8; 528 let id = req.value as u8;
525 let id = (id != 0).then(|| ReportId::In(id)); 529 let id = (id != 0).then_some(ReportId::In(id));
526 if let Some(dur) = handler.get_idle_ms(id) { 530 if let Some(dur) = handler.get_idle_ms(id) {
527 let dur = u8::try_from(dur / 4).unwrap_or(0); 531 let dur = u8::try_from(dur / 4).unwrap_or(0);
528 buf[0] = dur; 532 buf[0] = dur;
diff --git a/embassy-usb/src/class/midi.rs b/embassy-usb/src/class/midi.rs
new file mode 100644
index 000000000..52a96f278
--- /dev/null
+++ b/embassy-usb/src/class/midi.rs
@@ -0,0 +1,227 @@
1//! MIDI class implementation.
2
3use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
4use crate::Builder;
5
6/// This should be used as `device_class` when building the `UsbDevice`.
7pub const USB_AUDIO_CLASS: u8 = 0x01;
8
9const USB_AUDIOCONTROL_SUBCLASS: u8 = 0x01;
10const USB_MIDISTREAMING_SUBCLASS: u8 = 0x03;
11const MIDI_IN_JACK_SUBTYPE: u8 = 0x02;
12const MIDI_OUT_JACK_SUBTYPE: u8 = 0x03;
13const EMBEDDED: u8 = 0x01;
14const EXTERNAL: u8 = 0x02;
15const CS_INTERFACE: u8 = 0x24;
16const CS_ENDPOINT: u8 = 0x25;
17const HEADER_SUBTYPE: u8 = 0x01;
18const MS_HEADER_SUBTYPE: u8 = 0x01;
19const MS_GENERAL: u8 = 0x01;
20const PROTOCOL_NONE: u8 = 0x00;
21const MIDI_IN_SIZE: u8 = 0x06;
22const MIDI_OUT_SIZE: u8 = 0x09;
23
24/// Packet level implementation of a USB MIDI device.
25///
26/// This class can be used directly and it has the least overhead due to directly reading and
27/// writing USB packets with no intermediate buffers, but it will not act like a stream-like port.
28/// The following constraints must be followed if you use this class directly:
29///
30/// - `read_packet` must be called with a buffer large enough to hold `max_packet_size` bytes.
31/// - `write_packet` must not be called with a buffer larger than `max_packet_size` bytes.
32/// - If you write a packet that is exactly `max_packet_size` bytes long, it won't be processed by the
33/// host operating system until a subsequent shorter packet is sent. A zero-length packet (ZLP)
34/// can be sent if there is no other data to send. This is because USB bulk transactions must be
35/// terminated with a short packet, even if the bulk endpoint is used for stream-like data.
36pub struct MidiClass<'d, D: Driver<'d>> {
37 read_ep: D::EndpointOut,
38 write_ep: D::EndpointIn,
39}
40
41impl<'d, D: Driver<'d>> MidiClass<'d, D> {
42 /// Creates a new `MidiClass` with the provided UsbBus, number of input and output jacks and `max_packet_size` in bytes.
43 /// For full-speed devices, `max_packet_size` has to be one of 8, 16, 32 or 64.
44 pub fn new(builder: &mut Builder<'d, D>, n_in_jacks: u8, n_out_jacks: u8, max_packet_size: u16) -> Self {
45 let mut func = builder.function(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE);
46
47 // Audio control interface
48 let mut iface = func.interface();
49 let audio_if = iface.interface_number();
50 let midi_if = u8::from(audio_if) + 1;
51 let mut alt = iface.alt_setting(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE, None);
52 alt.descriptor(CS_INTERFACE, &[HEADER_SUBTYPE, 0x00, 0x01, 0x09, 0x00, 0x01, midi_if]);
53
54 // MIDIStreaming interface
55 let mut iface = func.interface();
56 let _midi_if = iface.interface_number();
57 let mut alt = iface.alt_setting(USB_AUDIO_CLASS, USB_MIDISTREAMING_SUBCLASS, PROTOCOL_NONE, None);
58
59 let midi_streaming_total_length = 7
60 + (n_in_jacks + n_out_jacks) as usize * (MIDI_IN_SIZE + MIDI_OUT_SIZE) as usize
61 + 7
62 + (4 + n_out_jacks as usize)
63 + 7
64 + (4 + n_in_jacks as usize);
65
66 alt.descriptor(
67 CS_INTERFACE,
68 &[
69 MS_HEADER_SUBTYPE,
70 0x00,
71 0x01,
72 (midi_streaming_total_length & 0xFF) as u8,
73 ((midi_streaming_total_length >> 8) & 0xFF) as u8,
74 ],
75 );
76
77 // Calculates the index'th external midi in jack id
78 let in_jack_id_ext = |index| 2 * index + 1;
79 // Calculates the index'th embedded midi out jack id
80 let out_jack_id_emb = |index| 2 * index + 2;
81 // Calculates the index'th external midi out jack id
82 let out_jack_id_ext = |index| 2 * n_in_jacks + 2 * index + 1;
83 // Calculates the index'th embedded midi in jack id
84 let in_jack_id_emb = |index| 2 * n_in_jacks + 2 * index + 2;
85
86 for i in 0..n_in_jacks {
87 alt.descriptor(CS_INTERFACE, &[MIDI_IN_JACK_SUBTYPE, EXTERNAL, in_jack_id_ext(i), 0x00]);
88 }
89
90 for i in 0..n_out_jacks {
91 alt.descriptor(CS_INTERFACE, &[MIDI_IN_JACK_SUBTYPE, EMBEDDED, in_jack_id_emb(i), 0x00]);
92 }
93
94 for i in 0..n_out_jacks {
95 alt.descriptor(
96 CS_INTERFACE,
97 &[
98 MIDI_OUT_JACK_SUBTYPE,
99 EXTERNAL,
100 out_jack_id_ext(i),
101 0x01,
102 in_jack_id_emb(i),
103 0x01,
104 0x00,
105 ],
106 );
107 }
108
109 for i in 0..n_in_jacks {
110 alt.descriptor(
111 CS_INTERFACE,
112 &[
113 MIDI_OUT_JACK_SUBTYPE,
114 EMBEDDED,
115 out_jack_id_emb(i),
116 0x01,
117 in_jack_id_ext(i),
118 0x01,
119 0x00,
120 ],
121 );
122 }
123
124 let mut endpoint_data = [
125 MS_GENERAL, 0, // Number of jacks
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Jack mappings
127 ];
128 endpoint_data[1] = n_out_jacks;
129 for i in 0..n_out_jacks {
130 endpoint_data[2 + i as usize] = in_jack_id_emb(i);
131 }
132 let read_ep = alt.endpoint_bulk_out(max_packet_size);
133 alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_out_jacks as usize]);
134
135 endpoint_data[1] = n_in_jacks;
136 for i in 0..n_in_jacks {
137 endpoint_data[2 + i as usize] = out_jack_id_emb(i);
138 }
139 let write_ep = alt.endpoint_bulk_in(max_packet_size);
140 alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_in_jacks as usize]);
141
142 MidiClass { read_ep, write_ep }
143 }
144
145 /// Gets the maximum packet size in bytes.
146 pub fn max_packet_size(&self) -> u16 {
147 // The size is the same for both endpoints.
148 self.read_ep.info().max_packet_size
149 }
150
151 /// Writes a single packet into the IN endpoint.
152 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
153 self.write_ep.write(data).await
154 }
155
156 /// Reads a single packet from the OUT endpoint.
157 pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
158 self.read_ep.read(data).await
159 }
160
161 /// Waits for the USB host to enable this interface
162 pub async fn wait_connection(&mut self) {
163 self.read_ep.wait_enabled().await;
164 }
165
166 /// Split the class into a sender and receiver.
167 ///
168 /// This allows concurrently sending and receiving packets from separate tasks.
169 pub fn split(self) -> (Sender<'d, D>, Receiver<'d, D>) {
170 (
171 Sender {
172 write_ep: self.write_ep,
173 },
174 Receiver { read_ep: self.read_ep },
175 )
176 }
177}
178
179/// Midi class packet sender.
180///
181/// You can obtain a `Sender` with [`MidiClass::split`]
182pub struct Sender<'d, D: Driver<'d>> {
183 write_ep: D::EndpointIn,
184}
185
186impl<'d, D: Driver<'d>> Sender<'d, D> {
187 /// Gets the maximum packet size in bytes.
188 pub fn max_packet_size(&self) -> u16 {
189 // The size is the same for both endpoints.
190 self.write_ep.info().max_packet_size
191 }
192
193 /// Writes a single packet.
194 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
195 self.write_ep.write(data).await
196 }
197
198 /// Waits for the USB host to enable this interface
199 pub async fn wait_connection(&mut self) {
200 self.write_ep.wait_enabled().await;
201 }
202}
203
204/// Midi class packet receiver.
205///
206/// You can obtain a `Receiver` with [`MidiClass::split`]
207pub struct Receiver<'d, D: Driver<'d>> {
208 read_ep: D::EndpointOut,
209}
210
211impl<'d, D: Driver<'d>> Receiver<'d, D> {
212 /// Gets the maximum packet size in bytes.
213 pub fn max_packet_size(&self) -> u16 {
214 // The size is the same for both endpoints.
215 self.read_ep.info().max_packet_size
216 }
217
218 /// Reads a single packet.
219 pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
220 self.read_ep.read(data).await
221 }
222
223 /// Waits for the USB host to enable this interface
224 pub async fn wait_connection(&mut self) {
225 self.read_ep.wait_enabled().await;
226 }
227}
diff --git a/embassy-usb/src/class/mod.rs b/embassy-usb/src/class/mod.rs
index b23e03d40..452eedf17 100644
--- a/embassy-usb/src/class/mod.rs
+++ b/embassy-usb/src/class/mod.rs
@@ -2,3 +2,4 @@
2pub mod cdc_acm; 2pub mod cdc_acm;
3pub mod cdc_ncm; 3pub mod cdc_ncm;
4pub mod hid; 4pub mod hid;
5pub mod midi;
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index ceccfd85b..79f736309 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -120,7 +120,7 @@ impl Request {
120 } 120 }
121 121
122 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request. 122 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request.
123 pub fn descriptor_type_index(&self) -> (u8, u8) { 123 pub const fn descriptor_type_index(&self) -> (u8, u8) {
124 ((self.value >> 8) as u8, self.value as u8) 124 ((self.value >> 8) as u8, self.value as u8)
125 } 125 }
126} 126}
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index ae38e26ca..fa83ef583 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -2,7 +2,7 @@
2 2
3use crate::builder::Config; 3use crate::builder::Config;
4use crate::driver::EndpointInfo; 4use crate::driver::EndpointInfo;
5use crate::types::*; 5use crate::types::{InterfaceNumber, StringIndex};
6use crate::CONFIGURATION_VALUE; 6use crate::CONFIGURATION_VALUE;
7 7
8/// Standard descriptor types 8/// Standard descriptor types
@@ -59,7 +59,7 @@ impl<'a> DescriptorWriter<'a> {
59 } 59 }
60 60
61 /// Gets the current position in the buffer, i.e. the number of bytes written so far. 61 /// Gets the current position in the buffer, i.e. the number of bytes written so far.
62 pub fn position(&self) -> usize { 62 pub const fn position(&self) -> usize {
63 self.position 63 self.position
64 } 64 }
65 65
@@ -67,9 +67,10 @@ impl<'a> DescriptorWriter<'a> {
67 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) { 67 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) {
68 let length = descriptor.len(); 68 let length = descriptor.len();
69 69
70 if (self.position + 2 + length) > self.buf.len() || (length + 2) > 255 { 70 assert!(
71 panic!("Descriptor buffer full"); 71 (self.position + 2 + length) <= self.buf.len() && (length + 2) <= 255,
72 } 72 "Descriptor buffer full"
73 );
73 74
74 self.buf[self.position] = (length + 2) as u8; 75 self.buf[self.position] = (length + 2) as u8;
75 self.buf[self.position + 1] = descriptor_type; 76 self.buf[self.position + 1] = descriptor_type;
@@ -102,7 +103,7 @@ impl<'a> DescriptorWriter<'a> {
102 config.serial_number.map_or(0, |_| 3), // iSerialNumber 103 config.serial_number.map_or(0, |_| 3), // iSerialNumber
103 1, // bNumConfigurations 104 1, // bNumConfigurations
104 ], 105 ],
105 ) 106 );
106 } 107 }
107 108
108 pub(crate) fn configuration(&mut self, config: &Config) { 109 pub(crate) fn configuration(&mut self, config: &Config) {
@@ -120,7 +121,7 @@ impl<'a> DescriptorWriter<'a> {
120 | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, // bmAttributes 121 | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, // bmAttributes
121 (config.max_power / 2) as u8, // bMaxPower 122 (config.max_power / 2) as u8, // bMaxPower
122 ], 123 ],
123 ) 124 );
124 } 125 }
125 126
126 #[allow(unused)] 127 #[allow(unused)]
@@ -248,9 +249,7 @@ impl<'a> DescriptorWriter<'a> {
248 pub(crate) fn string(&mut self, string: &str) { 249 pub(crate) fn string(&mut self, string: &str) {
249 let mut pos = self.position; 250 let mut pos = self.position;
250 251
251 if pos + 2 > self.buf.len() { 252 assert!(pos + 2 <= self.buf.len(), "Descriptor buffer full");
252 panic!("Descriptor buffer full");
253 }
254 253
255 self.buf[pos] = 0; // length placeholder 254 self.buf[pos] = 0; // length placeholder
256 self.buf[pos + 1] = descriptor_type::STRING; 255 self.buf[pos + 1] = descriptor_type::STRING;
@@ -258,9 +257,7 @@ impl<'a> DescriptorWriter<'a> {
258 pos += 2; 257 pos += 2;
259 258
260 for c in string.encode_utf16() { 259 for c in string.encode_utf16() {
261 if pos >= self.buf.len() { 260 assert!(pos < self.buf.len(), "Descriptor buffer full");
262 panic!("Descriptor buffer full");
263 }
264 261
265 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); 262 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
266 pos += 2; 263 pos += 2;
@@ -279,9 +276,9 @@ pub struct BosWriter<'a> {
279} 276}
280 277
281impl<'a> BosWriter<'a> { 278impl<'a> BosWriter<'a> {
282 pub(crate) fn new(writer: DescriptorWriter<'a>) -> Self { 279 pub(crate) const fn new(writer: DescriptorWriter<'a>) -> Self {
283 Self { 280 Self {
284 writer: writer, 281 writer,
285 num_caps_mark: None, 282 num_caps_mark: None,
286 } 283 }
287 } 284 }
@@ -314,9 +311,10 @@ impl<'a> BosWriter<'a> {
314 let mut start = self.writer.position; 311 let mut start = self.writer.position;
315 let blen = data.len(); 312 let blen = data.len();
316 313
317 if (start + blen + 3) > self.writer.buf.len() || (blen + 3) > 255 { 314 assert!(
318 panic!("Descriptor buffer full"); 315 (start + blen + 3) <= self.writer.buf.len() && (blen + 3) <= 255,
319 } 316 "Descriptor buffer full"
317 );
320 318
321 self.writer.buf[start] = (blen + 3) as u8; 319 self.writer.buf[start] = (blen + 3) as u8;
322 self.writer.buf[start + 1] = descriptor_type::CAPABILITY; 320 self.writer.buf[start + 1] = descriptor_type::CAPABILITY;
diff --git a/embassy-usb/src/descriptor_reader.rs b/embassy-usb/src/descriptor_reader.rs
index 05adcce60..abb4b379e 100644
--- a/embassy-usb/src/descriptor_reader.rs
+++ b/embassy-usb/src/descriptor_reader.rs
@@ -11,11 +11,11 @@ pub struct Reader<'a> {
11} 11}
12 12
13impl<'a> Reader<'a> { 13impl<'a> Reader<'a> {
14 pub fn new(data: &'a [u8]) -> Self { 14 pub const fn new(data: &'a [u8]) -> Self {
15 Self { data } 15 Self { data }
16 } 16 }
17 17
18 pub fn eof(&self) -> bool { 18 pub const fn eof(&self) -> bool {
19 self.data.is_empty() 19 self.data.is_empty()
20 } 20 }
21 21
@@ -102,7 +102,7 @@ pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<
102 } 102 }
103 descriptor_type::ENDPOINT => { 103 descriptor_type::ENDPOINT => {
104 ep.ep_address = EndpointAddress::from(r.read_u8()?); 104 ep.ep_address = EndpointAddress::from(r.read_u8()?);
105 f(ep) 105 f(ep);
106 } 106 }
107 _ => {} 107 _ => {}
108 } 108 }
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 1180b9b66..88d88cad7 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -24,12 +24,12 @@ use embassy_futures::select::{select, Either};
24use heapless::Vec; 24use heapless::Vec;
25 25
26pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder}; 26pub use crate::builder::{Builder, Config, FunctionBuilder, InterfaceAltBuilder, InterfaceBuilder};
27use crate::config::*; 27use crate::config::{MAX_HANDLER_COUNT, MAX_INTERFACE_COUNT};
28use crate::control::*; 28use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType};
29use crate::descriptor::*; 29use crate::descriptor::{descriptor_type, lang_id};
30use crate::descriptor_reader::foreach_endpoint; 30use crate::descriptor_reader::foreach_endpoint;
31use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; 31use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event};
32use crate::types::*; 32use crate::types::{InterfaceNumber, StringIndex};
33 33
34/// The global state of the USB device. 34/// The global state of the USB device.
35/// 35///
@@ -294,7 +294,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
294 /// After dropping the future, [`UsbDevice::disable()`] should be called 294 /// After dropping the future, [`UsbDevice::disable()`] should be called
295 /// before calling any other `UsbDevice` methods to fully reset the 295 /// before calling any other `UsbDevice` methods to fully reset the
296 /// peripheral. 296 /// peripheral.
297 pub async fn run_until_suspend(&mut self) -> () { 297 pub async fn run_until_suspend(&mut self) {
298 while !self.inner.suspended { 298 while !self.inner.suspended {
299 let control_fut = self.control.setup(); 299 let control_fut = self.control.setup();
300 let bus_fut = self.inner.bus.poll(); 300 let bus_fut = self.inner.bus.poll();
@@ -364,6 +364,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
364 } 364 }
365 365
366 async fn handle_control_in(&mut self, req: Request) { 366 async fn handle_control_in(&mut self, req: Request) {
367 const DEVICE_DESCRIPTOR_LEN: usize = 18;
368
367 let mut resp_length = req.length as usize; 369 let mut resp_length = req.length as usize;
368 let max_packet_size = self.control.max_packet_size(); 370 let max_packet_size = self.control.max_packet_size();
369 371
@@ -371,19 +373,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
371 // The host doesn't know our EP0 max packet size yet, and might assume 373 // The host doesn't know our EP0 max packet size yet, and might assume
372 // a full-length packet is a short packet, thinking we're done sending data. 374 // a full-length packet is a short packet, thinking we're done sending data.
373 // See https://github.com/hathach/tinyusb/issues/184 375 // See https://github.com/hathach/tinyusb/issues/184
374 const DEVICE_DESCRIPTOR_LEN: usize = 18; 376 if self.inner.address == 0 && max_packet_size < DEVICE_DESCRIPTOR_LEN && max_packet_size < resp_length {
375 if self.inner.address == 0
376 && max_packet_size < DEVICE_DESCRIPTOR_LEN
377 && (max_packet_size as usize) < resp_length
378 {
379 trace!("received control req while not addressed: capping response to 1 packet."); 377 trace!("received control req while not addressed: capping response to 1 packet.");
380 resp_length = max_packet_size; 378 resp_length = max_packet_size;
381 } 379 }
382 380
383 match self.inner.handle_control_in(req, &mut self.control_buf) { 381 match self.inner.handle_control_in(req, self.control_buf) {
384 InResponse::Accepted(data) => { 382 InResponse::Accepted(data) => {
385 let len = data.len().min(resp_length); 383 let len = data.len().min(resp_length);
386 let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0; 384 let need_zlp = len != resp_length && (len % max_packet_size) == 0;
387 385
388 let chunks = data[0..len] 386 let chunks = data[0..len]
389 .chunks(max_packet_size) 387 .chunks(max_packet_size)
@@ -435,7 +433,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
435 self.control.accept_set_address(self.inner.address).await; 433 self.control.accept_set_address(self.inner.address).await;
436 self.inner.set_address_pending = false; 434 self.inner.set_address_pending = false;
437 } else { 435 } else {
438 self.control.accept().await 436 self.control.accept().await;
439 } 437 }
440 } 438 }
441 OutResponse::Rejected => self.control.reject().await, 439 OutResponse::Rejected => self.control.reject().await,
@@ -548,9 +546,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
548 546
549 OutResponse::Accepted 547 OutResponse::Accepted
550 } 548 }
551 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { 549 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => {
552 UsbDeviceState::Default => OutResponse::Accepted, 550 if self.device_state != UsbDeviceState::Default {
553 _ => {
554 debug!("SET_CONFIGURATION: unconfigured"); 551 debug!("SET_CONFIGURATION: unconfigured");
555 self.device_state = UsbDeviceState::Addressed; 552 self.device_state = UsbDeviceState::Addressed;
556 553
@@ -564,17 +561,15 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
564 for h in &mut self.handlers { 561 for h in &mut self.handlers {
565 h.configured(false); 562 h.configured(false);
566 } 563 }
567
568 OutResponse::Accepted
569 } 564 }
570 }, 565 OutResponse::Accepted
566 }
571 _ => OutResponse::Rejected, 567 _ => OutResponse::Rejected,
572 }, 568 },
573 (RequestType::Standard, Recipient::Interface) => { 569 (RequestType::Standard, Recipient::Interface) => {
574 let iface_num = InterfaceNumber::new(req.index as _); 570 let iface_num = InterfaceNumber::new(req.index as _);
575 let iface = match self.interfaces.get_mut(iface_num.0 as usize) { 571 let Some(iface) = self.interfaces.get_mut(iface_num.0 as usize) else {
576 Some(iface) => iface, 572 return OutResponse::Rejected;
577 None => return OutResponse::Rejected,
578 }; 573 };
579 574
580 match req.request { 575 match req.request {
@@ -650,9 +645,8 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
650 _ => InResponse::Rejected, 645 _ => InResponse::Rejected,
651 }, 646 },
652 (RequestType::Standard, Recipient::Interface) => { 647 (RequestType::Standard, Recipient::Interface) => {
653 let iface = match self.interfaces.get_mut(req.index as usize) { 648 let Some(iface) = self.interfaces.get_mut(req.index as usize) else {
654 Some(iface) => iface, 649 return InResponse::Rejected;
655 None => return InResponse::Rejected,
656 }; 650 };
657 651
658 match req.request { 652 match req.request {
@@ -706,7 +700,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
706 } 700 }
707 701
708 fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { 702 fn handle_control_in_delegated<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
709 unsafe fn extend_lifetime<'x, 'y>(r: InResponse<'x>) -> InResponse<'y> { 703 unsafe fn extend_lifetime<'y>(r: InResponse<'_>) -> InResponse<'y> {
710 core::mem::transmute(r) 704 core::mem::transmute(r)
711 } 705 }
712 706
@@ -756,16 +750,12 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
756 }; 750 };
757 751
758 if let Some(s) = s { 752 if let Some(s) = s {
759 if buf.len() < 2 { 753 assert!(buf.len() >= 2, "control buffer too small");
760 panic!("control buffer too small");
761 }
762 754
763 buf[1] = descriptor_type::STRING; 755 buf[1] = descriptor_type::STRING;
764 let mut pos = 2; 756 let mut pos = 2;
765 for c in s.encode_utf16() { 757 for c in s.encode_utf16() {
766 if pos + 2 >= buf.len() { 758 assert!(pos + 2 < buf.len(), "control buffer too small");
767 panic!("control buffer too small");
768 }
769 759
770 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); 760 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
771 pos += 2; 761 pos += 2;
diff --git a/embassy-usb/src/msos.rs b/embassy-usb/src/msos.rs
index 847338e5f..13d5d7c4b 100644
--- a/embassy-usb/src/msos.rs
+++ b/embassy-usb/src/msos.rs
@@ -6,7 +6,7 @@
6 6
7use core::mem::size_of; 7use core::mem::size_of;
8 8
9use super::{capability_type, BosWriter}; 9use crate::descriptor::{capability_type, BosWriter};
10use crate::types::InterfaceNumber; 10use crate::types::InterfaceNumber;
11 11
12/// A serialized Microsoft OS 2.0 Descriptor set. 12/// A serialized Microsoft OS 2.0 Descriptor set.
diff --git a/embassy-usb/src/types.rs b/embassy-usb/src/types.rs
index c7a47f7e4..cb9fe2576 100644
--- a/embassy-usb/src/types.rs
+++ b/embassy-usb/src/types.rs
@@ -7,7 +7,7 @@
7pub struct InterfaceNumber(pub u8); 7pub struct InterfaceNumber(pub u8);
8 8
9impl InterfaceNumber { 9impl InterfaceNumber {
10 pub(crate) fn new(index: u8) -> InterfaceNumber { 10 pub(crate) const fn new(index: u8) -> InterfaceNumber {
11 InterfaceNumber(index) 11 InterfaceNumber(index)
12 } 12 }
13} 13}
@@ -25,7 +25,7 @@ impl From<InterfaceNumber> for u8 {
25pub struct StringIndex(pub u8); 25pub struct StringIndex(pub u8);
26 26
27impl StringIndex { 27impl StringIndex {
28 pub(crate) fn new(index: u8) -> StringIndex { 28 pub(crate) const fn new(index: u8) -> StringIndex {
29 StringIndex(index) 29 StringIndex(index)
30 } 30 }
31} 31}
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index 435a33919..275367ff7 100644
--- a/examples/boot/application/nrf/Cargo.toml
+++ b/examples/boot/application/nrf/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly"] }
11embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } 11embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] }
12embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } 12embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] }
13embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } 13embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] }
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs
index 15ebce5fa..a88c3c56c 100644
--- a/examples/boot/application/nrf/src/bin/b.rs
+++ b/examples/boot/application/nrf/src/bin/b.rs
@@ -5,7 +5,7 @@
5 5
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use panic_reset as _; 9use panic_reset as _;
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -19,8 +19,8 @@ async fn main(_spawner: Spawner) {
19 19
20 loop { 20 loop {
21 led.set_high(); 21 led.set_high();
22 Timer::after(Duration::from_millis(300)).await; 22 Timer::after_millis(300).await;
23 led.set_low(); 23 led.set_low();
24 Timer::after(Duration::from_millis(300)).await; 24 Timer::after_millis(300).await;
25 } 25 }
26} 26}
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml
index 01cfc5994..da89f15da 100644
--- a/examples/boot/application/rp/Cargo.toml
+++ b/examples/boot/application/rp/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly"] }
11embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } 11embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] }
12embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } 12embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs
index a4602a7ed..6fd5d7f60 100644
--- a/examples/boot/application/rp/src/bin/a.rs
+++ b/examples/boot/application/rp/src/bin/a.rs
@@ -41,7 +41,7 @@ async fn main(_s: Spawner) {
41 let mut aligned = AlignedBuffer([0; 1]); 41 let mut aligned = AlignedBuffer([0; 1]);
42 let mut updater = BlockingFirmwareUpdater::new(config, &mut aligned.0); 42 let mut updater = BlockingFirmwareUpdater::new(config, &mut aligned.0);
43 43
44 Timer::after(Duration::from_secs(5)).await; 44 Timer::after_secs(5).await;
45 watchdog.feed(); 45 watchdog.feed();
46 led.set_high(); 46 led.set_high();
47 let mut offset = 0; 47 let mut offset = 0;
@@ -61,7 +61,7 @@ async fn main(_s: Spawner) {
61 watchdog.feed(); 61 watchdog.feed();
62 defmt::info!("firmware written, marking update"); 62 defmt::info!("firmware written, marking update");
63 updater.mark_updated().unwrap(); 63 updater.mark_updated().unwrap();
64 Timer::after(Duration::from_secs(2)).await; 64 Timer::after_secs(2).await;
65 led.set_low(); 65 led.set_low();
66 defmt::info!("update marked, resetting"); 66 defmt::info!("update marked, resetting");
67 cortex_m::peripheral::SCB::sys_reset(); 67 cortex_m::peripheral::SCB::sys_reset();
diff --git a/examples/boot/application/rp/src/bin/b.rs b/examples/boot/application/rp/src/bin/b.rs
index 47dec329c..1eca5b4a2 100644
--- a/examples/boot/application/rp/src/bin/b.rs
+++ b/examples/boot/application/rp/src/bin/b.rs
@@ -4,7 +4,7 @@
4 4
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::gpio; 6use embassy_rp::gpio;
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use gpio::{Level, Output}; 8use gpio::{Level, Output};
9use {defmt_rtt as _, panic_reset as _}; 9use {defmt_rtt as _, panic_reset as _};
10 10
@@ -15,9 +15,9 @@ async fn main(_s: Spawner) {
15 15
16 loop { 16 loop {
17 led.set_high(); 17 led.set_high();
18 Timer::after(Duration::from_millis(100)).await; 18 Timer::after_millis(100).await;
19 19
20 led.set_low(); 20 led.set_low();
21 Timer::after(Duration::from_millis(100)).await; 21 Timer::after_millis(100).await;
22 } 22 }
23} 23}
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml
index a0649cf83..147a5bcf5 100644
--- a/examples/boot/application/stm32f3/Cargo.toml
+++ b/examples/boot/application/stm32f3/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32f3/src/bin/b.rs b/examples/boot/application/stm32f3/src/bin/b.rs
index a5862b1b0..8411f384c 100644
--- a/examples/boot/application/stm32f3/src/bin/b.rs
+++ b/examples/boot/application/stm32f3/src/bin/b.rs
@@ -6,7 +6,7 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,9 +16,9 @@ async fn main(_spawner: Spawner) {
16 16
17 loop { 17 loop {
18 led.set_high(); 18 led.set_high();
19 Timer::after(Duration::from_millis(500)).await; 19 Timer::after_millis(500).await;
20 20
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(500)).await; 22 Timer::after_millis(500).await;
23 } 23 }
24} 24}
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml
index ca1c0c424..3fa136aea 100644
--- a/examples/boot/application/stm32f7/Cargo.toml
+++ b/examples/boot/application/stm32f7/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32f7/src/bin/b.rs b/examples/boot/application/stm32f7/src/bin/b.rs
index 16c94d845..4c2ad06a2 100644
--- a/examples/boot/application/stm32f7/src/bin/b.rs
+++ b/examples/boot/application/stm32f7/src/bin/b.rs
@@ -6,21 +6,21 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 Timer::after(Duration::from_millis(300)).await; 15 Timer::after_millis(300).await;
16 let mut led = Output::new(p.PB7, Level::High, Speed::Low); 16 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
17 led.set_high(); 17 led.set_high();
18 18
19 loop { 19 loop {
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 led.set_low(); 23 led.set_low();
24 Timer::after(Duration::from_millis(500)).await; 24 Timer::after_millis(500).await;
25 } 25 }
26} 26}
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml
index e50c8c415..7ca767bde 100644
--- a/examples/boot/application/stm32h7/Cargo.toml
+++ b/examples/boot/application/stm32h7/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32h7/src/bin/b.rs b/examples/boot/application/stm32h7/src/bin/b.rs
index 34799279c..5c03e2d0c 100644
--- a/examples/boot/application/stm32h7/src/bin/b.rs
+++ b/examples/boot/application/stm32h7/src/bin/b.rs
@@ -6,21 +6,21 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 Timer::after(Duration::from_millis(300)).await; 15 Timer::after_millis(300).await;
16 let mut led = Output::new(p.PB14, Level::High, Speed::Low); 16 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
17 led.set_high(); 17 led.set_high();
18 18
19 loop { 19 loop {
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 led.set_low(); 23 led.set_low();
24 Timer::after(Duration::from_millis(500)).await; 24 Timer::after_millis(500).await;
25 } 25 }
26} 26}
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml
index 1f1a0f3cf..3e3cbbd82 100644
--- a/examples/boot/application/stm32l0/Cargo.toml
+++ b/examples/boot/application/stm32l0/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs
index b4cdcd44d..42e1a71eb 100644
--- a/examples/boot/application/stm32l0/src/bin/a.rs
+++ b/examples/boot/application/stm32l0/src/bin/a.rs
@@ -11,7 +11,7 @@ use embassy_stm32::exti::ExtiInput;
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
13use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
14use embassy_time::{Duration, Timer}; 14use embassy_time::Timer;
15use panic_reset as _; 15use panic_reset as _;
16 16
17#[cfg(feature = "skip-include")] 17#[cfg(feature = "skip-include")]
@@ -46,6 +46,6 @@ async fn main(_spawner: Spawner) {
46 46
47 updater.mark_updated().await.unwrap(); 47 updater.mark_updated().await.unwrap();
48 led.set_low(); 48 led.set_low();
49 Timer::after(Duration::from_secs(1)).await; 49 Timer::after_secs(1).await;
50 cortex_m::peripheral::SCB::sys_reset(); 50 cortex_m::peripheral::SCB::sys_reset();
51} 51}
diff --git a/examples/boot/application/stm32l0/src/bin/b.rs b/examples/boot/application/stm32l0/src/bin/b.rs
index ee40274ff..52d42395f 100644
--- a/examples/boot/application/stm32l0/src/bin/b.rs
+++ b/examples/boot/application/stm32l0/src/bin/b.rs
@@ -6,7 +6,7 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,9 +16,9 @@ async fn main(_spawner: Spawner) {
16 16
17 loop { 17 loop {
18 led.set_high(); 18 led.set_high();
19 Timer::after(Duration::from_millis(500)).await; 19 Timer::after_millis(500).await;
20 20
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(500)).await; 22 Timer::after_millis(500).await;
23 } 23 }
24} 24}
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml
index 45b12813e..5e77b7d53 100644
--- a/examples/boot/application/stm32l1/Cargo.toml
+++ b/examples/boot/application/stm32l1/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs
index b4cdcd44d..42e1a71eb 100644
--- a/examples/boot/application/stm32l1/src/bin/a.rs
+++ b/examples/boot/application/stm32l1/src/bin/a.rs
@@ -11,7 +11,7 @@ use embassy_stm32::exti::ExtiInput;
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
13use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
14use embassy_time::{Duration, Timer}; 14use embassy_time::Timer;
15use panic_reset as _; 15use panic_reset as _;
16 16
17#[cfg(feature = "skip-include")] 17#[cfg(feature = "skip-include")]
@@ -46,6 +46,6 @@ async fn main(_spawner: Spawner) {
46 46
47 updater.mark_updated().await.unwrap(); 47 updater.mark_updated().await.unwrap();
48 led.set_low(); 48 led.set_low();
49 Timer::after(Duration::from_secs(1)).await; 49 Timer::after_secs(1).await;
50 cortex_m::peripheral::SCB::sys_reset(); 50 cortex_m::peripheral::SCB::sys_reset();
51} 51}
diff --git a/examples/boot/application/stm32l1/src/bin/b.rs b/examples/boot/application/stm32l1/src/bin/b.rs
index ee40274ff..52d42395f 100644
--- a/examples/boot/application/stm32l1/src/bin/b.rs
+++ b/examples/boot/application/stm32l1/src/bin/b.rs
@@ -6,7 +6,7 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,9 +16,9 @@ async fn main(_spawner: Spawner) {
16 16
17 loop { 17 loop {
18 led.set_high(); 18 led.set_high();
19 Timer::after(Duration::from_millis(500)).await; 19 Timer::after_millis(500).await;
20 20
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(500)).await; 22 Timer::after_millis(500).await;
23 } 23 }
24} 24}
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml
index d0d0d0fbe..aa5c5cf9f 100644
--- a/examples/boot/application/stm32l4/Cargo.toml
+++ b/examples/boot/application/stm32l4/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32l4/src/bin/b.rs b/examples/boot/application/stm32l4/src/bin/b.rs
index a5862b1b0..8411f384c 100644
--- a/examples/boot/application/stm32l4/src/bin/b.rs
+++ b/examples/boot/application/stm32l4/src/bin/b.rs
@@ -6,7 +6,7 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,9 +16,9 @@ async fn main(_spawner: Spawner) {
16 16
17 loop { 17 loop {
18 led.set_high(); 18 led.set_high();
19 Timer::after(Duration::from_millis(500)).await; 19 Timer::after_millis(500).await;
20 20
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(500)).await; 22 Timer::after_millis(500).await;
23 } 23 }
24} 24}
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml
index 3265b9f1a..87b8a1161 100644
--- a/examples/boot/application/stm32wl/Cargo.toml
+++ b/examples/boot/application/stm32wl/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" } 8embassy-sync = { version = "0.3.0", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } 12embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] }
13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } 13embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" }
diff --git a/examples/boot/application/stm32wl/src/bin/b.rs b/examples/boot/application/stm32wl/src/bin/b.rs
index f9f0ffc60..1ca3c6ea8 100644
--- a/examples/boot/application/stm32wl/src/bin/b.rs
+++ b/examples/boot/application/stm32wl/src/bin/b.rs
@@ -6,7 +6,7 @@
6use defmt_rtt::*; 6use defmt_rtt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use panic_reset as _; 10use panic_reset as _;
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,9 +16,9 @@ async fn main(_spawner: Spawner) {
16 16
17 loop { 17 loop {
18 led.set_high(); 18 led.set_high();
19 Timer::after(Duration::from_millis(500)).await; 19 Timer::after_millis(500).await;
20 20
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(500)).await; 22 Timer::after_millis(500).await;
23 } 23 }
24} 24}
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
index e402e49f4..e5820f26d 100644
--- a/examples/nrf-rtos-trace/Cargo.toml
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -18,7 +18,7 @@ log = [
18[dependencies] 18[dependencies]
19embassy-sync = { version = "0.3.0", path = "../../embassy-sync" } 19embassy-sync = { version = "0.3.0", path = "../../embassy-sync" }
20embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } 20embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] }
21embassy-time = { version = "0.1.3", path = "../../embassy-time" } 21embassy-time = { version = "0.1.5", path = "../../embassy-time" }
22embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 22embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
23 23
24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
index cf8b2f808..888375693 100644
--- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
+++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
@@ -6,7 +6,7 @@ use core::future::poll_fn;
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_time::{Duration, Instant, Timer}; 9use embassy_time::{Instant, Timer};
10#[cfg(feature = "log")] 10#[cfg(feature = "log")]
11use log::*; 11use log::*;
12use panic_probe as _; 12use panic_probe as _;
@@ -34,7 +34,7 @@ async fn run1() {
34 info!("DING DONG"); 34 info!("DING DONG");
35 #[cfg(not(feature = "log"))] 35 #[cfg(not(feature = "log"))]
36 rtos_trace::trace::marker(13); 36 rtos_trace::trace::marker(13);
37 Timer::after(Duration::from_ticks(16000)).await; 37 Timer::after_ticks(16000).await;
38 } 38 }
39} 39}
40 40
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml
index c588b807e..a81d43a26 100644
--- a/examples/nrf52840-rtic/Cargo.toml
+++ b/examples/nrf52840-rtic/Cargo.toml
@@ -9,7 +9,7 @@ rtic = { version = "2", features = ["thumbv7-backend"] }
9 9
10embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 10embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] }
13embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
14 14
15defmt = "0.3" 15defmt = "0.3"
diff --git a/examples/nrf52840-rtic/memory.x b/examples/nrf52840-rtic/memory.x
index 9b04edec0..15b492bce 100644
--- a/examples/nrf52840-rtic/memory.x
+++ b/examples/nrf52840-rtic/memory.x
@@ -1,7 +1,12 @@
1MEMORY 1MEMORY
2{ 2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */ 3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 /* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */
5 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K 4 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
6 RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 RAM : ORIGIN = 0x20000000, LENGTH = 256K
6
7 /* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */
8 /*
9 FLASH : ORIGIN = 0x00027000, LENGTH = 868K
10 RAM : ORIGIN = 0x20020000, LENGTH = 128K
11 */
7} 12}
diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs
index a682c1932..060bb9ebc 100644
--- a/examples/nrf52840-rtic/src/bin/blinky.rs
+++ b/examples/nrf52840-rtic/src/bin/blinky.rs
@@ -9,7 +9,7 @@ mod app {
9 use defmt::info; 9 use defmt::info;
10 use embassy_nrf::gpio::{Level, Output, OutputDrive}; 10 use embassy_nrf::gpio::{Level, Output, OutputDrive};
11 use embassy_nrf::peripherals; 11 use embassy_nrf::peripherals;
12 use embassy_time::{Duration, Timer}; 12 use embassy_time::Timer;
13 13
14 #[shared] 14 #[shared]
15 struct Shared {} 15 struct Shared {}
@@ -34,10 +34,10 @@ mod app {
34 loop { 34 loop {
35 info!("off!"); 35 info!("off!");
36 led.set_high(); 36 led.set_high();
37 Timer::after(Duration::from_millis(300)).await; 37 Timer::after_millis(300).await;
38 info!("on!"); 38 info!("on!");
39 led.set_low(); 39 led.set_low();
40 Timer::after(Duration::from_millis(300)).await; 40 Timer::after_millis(300).await;
41 } 41 }
42 } 42 }
43} 43}
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index d45e006c7..753733509 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -31,12 +31,12 @@ nightly = [
31embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 31embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
32embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 32embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
33embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 33embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
34embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 34embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
35embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 35embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
36embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } 36embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
37embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } 37embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true }
38embedded-io = { version = "0.5.0", features = ["defmt-03"] } 38embedded-io = { version = "0.6.0", features = ["defmt-03"] }
39embedded-io-async = { version = "0.5.0", optional = true, features = ["defmt-03"] } 39embedded-io-async = { version = "0.6.0", optional = true, features = ["defmt-03"] }
40embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } 40embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true }
41lora-phy = { version = "2", optional = true } 41lora-phy = { version = "2", optional = true }
42lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"], optional = true } 42lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"], optional = true }
diff --git a/examples/nrf52840/memory.x b/examples/nrf52840/memory.x
index 9b04edec0..15b492bce 100644
--- a/examples/nrf52840/memory.x
+++ b/examples/nrf52840/memory.x
@@ -1,7 +1,12 @@
1MEMORY 1MEMORY
2{ 2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */ 3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 /* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */
5 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K 4 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
6 RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 RAM : ORIGIN = 0x20000000, LENGTH = 256K
6
7 /* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */
8 /*
9 FLASH : ORIGIN = 0x00027000, LENGTH = 868K
10 RAM : ORIGIN = 0x20020000, LENGTH = 128K
11 */
7} 12}
diff --git a/examples/nrf52840/src/bin/blinky.rs b/examples/nrf52840/src/bin/blinky.rs
index 513f6cd82..d3d1a7122 100644
--- a/examples/nrf52840/src/bin/blinky.rs
+++ b/examples/nrf52840/src/bin/blinky.rs
@@ -4,7 +4,7 @@
4 4
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive}; 6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
@@ -14,8 +14,8 @@ async fn main(_spawner: Spawner) {
14 14
15 loop { 15 loop {
16 led.set_high(); 16 led.set_high();
17 Timer::after(Duration::from_millis(300)).await; 17 Timer::after_millis(300).await;
18 led.set_low(); 18 led.set_low();
19 Timer::after(Duration::from_millis(300)).await; 19 Timer::after_millis(300).await;
20 } 20 }
21} 21}
diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs
index bd9c909da..d3c7b47d2 100644
--- a/examples/nrf52840/src/bin/channel.rs
+++ b/examples/nrf52840/src/bin/channel.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 8use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
9use embassy_sync::channel::Channel; 9use embassy_sync::channel::Channel;
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13enum LedState { 13enum LedState {
@@ -21,9 +21,9 @@ static CHANNEL: Channel<ThreadModeRawMutex, LedState, 1> = Channel::new();
21async fn my_task() { 21async fn my_task() {
22 loop { 22 loop {
23 CHANNEL.send(LedState::On).await; 23 CHANNEL.send(LedState::On).await;
24 Timer::after(Duration::from_secs(1)).await; 24 Timer::after_secs(1).await;
25 CHANNEL.send(LedState::Off).await; 25 CHANNEL.send(LedState::Off).await;
26 Timer::after(Duration::from_secs(1)).await; 26 Timer::after_secs(1).await;
27 } 27 }
28} 28}
29 29
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs
index ec4f1d800..79d2c4048 100644
--- a/examples/nrf52840/src/bin/channel_sender_receiver.rs
+++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; 7use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin};
8use embassy_sync::blocking_mutex::raw::NoopRawMutex; 8use embassy_sync::blocking_mutex::raw::NoopRawMutex;
9use embassy_sync::channel::{Channel, Receiver, Sender}; 9use embassy_sync::channel::{Channel, Receiver, Sender};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -22,9 +22,9 @@ static CHANNEL: StaticCell<Channel<NoopRawMutex, LedState, 1>> = StaticCell::new
22async fn send_task(sender: Sender<'static, NoopRawMutex, LedState, 1>) { 22async fn send_task(sender: Sender<'static, NoopRawMutex, LedState, 1>) {
23 loop { 23 loop {
24 sender.send(LedState::On).await; 24 sender.send(LedState::On).await;
25 Timer::after(Duration::from_secs(1)).await; 25 Timer::after_secs(1).await;
26 sender.send(LedState::Off).await; 26 sender.send(LedState::Off).await;
27 Timer::after(Duration::from_secs(1)).await; 27 Timer::after_secs(1).await;
28 } 28 }
29} 29}
30 30
diff --git a/examples/nrf52840/src/bin/executor_fairness_test.rs b/examples/nrf52840/src/bin/executor_fairness_test.rs
index 2a28f2763..f111b272e 100644
--- a/examples/nrf52840/src/bin/executor_fairness_test.rs
+++ b/examples/nrf52840/src/bin/executor_fairness_test.rs
@@ -7,14 +7,14 @@ use core::task::Poll;
7 7
8use defmt::{info, unwrap}; 8use defmt::{info, unwrap};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_time::{Duration, Instant, Timer}; 10use embassy_time::{Instant, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::task] 13#[embassy_executor::task]
14async fn run1() { 14async fn run1() {
15 loop { 15 loop {
16 info!("DING DONG"); 16 info!("DING DONG");
17 Timer::after(Duration::from_ticks(16000)).await; 17 Timer::after_ticks(16000).await;
18 } 18 }
19} 19}
20 20
diff --git a/examples/nrf52840/src/bin/lora_cad.rs b/examples/nrf52840/src/bin/lora_cad.rs
index 3a98133c9..38e6d6197 100644
--- a/examples/nrf52840/src/bin/lora_cad.rs
+++ b/examples/nrf52840/src/bin/lora_cad.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant; 11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; 12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
13use embassy_nrf::{bind_interrupts, peripherals, spim}; 13use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard); 55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
56 56
57 start_indicator.set_high(); 57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await; 58 Timer::after_secs(5).await;
59 start_indicator.set_low(); 59 start_indicator.set_low();
60 60
61 let mdltn_params = { 61 let mdltn_params = {
@@ -89,7 +89,7 @@ async fn main(_spawner: Spawner) {
89 info!("cad successful without activity detected") 89 info!("cad successful without activity detected")
90 } 90 }
91 debug_indicator.set_high(); 91 debug_indicator.set_high();
92 Timer::after(Duration::from_secs(5)).await; 92 Timer::after_secs(5).await;
93 debug_indicator.set_low(); 93 debug_indicator.set_low();
94 } 94 }
95 Err(err) => info!("cad unsuccessful = {}", err), 95 Err(err) => info!("cad unsuccessful = {}", err),
diff --git a/examples/nrf52840/src/bin/lora_p2p_receive.rs b/examples/nrf52840/src/bin/lora_p2p_receive.rs
index 1d293c6bf..4f41e1245 100644
--- a/examples/nrf52840/src/bin/lora_p2p_receive.rs
+++ b/examples/nrf52840/src/bin/lora_p2p_receive.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant; 11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; 12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
13use embassy_nrf::{bind_interrupts, peripherals, spim}; 13use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard); 55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
56 56
57 start_indicator.set_high(); 57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await; 58 Timer::after_secs(5).await;
59 start_indicator.set_low(); 59 start_indicator.set_low();
60 60
61 let mut receiving_buffer = [00u8; 100]; 61 let mut receiving_buffer = [00u8; 100];
@@ -107,7 +107,7 @@ async fn main(_spawner: Spawner) {
107 { 107 {
108 info!("rx successful"); 108 info!("rx successful");
109 debug_indicator.set_high(); 109 debug_indicator.set_high();
110 Timer::after(Duration::from_secs(5)).await; 110 Timer::after_secs(5).await;
111 debug_indicator.set_low(); 111 debug_indicator.set_low();
112 } else { 112 } else {
113 info!("rx unknown packet"); 113 info!("rx unknown packet");
diff --git a/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
index eee4d20e7..3d34f6aef 100644
--- a/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
+++ b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant; 11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; 12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
13use embassy_nrf::{bind_interrupts, peripherals, spim}; 13use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard); 55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
56 56
57 start_indicator.set_high(); 57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await; 58 Timer::after_secs(5).await;
59 start_indicator.set_low(); 59 start_indicator.set_low();
60 60
61 let mut receiving_buffer = [00u8; 100]; 61 let mut receiving_buffer = [00u8; 100];
@@ -116,7 +116,7 @@ async fn main(_spawner: Spawner) {
116 { 116 {
117 info!("rx successful"); 117 info!("rx successful");
118 debug_indicator.set_high(); 118 debug_indicator.set_high();
119 Timer::after(Duration::from_secs(5)).await; 119 Timer::after_secs(5).await;
120 debug_indicator.set_low(); 120 debug_indicator.set_low();
121 } else { 121 } else {
122 info!("rx unknown packet") 122 info!("rx unknown packet")
diff --git a/examples/nrf52840/src/bin/manually_create_executor.rs b/examples/nrf52840/src/bin/manually_create_executor.rs
index 12ce660f9..80364d34a 100644
--- a/examples/nrf52840/src/bin/manually_create_executor.rs
+++ b/examples/nrf52840/src/bin/manually_create_executor.rs
@@ -8,7 +8,7 @@
8use cortex_m_rt::entry; 8use cortex_m_rt::entry;
9use defmt::{info, unwrap}; 9use defmt::{info, unwrap};
10use embassy_executor::Executor; 10use embassy_executor::Executor;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use static_cell::StaticCell; 12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
@@ -16,7 +16,7 @@ use {defmt_rtt as _, panic_probe as _};
16async fn run1() { 16async fn run1() {
17 loop { 17 loop {
18 info!("BIG INFREQUENT TICK"); 18 info!("BIG INFREQUENT TICK");
19 Timer::after(Duration::from_ticks(64000)).await; 19 Timer::after_ticks(64000).await;
20 } 20 }
21} 21}
22 22
@@ -24,7 +24,7 @@ async fn run1() {
24async fn run2() { 24async fn run2() {
25 loop { 25 loop {
26 info!("tick"); 26 info!("tick");
27 Timer::after(Duration::from_ticks(13000)).await; 27 Timer::after_ticks(13000).await;
28 } 28 }
29} 29}
30 30
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs
index aab819117..352f62bf2 100644
--- a/examples/nrf52840/src/bin/multiprio.rs
+++ b/examples/nrf52840/src/bin/multiprio.rs
@@ -62,7 +62,7 @@ use defmt::{info, unwrap};
62use embassy_executor::{Executor, InterruptExecutor}; 62use embassy_executor::{Executor, InterruptExecutor};
63use embassy_nrf::interrupt; 63use embassy_nrf::interrupt;
64use embassy_nrf::interrupt::{InterruptExt, Priority}; 64use embassy_nrf::interrupt::{InterruptExt, Priority};
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Instant, Timer};
66use static_cell::StaticCell; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
@@ -70,7 +70,7 @@ use {defmt_rtt as _, panic_probe as _};
70async fn run_high() { 70async fn run_high() {
71 loop { 71 loop {
72 info!(" [high] tick!"); 72 info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(27374)).await; 73 Timer::after_ticks(27374).await;
74 } 74 }
75} 75}
76 76
@@ -87,7 +87,7 @@ async fn run_med() {
87 let ms = end.duration_since(start).as_ticks() / 33; 87 let ms = end.duration_since(start).as_ticks() / 33;
88 info!(" [med] done in {} ms", ms); 88 info!(" [med] done in {} ms", ms);
89 89
90 Timer::after(Duration::from_ticks(23421)).await; 90 Timer::after_ticks(23421).await;
91 } 91 }
92} 92}
93 93
@@ -104,7 +104,7 @@ async fn run_low() {
104 let ms = end.duration_since(start).as_ticks() / 33; 104 let ms = end.duration_since(start).as_ticks() / 33;
105 info!("[low] done in {} ms", ms); 105 info!("[low] done in {} ms", ms);
106 106
107 Timer::after(Duration::from_ticks(32983)).await; 107 Timer::after_ticks(32983).await;
108 } 108 }
109} 109}
110 110
diff --git a/examples/nrf52840/src/bin/mutex.rs b/examples/nrf52840/src/bin/mutex.rs
index c402c6ba1..11b47d991 100644
--- a/examples/nrf52840/src/bin/mutex.rs
+++ b/examples/nrf52840/src/bin/mutex.rs
@@ -6,7 +6,7 @@ use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
8use embassy_sync::mutex::Mutex; 8use embassy_sync::mutex::Mutex;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12static MUTEX: Mutex<ThreadModeRawMutex, u32> = Mutex::new(0); 12static MUTEX: Mutex<ThreadModeRawMutex, u32> = Mutex::new(0);
@@ -20,11 +20,11 @@ async fn my_task() {
20 *m += 1000; 20 *m += 1000;
21 21
22 // Hold the mutex for a long time. 22 // Hold the mutex for a long time.
23 Timer::after(Duration::from_secs(1)).await; 23 Timer::after_secs(1).await;
24 info!("end long operation: count = {}", *m); 24 info!("end long operation: count = {}", *m);
25 } 25 }
26 26
27 Timer::after(Duration::from_secs(1)).await; 27 Timer::after_secs(1).await;
28 } 28 }
29} 29}
30 30
@@ -34,7 +34,7 @@ async fn main(spawner: Spawner) {
34 unwrap!(spawner.spawn(my_task())); 34 unwrap!(spawner.spawn(my_task()));
35 35
36 loop { 36 loop {
37 Timer::after(Duration::from_millis(300)).await; 37 Timer::after_millis(300).await;
38 let mut m = MUTEX.lock().await; 38 let mut m = MUTEX.lock().await;
39 *m += 1; 39 *m += 1;
40 info!("short operation: count = {}", *m); 40 info!("short operation: count = {}", *m);
diff --git a/examples/nrf52840/src/bin/nvmc.rs b/examples/nrf52840/src/bin/nvmc.rs
index 31c6fe4b6..624829863 100644
--- a/examples/nrf52840/src/bin/nvmc.rs
+++ b/examples/nrf52840/src/bin/nvmc.rs
@@ -5,7 +5,7 @@
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::nvmc::Nvmc; 7use embassy_nrf::nvmc::Nvmc;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; 9use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
15 info!("Hello NVMC!"); 15 info!("Hello NVMC!");
16 16
17 // probe-rs run breaks without this, I'm not sure why. 17 // probe-rs run breaks without this, I'm not sure why.
18 Timer::after(Duration::from_secs(1)).await; 18 Timer::after_secs(1).await;
19 19
20 let mut f = Nvmc::new(p.NVMC); 20 let mut f = Nvmc::new(p.NVMC);
21 const ADDR: u32 = 0x80000; 21 const ADDR: u32 = 0x80000;
diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs
index 444b9137f..bff323974 100644
--- a/examples/nrf52840/src/bin/pdm.rs
+++ b/examples/nrf52840/src/bin/pdm.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::pdm::{self, Config, Pdm}; 7use embassy_nrf::pdm::{self, Config, Pdm};
8use embassy_nrf::{bind_interrupts, peripherals}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use fixed::types::I7F1; 10use fixed::types::I7F1;
11use num_integer::Roots; 11use num_integer::Roots;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -28,7 +28,7 @@ async fn main(_p: Spawner) {
28 pdm.start().await; 28 pdm.start().await;
29 29
30 // wait some time till the microphon settled 30 // wait some time till the microphon settled
31 Timer::after(Duration::from_millis(1000)).await; 31 Timer::after_millis(1000).await;
32 32
33 const SAMPLES: usize = 2048; 33 const SAMPLES: usize = 2048;
34 let mut buf = [0i16; SAMPLES]; 34 let mut buf = [0i16; SAMPLES];
@@ -51,7 +51,7 @@ async fn main(_p: Spawner) {
51 info!("samples: {:?}", &buf); 51 info!("samples: {:?}", &buf);
52 52
53 pdm.stop().await; 53 pdm.stop().await;
54 Timer::after(Duration::from_millis(100)).await; 54 Timer::after_millis(100).await;
55 } 55 }
56 } 56 }
57} 57}
diff --git a/examples/nrf52840/src/bin/pubsub.rs b/examples/nrf52840/src/bin/pubsub.rs
index cca60ebc9..17d902227 100644
--- a/examples/nrf52840/src/bin/pubsub.rs
+++ b/examples/nrf52840/src/bin/pubsub.rs
@@ -6,7 +6,7 @@ use defmt::unwrap;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
8use embassy_sync::pubsub::{DynSubscriber, PubSubChannel, Subscriber}; 8use embassy_sync::pubsub::{DynSubscriber, PubSubChannel, Subscriber};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12/// Create the message bus. It has a queue of 4, supports 3 subscribers and 1 publisher 12/// Create the message bus. It has a queue of 4, supports 3 subscribers and 1 publisher
@@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
39 39
40 let mut index = 0; 40 let mut index = 0;
41 loop { 41 loop {
42 Timer::after(Duration::from_millis(500)).await; 42 Timer::after_millis(500).await;
43 43
44 let message = match index % 3 { 44 let message = match index % 3 {
45 0 => Message::A, 45 0 => Message::A,
@@ -81,7 +81,7 @@ async fn fast_logger(mut messages: Subscriber<'static, ThreadModeRawMutex, Messa
81async fn slow_logger(mut messages: DynSubscriber<'static, Message>) { 81async fn slow_logger(mut messages: DynSubscriber<'static, Message>) {
82 loop { 82 loop {
83 // Do some work 83 // Do some work
84 Timer::after(Duration::from_millis(2000)).await; 84 Timer::after_millis(2000).await;
85 85
86 // If the publisher has used the `publish_immediate` function, then we may receive a lag message here 86 // If the publisher has used the `publish_immediate` function, then we may receive a lag message here
87 let message = messages.next_message().await; 87 let message = messages.next_message().await;
@@ -98,7 +98,7 @@ async fn slow_logger(mut messages: DynSubscriber<'static, Message>) {
98async fn slow_logger_pure(mut messages: DynSubscriber<'static, Message>) { 98async fn slow_logger_pure(mut messages: DynSubscriber<'static, Message>) {
99 loop { 99 loop {
100 // Do some work 100 // Do some work
101 Timer::after(Duration::from_millis(2000)).await; 101 Timer::after_millis(2000).await;
102 102
103 // Instead of receiving lags here, we just ignore that and read the next message 103 // Instead of receiving lags here, we just ignore that and read the next message
104 let message = messages.next_message_pure().await; 104 let message = messages.next_message_pure().await;
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs
index 1698c0bc8..9750935c8 100644
--- a/examples/nrf52840/src/bin/pwm.rs
+++ b/examples/nrf52840/src/bin/pwm.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::pwm::{Prescaler, SimplePwm}; 7use embassy_nrf::pwm::{Prescaler, SimplePwm};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='') 11// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='')
@@ -84,6 +84,6 @@ async fn main(_spawner: Spawner) {
84 pwm.set_duty(1, DUTY[(i + 256) % 1024]); 84 pwm.set_duty(1, DUTY[(i + 256) % 1024]);
85 pwm.set_duty(2, DUTY[(i + 512) % 1024]); 85 pwm.set_duty(2, DUTY[(i + 512) % 1024]);
86 pwm.set_duty(3, DUTY[(i + 768) % 1024]); 86 pwm.set_duty(3, DUTY[(i + 768) % 1024]);
87 Timer::after(Duration::from_millis(3)).await; 87 Timer::after_millis(3).await;
88 } 88 }
89} 89}
diff --git a/examples/nrf52840/src/bin/pwm_double_sequence.rs b/examples/nrf52840/src/bin/pwm_double_sequence.rs
index 16e50e909..1bfe6e15a 100644
--- a/examples/nrf52840/src/bin/pwm_double_sequence.rs
+++ b/examples/nrf52840/src/bin/pwm_double_sequence.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_nrf::pwm::{ 7use embassy_nrf::pwm::{
8 Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequencer, StartSequence, 8 Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequencer, StartSequence,
9}; 9};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
@@ -36,6 +36,6 @@ async fn main(_spawner: Spawner) {
36 // we can abort a sequence if we need to before its complete with pwm.stop() 36 // we can abort a sequence if we need to before its complete with pwm.stop()
37 // or stop is also implicitly called when the pwm peripheral is dropped 37 // or stop is also implicitly called when the pwm peripheral is dropped
38 // when it goes out of scope 38 // when it goes out of scope
39 Timer::after(Duration::from_millis(40000)).await; 39 Timer::after_millis(40000).await;
40 info!("pwm stopped early!"); 40 info!("pwm stopped early!");
41} 41}
diff --git a/examples/nrf52840/src/bin/pwm_sequence.rs b/examples/nrf52840/src/bin/pwm_sequence.rs
index b9aca9aaa..f282cf910 100644
--- a/examples/nrf52840/src/bin/pwm_sequence.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; 7use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // we can abort a sequence if we need to before its complete with pwm.stop() 31 // we can abort a sequence if we need to before its complete with pwm.stop()
32 // or stop is also implicitly called when the pwm peripheral is dropped 32 // or stop is also implicitly called when the pwm peripheral is dropped
33 // when it goes out of scope 33 // when it goes out of scope
34 Timer::after(Duration::from_millis(20000)).await; 34 Timer::after_millis(20000).await;
35 info!("pwm stopped early!"); 35 info!("pwm stopped early!");
36} 36}
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
index 711c8a17b..8596e6545 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ws2812b.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_nrf::pwm::{ 7use embassy_nrf::pwm::{
8 Config, Prescaler, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, SingleSequencer, 8 Config, Prescaler, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, SingleSequencer,
9}; 9};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13// WS2812B LED light demonstration. Drives just one light. 13// WS2812B LED light demonstration. Drives just one light.
@@ -52,7 +52,7 @@ async fn main(_spawner: Spawner) {
52 let sequences = SingleSequencer::new(&mut pwm, &seq_words, seq_config.clone()); 52 let sequences = SingleSequencer::new(&mut pwm, &seq_words, seq_config.clone());
53 unwrap!(sequences.start(SingleSequenceMode::Times(1))); 53 unwrap!(sequences.start(SingleSequenceMode::Times(1)));
54 54
55 Timer::after(Duration::from_millis(50)).await; 55 Timer::after_millis(50).await;
56 56
57 if bit_value == T0H { 57 if bit_value == T0H {
58 if color_bit == 20 { 58 if color_bit == 20 {
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs
index 19228f433..92ded1f88 100644
--- a/examples/nrf52840/src/bin/pwm_servo.rs
+++ b/examples/nrf52840/src/bin/pwm_servo.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::pwm::{Prescaler, SimplePwm}; 7use embassy_nrf::pwm::{Prescaler, SimplePwm};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -19,29 +19,29 @@ async fn main(_spawner: Spawner) {
19 pwm.set_max_duty(2500); 19 pwm.set_max_duty(2500);
20 info!("pwm initialized!"); 20 info!("pwm initialized!");
21 21
22 Timer::after(Duration::from_millis(5000)).await; 22 Timer::after_millis(5000).await;
23 23
24 // 1ms 0deg (1/.008=125), 1.5ms 90deg (1.5/.008=187.5), 2ms 180deg (2/.008=250), 24 // 1ms 0deg (1/.008=125), 1.5ms 90deg (1.5/.008=187.5), 2ms 180deg (2/.008=250),
25 loop { 25 loop {
26 info!("45 deg"); 26 info!("45 deg");
27 // poor mans inverting, subtract our value from max_duty 27 // poor mans inverting, subtract our value from max_duty
28 pwm.set_duty(0, 2500 - 156); 28 pwm.set_duty(0, 2500 - 156);
29 Timer::after(Duration::from_millis(5000)).await; 29 Timer::after_millis(5000).await;
30 30
31 info!("90 deg"); 31 info!("90 deg");
32 pwm.set_duty(0, 2500 - 187); 32 pwm.set_duty(0, 2500 - 187);
33 Timer::after(Duration::from_millis(5000)).await; 33 Timer::after_millis(5000).await;
34 34
35 info!("135 deg"); 35 info!("135 deg");
36 pwm.set_duty(0, 2500 - 218); 36 pwm.set_duty(0, 2500 - 218);
37 Timer::after(Duration::from_millis(5000)).await; 37 Timer::after_millis(5000).await;
38 38
39 info!("180 deg"); 39 info!("180 deg");
40 pwm.set_duty(0, 2500 - 250); 40 pwm.set_duty(0, 2500 - 250);
41 Timer::after(Duration::from_millis(5000)).await; 41 Timer::after_millis(5000).await;
42 42
43 info!("0 deg"); 43 info!("0 deg");
44 pwm.set_duty(0, 2500 - 125); 44 pwm.set_duty(0, 2500 - 125);
45 Timer::after(Duration::from_millis(5000)).await; 45 Timer::after_millis(5000).await;
46 } 46 }
47} 47}
diff --git a/examples/nrf52840/src/bin/qspi_lowpower.rs b/examples/nrf52840/src/bin/qspi_lowpower.rs
index 22a5c0c6d..42b5454e0 100644
--- a/examples/nrf52840/src/bin/qspi_lowpower.rs
+++ b/examples/nrf52840/src/bin/qspi_lowpower.rs
@@ -8,7 +8,7 @@ use defmt::{info, unwrap};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::qspi::Frequency; 9use embassy_nrf::qspi::Frequency;
10use embassy_nrf::{bind_interrupts, peripherals, qspi}; 10use embassy_nrf::{bind_interrupts, peripherals, qspi};
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14// Workaround for alignment requirements. 14// Workaround for alignment requirements.
@@ -79,6 +79,6 @@ async fn main(_p: Spawner) {
79 79
80 // Sleep for 1 second. The executor ensures the core sleeps with a WFE when it has nothing to do. 80 // Sleep for 1 second. The executor ensures the core sleeps with a WFE when it has nothing to do.
81 // During this sleep, the nRF chip should only use ~3uA 81 // During this sleep, the nRF chip should only use ~3uA
82 Timer::after(Duration::from_secs(1)).await; 82 Timer::after_secs(1).await;
83 } 83 }
84} 84}
diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs
index 1b067f5e4..717b0faa6 100644
--- a/examples/nrf52840/src/bin/raw_spawn.rs
+++ b/examples/nrf52840/src/bin/raw_spawn.rs
@@ -7,21 +7,21 @@ use cortex_m_rt::entry;
7use defmt::{info, unwrap}; 7use defmt::{info, unwrap};
8use embassy_executor::raw::TaskStorage; 8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14async fn run1() { 14async fn run1() {
15 loop { 15 loop {
16 info!("BIG INFREQUENT TICK"); 16 info!("BIG INFREQUENT TICK");
17 Timer::after(Duration::from_ticks(64000)).await; 17 Timer::after_ticks(64000).await;
18 } 18 }
19} 19}
20 20
21async fn run2() { 21async fn run2() {
22 loop { 22 loop {
23 info!("tick"); 23 info!("tick");
24 Timer::after(Duration::from_ticks(13000)).await; 24 Timer::after_ticks(13000).await;
25 } 25 }
26} 26}
27 27
diff --git a/examples/nrf52840/src/bin/saadc.rs b/examples/nrf52840/src/bin/saadc.rs
index ffd9a7f4b..d651834f5 100644
--- a/examples/nrf52840/src/bin/saadc.rs
+++ b/examples/nrf52840/src/bin/saadc.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::saadc::{ChannelConfig, Config, Saadc}; 7use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
8use embassy_nrf::{bind_interrupts, saadc}; 8use embassy_nrf::{bind_interrupts, saadc};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -24,6 +24,6 @@ async fn main(_p: Spawner) {
24 let mut buf = [0; 1]; 24 let mut buf = [0; 1];
25 saadc.sample(&mut buf).await; 25 saadc.sample(&mut buf).await;
26 info!("sample: {=i16}", &buf[0]); 26 info!("sample: {=i16}", &buf[0]);
27 Timer::after(Duration::from_millis(100)).await; 27 Timer::after_millis(100).await;
28 } 28 }
29} 29}
diff --git a/examples/nrf52840/src/bin/saadc_continuous.rs b/examples/nrf52840/src/bin/saadc_continuous.rs
index a25e17465..a5f8a4dd7 100644
--- a/examples/nrf52840/src/bin/saadc_continuous.rs
+++ b/examples/nrf52840/src/bin/saadc_continuous.rs
@@ -7,7 +7,6 @@ use embassy_executor::Spawner;
7use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc}; 7use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc};
8use embassy_nrf::timer::Frequency; 8use embassy_nrf::timer::Frequency;
9use embassy_nrf::{bind_interrupts, saadc}; 9use embassy_nrf::{bind_interrupts, saadc};
10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
13// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer 12// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer
@@ -32,7 +31,7 @@ async fn main(_p: Spawner) {
32 31
33 // This delay demonstrates that starting the timer prior to running 32 // This delay demonstrates that starting the timer prior to running
34 // the task sampler is benign given the calibration that follows. 33 // the task sampler is benign given the calibration that follows.
35 embassy_time::Timer::after(Duration::from_millis(500)).await; 34 embassy_time::Timer::after_millis(500).await;
36 saadc.calibrate().await; 35 saadc.calibrate().await;
37 36
38 let mut bufs = [[[0; 3]; 500]; 2]; 37 let mut bufs = [[[0; 3]; 500]; 2];
diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs
index 31ea6c81e..8a58396a4 100644
--- a/examples/nrf52840/src/bin/self_spawn.rs
+++ b/examples/nrf52840/src/bin/self_spawn.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10mod config { 10mod config {
@@ -13,7 +13,7 @@ mod config {
13 13
14#[embassy_executor::task(pool_size = config::MY_TASK_POOL_SIZE)] 14#[embassy_executor::task(pool_size = config::MY_TASK_POOL_SIZE)]
15async fn my_task(spawner: Spawner, n: u32) { 15async fn my_task(spawner: Spawner, n: u32) {
16 Timer::after(Duration::from_secs(1)).await; 16 Timer::after_secs(1).await;
17 info!("Spawning self! {}", n); 17 info!("Spawning self! {}", n);
18 unwrap!(spawner.spawn(my_task(spawner, n + 1))); 18 unwrap!(spawner.spawn(my_task(spawner, n + 1)));
19} 19}
diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
index 8a179886c..65d50f8c3 100644
--- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs
+++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
@@ -4,12 +4,12 @@
4 4
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::task(pool_size = 2)] 10#[embassy_executor::task(pool_size = 2)]
11async fn my_task(n: u32) { 11async fn my_task(n: u32) {
12 Timer::after(Duration::from_secs(1)).await; 12 Timer::after_secs(1).await;
13 info!("Spawning self! {}", n); 13 info!("Spawning self! {}", n);
14 unwrap!(Spawner::for_current_executor().await.spawn(my_task(n + 1))); 14 unwrap!(Spawner::for_current_executor().await.spawn(my_task(n + 1)));
15} 15}
diff --git a/examples/nrf52840/src/bin/temp.rs b/examples/nrf52840/src/bin/temp.rs
index 70957548f..d94dea38d 100644
--- a/examples/nrf52840/src/bin/temp.rs
+++ b/examples/nrf52840/src/bin/temp.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::temp::Temp; 7use embassy_nrf::temp::Temp;
8use embassy_nrf::{bind_interrupts, temp}; 8use embassy_nrf::{bind_interrupts, temp};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -21,6 +21,6 @@ async fn main(_spawner: Spawner) {
21 loop { 21 loop {
22 let value = temp.read().await; 22 let value = temp.read().await;
23 info!("temperature: {}℃", value.to_num::<u16>()); 23 info!("temperature: {}℃", value.to_num::<u16>());
24 Timer::after(Duration::from_secs(1)).await; 24 Timer::after_secs(1).await;
25 } 25 }
26} 26}
diff --git a/examples/nrf52840/src/bin/timer.rs b/examples/nrf52840/src/bin/timer.rs
index c22b5acd5..9b9bb3eb4 100644
--- a/examples/nrf52840/src/bin/timer.rs
+++ b/examples/nrf52840/src/bin/timer.rs
@@ -4,14 +4,14 @@
4 4
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::task] 10#[embassy_executor::task]
11async fn run1() { 11async fn run1() {
12 loop { 12 loop {
13 info!("BIG INFREQUENT TICK"); 13 info!("BIG INFREQUENT TICK");
14 Timer::after(Duration::from_ticks(64000)).await; 14 Timer::after_ticks(64000).await;
15 } 15 }
16} 16}
17 17
@@ -19,7 +19,7 @@ async fn run1() {
19async fn run2() { 19async fn run2() {
20 loop { 20 loop {
21 info!("tick"); 21 info!("tick");
22 Timer::after(Duration::from_ticks(13000)).await; 22 Timer::after_ticks(13000).await;
23 } 23 }
24} 24}
25 25
diff --git a/examples/nrf52840/src/bin/twim_lowpower.rs b/examples/nrf52840/src/bin/twim_lowpower.rs
index 0970d3c3c..bf9f966ef 100644
--- a/examples/nrf52840/src/bin/twim_lowpower.rs
+++ b/examples/nrf52840/src/bin/twim_lowpower.rs
@@ -14,7 +14,7 @@ use defmt::*;
14use embassy_executor::Spawner; 14use embassy_executor::Spawner;
15use embassy_nrf::twim::{self, Twim}; 15use embassy_nrf::twim::{self, Twim};
16use embassy_nrf::{bind_interrupts, peripherals}; 16use embassy_nrf::{bind_interrupts, peripherals};
17use embassy_time::{Duration, Timer}; 17use embassy_time::Timer;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20const ADDRESS: u8 = 0x50; 20const ADDRESS: u8 = 0x50;
@@ -48,6 +48,6 @@ async fn main(_p: Spawner) {
48 48
49 // Sleep for 1 second. The executor ensures the core sleeps with a WFE when it has nothing to do. 49 // Sleep for 1 second. The executor ensures the core sleeps with a WFE when it has nothing to do.
50 // During this sleep, the nRF chip should only use ~3uA 50 // During this sleep, the nRF chip should only use ~3uA
51 Timer::after(Duration::from_secs(1)).await; 51 Timer::after_secs(1).await;
52 } 52 }
53} 53}
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index edf634a5e..96fcf8a66 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -10,7 +10,7 @@ use embassy_futures::join::join;
10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect; 10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
11use embassy_nrf::usb::Driver; 11use embassy_nrf::usb::Driver;
12use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 12use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
15use embassy_usb::control::OutResponse; 15use embassy_usb::control::OutResponse;
16use embassy_usb::{Builder, Config}; 16use embassy_usb::{Builder, Config};
@@ -83,7 +83,7 @@ async fn main(_spawner: Spawner) {
83 let hid_fut = async { 83 let hid_fut = async {
84 let mut y: i8 = 5; 84 let mut y: i8 = 5;
85 loop { 85 loop {
86 Timer::after(Duration::from_millis(500)).await; 86 Timer::after_millis(500).await;
87 87
88 y = -y; 88 y = -y;
89 let report = MouseReport { 89 let report = MouseReport {
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index 86d969ed5..24972a4fb 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -14,7 +14,7 @@ embassy-executor = { version = "0.3.0", path = "../../embassy-executor", feature
14 "defmt", 14 "defmt",
15 "integrated-timers", 15 "integrated-timers",
16] } 16] }
17embassy-time = { version = "0.1.3", path = "../../embassy-time", features = [ 17embassy-time = { version = "0.1.5", path = "../../embassy-time", features = [
18 "defmt", 18 "defmt",
19 "defmt-timestamp-uptime", 19 "defmt-timestamp-uptime",
20] } 20] }
@@ -27,7 +27,7 @@ embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = [
27 "gpiote", 27 "gpiote",
28 "unstable-pac", 28 "unstable-pac",
29] } 29] }
30embassy-net = { version = "0.1.0", path = "../../embassy-net", features = [ 30embassy-net = { version = "0.2.0", path = "../../embassy-net", features = [
31 "nightly", 31 "nightly",
32 "defmt", 32 "defmt",
33 "tcp", 33 "tcp",
@@ -37,7 +37,7 @@ embassy-net = { version = "0.1.0", path = "../../embassy-net", features = [
37embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = [ 37embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = [
38 "defmt", 38 "defmt",
39] } 39] }
40embedded-io-async = { version = "0.5.0" } 40embedded-io-async = { version = "0.6.0" }
41 41
42defmt = "0.3" 42defmt = "0.3"
43defmt-rtt = "0.4" 43defmt-rtt = "0.4"
diff --git a/examples/nrf5340/src/bin/blinky.rs b/examples/nrf5340/src/bin/blinky.rs
index 3422cedf0..b784564a5 100644
--- a/examples/nrf5340/src/bin/blinky.rs
+++ b/examples/nrf5340/src/bin/blinky.rs
@@ -4,7 +4,7 @@
4 4
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive}; 6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
@@ -14,8 +14,8 @@ async fn main(_spawner: Spawner) {
14 14
15 loop { 15 loop {
16 led.set_high(); 16 led.set_high();
17 Timer::after(Duration::from_millis(300)).await; 17 Timer::after_millis(300).await;
18 led.set_low(); 18 led.set_low();
19 Timer::after(Duration::from_millis(300)).await; 19 Timer::after_millis(300).await;
20 } 20 }
21} 21}
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 2677e0402..7386eeea7 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -9,10 +9,10 @@ license = "MIT OR Apache-2.0"
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.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "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"] }
15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } 18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" }
@@ -45,7 +45,7 @@ usbd-hid = "0.6.1"
45embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } 45embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
46embedded-hal-async = "1.0.0-rc.1" 46embedded-hal-async = "1.0.0-rc.1"
47embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] } 47embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }
48embedded-io-async = { version = "0.5.0", features = ["defmt-03"] } 48embedded-io-async = { version = "0.6.0", features = ["defmt-03"] }
49embedded-storage = { version = "0.3" } 49embedded-storage = { version = "0.3" }
50static_cell = { version = "1.1", features = ["nightly"]} 50static_cell = { version = "1.1", features = ["nightly"]}
51log = "0.4" 51log = "0.4"
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs
index 02bc493b6..a579be139 100644
--- a/examples/rp/src/bin/adc.rs
+++ b/examples/rp/src/bin/adc.rs
@@ -10,7 +10,7 @@ use embassy_executor::Spawner;
10use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; 10use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler};
11use embassy_rp::bind_interrupts; 11use embassy_rp::bind_interrupts;
12use embassy_rp::gpio::Pull; 12use embassy_rp::gpio::Pull;
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
36 info!("Pin 28 ADC: {}", level); 36 info!("Pin 28 ADC: {}", level);
37 let temp = adc.read(&mut ts).await.unwrap(); 37 let temp = adc.read(&mut ts).await.unwrap();
38 info!("Temp: {} degrees", convert_to_celsius(temp)); 38 info!("Temp: {} degrees", convert_to_celsius(temp));
39 Timer::after(Duration::from_secs(1)).await; 39 Timer::after_secs(1).await;
40 } 40 }
41} 41}
42 42
diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs
index 295b000f3..66c8773fa 100644
--- a/examples/rp/src/bin/blinky.rs
+++ b/examples/rp/src/bin/blinky.rs
@@ -9,7 +9,7 @@
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::gpio; 11use embassy_rp::gpio;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use gpio::{Level, Output}; 13use gpio::{Level, Output};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -21,10 +21,10 @@ async fn main(_spawner: Spawner) {
21 loop { 21 loop {
22 info!("led on!"); 22 info!("led on!");
23 led.set_high(); 23 led.set_high();
24 Timer::after(Duration::from_secs(1)).await; 24 Timer::after_secs(1).await;
25 25
26 info!("led off!"); 26 info!("led off!");
27 led.set_low(); 27 led.set_low();
28 Timer::after(Duration::from_secs(1)).await; 28 Timer::after_secs(1).await;
29 } 29 }
30} 30}
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
index e593acae4..b19362fc1 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
@@ -111,7 +111,7 @@ async fn main(spawner: Spawner) {
111 break; 111 break;
112 } 112 }
113 info!("txd: {}", core::str::from_utf8(msg).unwrap()); 113 info!("txd: {}", core::str::from_utf8(msg).unwrap());
114 Timer::after(Duration::from_secs(1)).await; 114 Timer::after_secs(1).await;
115 } 115 }
116 } 116 }
117} 117}
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs
index 911a657eb..129a8497f 100644
--- a/examples/rp/src/bin/flash.rs
+++ b/examples/rp/src/bin/flash.rs
@@ -8,7 +8,7 @@ use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE}; 9use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE};
10use embassy_rp::peripherals::FLASH; 10use embassy_rp::peripherals::FLASH;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14const ADDR_OFFSET: u32 = 0x100000; 14const ADDR_OFFSET: u32 = 0x100000;
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 // defmt RTT header. Reading that header might touch flash memory, which 23 // defmt RTT header. Reading that header might touch flash memory, which
24 // interferes with flash write operations. 24 // interferes with flash write operations.
25 // https://github.com/knurling-rs/defmt/pull/683 25 // https://github.com/knurling-rs/defmt/pull/683
26 Timer::after(Duration::from_millis(10)).await; 26 Timer::after_millis(10).await;
27 27
28 let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0); 28 let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0);
29 29
diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs
index bf58044d5..98209fe41 100644
--- a/examples/rp/src/bin/gpio_async.rs
+++ b/examples/rp/src/bin/gpio_async.rs
@@ -9,7 +9,7 @@
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::gpio; 11use embassy_rp::gpio;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use gpio::{Input, Level, Output, Pull}; 13use gpio::{Input, Level, Output, Pull};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -36,6 +36,6 @@ async fn main(_spawner: Spawner) {
36 info!("done wait_for_high. Turn off LED"); 36 info!("done wait_for_high. Turn off LED");
37 led.set_low(); 37 led.set_low();
38 38
39 Timer::after(Duration::from_secs(2)).await; 39 Timer::after_secs(2).await;
40 } 40 }
41} 41}
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs
index 0a3b5fa98..896cc15ee 100644
--- a/examples/rp/src/bin/gpout.rs
+++ b/examples/rp/src/bin/gpout.rs
@@ -9,7 +9,7 @@
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::clocks; 11use embassy_rp::clocks;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
@@ -26,13 +26,13 @@ async fn main(_spawner: Spawner) {
26 "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", 26 "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}",
27 gpout3.get_freq() 27 gpout3.get_freq()
28 ); 28 );
29 Timer::after(Duration::from_secs(2)).await; 29 Timer::after_secs(2).await;
30 30
31 gpout3.set_src(clocks::GpoutSrc::Ref); 31 gpout3.set_src(clocks::GpoutSrc::Ref);
32 info!( 32 info!(
33 "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", 33 "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}",
34 gpout3.get_freq() 34 gpout3.get_freq()
35 ); 35 );
36 Timer::after(Duration::from_secs(2)).await; 36 Timer::after_secs(2).await;
37 } 37 }
38} 38}
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs
index 93224bc43..7b53aae72 100644
--- a/examples/rp/src/bin/i2c_async.rs
+++ b/examples/rp/src/bin/i2c_async.rs
@@ -12,7 +12,7 @@ use embassy_executor::Spawner;
12use embassy_rp::bind_interrupts; 12use embassy_rp::bind_interrupts;
13use embassy_rp::i2c::{self, Config, InterruptHandler}; 13use embassy_rp::i2c::{self, Config, InterruptHandler};
14use embassy_rp::peripherals::I2C1; 14use embassy_rp::peripherals::I2C1;
15use embassy_time::{Duration, Timer}; 15use embassy_time::Timer;
16use embedded_hal_async::i2c::I2c; 16use embedded_hal_async::i2c::I2c;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
@@ -106,6 +106,6 @@ async fn main(_spawner: Spawner) {
106 } 106 }
107 } 107 }
108 108
109 Timer::after(Duration::from_millis(100)).await; 109 Timer::after_millis(100).await;
110 } 110 }
111} 111}
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs
index 1c8c2039d..9ddb48d69 100644
--- a/examples/rp/src/bin/i2c_blocking.rs
+++ b/examples/rp/src/bin/i2c_blocking.rs
@@ -10,7 +10,7 @@
10use defmt::*; 10use defmt::*;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_rp::i2c::{self, Config}; 12use embassy_rp::i2c::{self, Config};
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use embedded_hal_1::i2c::I2c; 14use embedded_hal_1::i2c::I2c;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
@@ -70,6 +70,6 @@ async fn main(_spawner: Spawner) {
70 info!("portb = {:02x}", portb[0]); 70 info!("portb = {:02x}", portb[0]);
71 val = !val; 71 val = !val;
72 72
73 Timer::after(Duration::from_secs(1)).await; 73 Timer::after_secs(1).await;
74 } 74 }
75} 75}
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs
index 7de300fb8..151b083a4 100644
--- a/examples/rp/src/bin/i2c_slave.rs
+++ b/examples/rp/src/bin/i2c_slave.rs
@@ -7,7 +7,7 @@ use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_rp::peripherals::{I2C0, I2C1}; 8use embassy_rp::peripherals::{I2C0, I2C1};
9use embassy_rp::{bind_interrupts, i2c, i2c_slave}; 9use embassy_rp::{bind_interrupts, i2c, i2c_slave};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use embedded_hal_async::i2c::I2c; 11use embedded_hal_async::i2c::I2c;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -81,7 +81,7 @@ async fn controller_task(mut con: i2c::I2c<'static, I2C0, i2c::Async>) {
81 Err(e) => error!("Error writing {}", e), 81 Err(e) => error!("Error writing {}", e),
82 } 82 }
83 83
84 Timer::after(Duration::from_millis(100)).await; 84 Timer::after_millis(100).await;
85 } 85 }
86 match con.read(DEV_ADDR, &mut resp_buff).await { 86 match con.read(DEV_ADDR, &mut resp_buff).await {
87 Ok(_) => info!("read response: {}", resp_buff), 87 Ok(_) => info!("read response: {}", resp_buff),
@@ -91,7 +91,7 @@ async fn controller_task(mut con: i2c::I2c<'static, I2C0, i2c::Async>) {
91 Ok(_) => info!("write_read response: {}", resp_buff), 91 Ok(_) => info!("write_read response: {}", resp_buff),
92 Err(e) => error!("Error writing {}", e), 92 Err(e) => error!("Error writing {}", e),
93 } 93 }
94 Timer::after(Duration::from_millis(100)).await; 94 Timer::after_millis(100).await;
95 } 95 }
96} 96}
97 97
diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs
index 5891826fd..d5843fdcd 100644
--- a/examples/rp/src/bin/lora_p2p_receive.rs
+++ b/examples/rp/src/bin/lora_p2p_receive.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant; 11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_rp::gpio::{Input, Level, Output, Pin, Pull}; 12use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
13use embassy_rp::spi::{Config, Spi}; 13use embassy_rp::spi::{Config, Spi};
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
@@ -96,7 +96,7 @@ async fn main(_spawner: Spawner) {
96 { 96 {
97 info!("rx successful"); 97 info!("rx successful");
98 debug_indicator.set_high(); 98 debug_indicator.set_high();
99 Timer::after(Duration::from_secs(5)).await; 99 Timer::after_secs(5).await;
100 debug_indicator.set_low(); 100 debug_indicator.set_low();
101 } else { 101 } else {
102 info!("rx unknown packet"); 102 info!("rx unknown packet");
diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs
index e31aa62a2..ccf44987c 100644
--- a/examples/rp/src/bin/lora_p2p_send_multicore.rs
+++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs
@@ -15,7 +15,7 @@ use embassy_rp::peripherals::SPI1;
15use embassy_rp::spi::{Async, Config, Spi}; 15use embassy_rp::spi::{Async, Config, Spi};
16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
17use embassy_sync::channel::Channel; 17use embassy_sync::channel::Channel;
18use embassy_time::{Delay, Duration, Timer}; 18use embassy_time::{Delay, Timer};
19use lora_phy::mod_params::*; 19use lora_phy::mod_params::*;
20use lora_phy::sx1261_2::SX1261_2; 20use lora_phy::sx1261_2::SX1261_2;
21use lora_phy::LoRa; 21use lora_phy::LoRa;
@@ -59,7 +59,7 @@ async fn core0_task() {
59 info!("Hello from core 0"); 59 info!("Hello from core 0");
60 loop { 60 loop {
61 CHANNEL.send([0x01u8, 0x02u8, 0x03u8]).await; 61 CHANNEL.send([0x01u8, 0x02u8, 0x03u8]).await;
62 Timer::after(Duration::from_millis(60 * 1000)).await; 62 Timer::after_millis(60 * 1000).await;
63 } 63 }
64} 64}
65 65
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index bf017f6a7..43eaf8b0a 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -13,7 +13,7 @@ use embassy_rp::multicore::{spawn_core1, Stack};
13use embassy_rp::peripherals::PIN_25; 13use embassy_rp::peripherals::PIN_25;
14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15use embassy_sync::channel::Channel; 15use embassy_sync::channel::Channel;
16use embassy_time::{Duration, Timer}; 16use embassy_time::Timer;
17use static_cell::StaticCell; 17use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
@@ -46,9 +46,9 @@ async fn core0_task() {
46 info!("Hello from core 0"); 46 info!("Hello from core 0");
47 loop { 47 loop {
48 CHANNEL.send(LedState::On).await; 48 CHANNEL.send(LedState::On).await;
49 Timer::after(Duration::from_millis(100)).await; 49 Timer::after_millis(100).await;
50 CHANNEL.send(LedState::Off).await; 50 CHANNEL.send(LedState::Off).await;
51 Timer::after(Duration::from_millis(400)).await; 51 Timer::after_millis(400).await;
52 } 52 }
53} 53}
54 54
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs
index 9ace4cd68..28f621437 100644
--- a/examples/rp/src/bin/multiprio.rs
+++ b/examples/rp/src/bin/multiprio.rs
@@ -62,7 +62,7 @@ use defmt::{info, unwrap};
62use embassy_executor::{Executor, InterruptExecutor}; 62use embassy_executor::{Executor, InterruptExecutor};
63use embassy_rp::interrupt; 63use embassy_rp::interrupt;
64use embassy_rp::interrupt::{InterruptExt, Priority}; 64use embassy_rp::interrupt::{InterruptExt, Priority};
65use embassy_time::{Duration, Instant, Timer, TICK_HZ}; 65use embassy_time::{Instant, Timer, TICK_HZ};
66use static_cell::StaticCell; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
@@ -70,7 +70,7 @@ use {defmt_rtt as _, panic_probe as _};
70async fn run_high() { 70async fn run_high() {
71 loop { 71 loop {
72 info!(" [high] tick!"); 72 info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(673740)).await; 73 Timer::after_ticks(673740).await;
74 } 74 }
75} 75}
76 76
@@ -87,7 +87,7 @@ async fn run_med() {
87 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; 87 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ;
88 info!(" [med] done in {} ms", ms); 88 info!(" [med] done in {} ms", ms);
89 89
90 Timer::after(Duration::from_ticks(53421)).await; 90 Timer::after_ticks(53421).await;
91 } 91 }
92} 92}
93 93
@@ -104,7 +104,7 @@ async fn run_low() {
104 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; 104 let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ;
105 info!("[low] done in {} ms", ms); 105 info!("[low] done in {} ms", ms);
106 106
107 Timer::after(Duration::from_ticks(82983)).await; 107 Timer::after_ticks(82983).await;
108 } 108 }
109} 109}
110 110
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index d80c5c24b..5e5a6f9a3 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -15,7 +15,7 @@ use embassy_rp::pio::{
15}; 15};
16use embassy_rp::pwm::{self, Pwm}; 16use embassy_rp::pwm::{self, Pwm};
17use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; 17use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef};
18use embassy_time::{Duration, Instant, Timer}; 18use embassy_time::{Instant, Timer};
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20 20
21bind_interrupts!(pub struct Irqs { 21bind_interrupts!(pub struct Irqs {
@@ -66,7 +66,7 @@ async fn main(_spawner: Spawner) {
66 let mut buf = Buf([0; 16], 0); 66 let mut buf = Buf([0; 16], 0);
67 write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap(); 67 write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap();
68 hd.add_line(&buf.0[0..buf.1]).await; 68 hd.add_line(&buf.0[0..buf.1]).await;
69 Timer::after(Duration::from_secs(1)).await; 69 Timer::after_secs(1).await;
70 } 70 }
71} 71}
72 72
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs
index 5c0c60246..7b3259538 100644
--- a/examples/rp/src/bin/pio_ws2812.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -13,7 +13,7 @@ use embassy_rp::pio::{
13 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, 13 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
14}; 14};
15use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; 15use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef};
16use embassy_time::{Duration, Timer}; 16use embassy_time::Timer;
17use fixed::types::U24F8; 17use fixed::types::U24F8;
18use fixed_macro::fixed; 18use fixed_macro::fixed;
19use smart_leds::RGB8; 19use smart_leds::RGB8;
@@ -153,7 +153,7 @@ async fn main(_spawner: Spawner) {
153 } 153 }
154 ws2812.write(&data).await; 154 ws2812.write(&data).await;
155 155
156 Timer::after(Duration::from_millis(10)).await; 156 Timer::after_millis(10).await;
157 } 157 }
158 } 158 }
159} 159}
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs
index 9d919287c..a99e88003 100644
--- a/examples/rp/src/bin/pwm.rs
+++ b/examples/rp/src/bin/pwm.rs
@@ -9,7 +9,7 @@
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::pwm::{Config, Pwm}; 11use embassy_rp::pwm::{Config, Pwm};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 23
24 loop { 24 loop {
25 info!("current LED duty cycle: {}/32768", c.compare_b); 25 info!("current LED duty cycle: {}/32768", c.compare_b);
26 Timer::after(Duration::from_secs(1)).await; 26 Timer::after_secs(1).await;
27 c.compare_b = c.compare_b.rotate_left(4); 27 c.compare_b = c.compare_b.rotate_left(4);
28 pwm.set_config(&c); 28 pwm.set_config(&c);
29 } 29 }
diff --git a/examples/rp/src/bin/rosc.rs b/examples/rp/src/bin/rosc.rs
new file mode 100644
index 000000000..f841043b6
--- /dev/null
+++ b/examples/rp/src/bin/rosc.rs
@@ -0,0 +1,32 @@
1//! This example test the RP Pico on board LED.
2//!
3//! It does not work with the RP Pico W board. See wifi_blinky.rs.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_rp::{clocks, gpio};
12use embassy_time::Timer;
13use gpio::{Level, Output};
14use {defmt_rtt as _, panic_probe as _};
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut config = embassy_rp::config::Config::default();
19 config.clocks = clocks::ClockConfig::rosc();
20 let p = embassy_rp::init(config);
21 let mut led = Output::new(p.PIN_25, Level::Low);
22
23 loop {
24 info!("led on!");
25 led.set_high();
26 Timer::after_secs(1).await;
27
28 info!("led off!");
29 led.set_low();
30 Timer::after_secs(1).await;
31 }
32}
diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs
index 15aa8243f..667876db5 100644
--- a/examples/rp/src/bin/rtc.rs
+++ b/examples/rp/src/bin/rtc.rs
@@ -7,7 +7,7 @@
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; 9use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
@@ -31,7 +31,7 @@ async fn main(_spawner: Spawner) {
31 rtc.set_datetime(now).unwrap(); 31 rtc.set_datetime(now).unwrap();
32 } 32 }
33 33
34 Timer::after(Duration::from_millis(20000)).await; 34 Timer::after_millis(20000).await;
35 35
36 if let Ok(dt) = rtc.now() { 36 if let Ok(dt) = rtc.now() {
37 info!( 37 info!(
@@ -41,6 +41,6 @@ async fn main(_spawner: Spawner) {
41 } 41 }
42 42
43 info!("Reboot."); 43 info!("Reboot.");
44 Timer::after(Duration::from_millis(200)).await; 44 Timer::after_millis(200).await;
45 cortex_m::peripheral::SCB::sys_reset(); 45 cortex_m::peripheral::SCB::sys_reset();
46} 46}
diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs
index 328074e8b..f5a2d334e 100644
--- a/examples/rp/src/bin/spi_async.rs
+++ b/examples/rp/src/bin/spi_async.rs
@@ -8,7 +8,7 @@
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::spi::{Config, Spi}; 10use embassy_rp::spi::{Config, Spi};
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
@@ -27,6 +27,6 @@ async fn main(_spawner: Spawner) {
27 let mut rx_buf = [0_u8; 6]; 27 let mut rx_buf = [0_u8; 6];
28 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); 28 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
29 info!("{:?}", rx_buf); 29 info!("{:?}", rx_buf);
30 Timer::after(Duration::from_secs(1)).await; 30 Timer::after_secs(1).await;
31 } 31 }
32} 32}
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs
index d3e67c8ed..14e8810a4 100644
--- a/examples/rp/src/bin/uart_buffered_split.rs
+++ b/examples/rp/src/bin/uart_buffered_split.rs
@@ -13,7 +13,7 @@ use embassy_executor::Spawner;
13use embassy_rp::bind_interrupts; 13use embassy_rp::bind_interrupts;
14use embassy_rp::peripherals::UART0; 14use embassy_rp::peripherals::UART0;
15use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; 15use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config};
16use embassy_time::{Duration, Timer}; 16use embassy_time::Timer;
17use embedded_io_async::{Read, Write}; 17use embedded_io_async::{Read, Write};
18use static_cell::make_static; 18use static_cell::make_static;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
@@ -42,7 +42,7 @@ async fn main(spawner: Spawner) {
42 ]; 42 ];
43 info!("TX {:?}", data); 43 info!("TX {:?}", data);
44 tx.write_all(&data).await.unwrap(); 44 tx.write_all(&data).await.unwrap();
45 Timer::after(Duration::from_secs(1)).await; 45 Timer::after_secs(1).await;
46 } 46 }
47} 47}
48 48
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index c1515a911..42c8b432e 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -14,7 +14,7 @@ use embassy_executor::Spawner;
14use embassy_rp::bind_interrupts; 14use embassy_rp::bind_interrupts;
15use embassy_rp::peripherals::UART1; 15use embassy_rp::peripherals::UART1;
16use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx}; 16use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx};
17use embassy_time::{Duration, Timer}; 17use embassy_time::Timer;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
@@ -35,7 +35,7 @@ async fn main(spawner: Spawner) {
35 let data = [1u8, 2, 3, 4, 5, 6, 7, 8]; 35 let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
36 info!("TX {:?}", data); 36 info!("TX {:?}", data);
37 uart_tx.write(&data).await.unwrap(); 37 uart_tx.write(&data).await.unwrap();
38 Timer::after(Duration::from_secs(1)).await; 38 Timer::after_secs(1).await;
39 } 39 }
40} 40}
41 41
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index 99af1f02f..cc2090d22 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -78,6 +78,9 @@ async fn main(_spawner: Spawner) {
78 // Set up the signal pin that will be used to trigger the keyboard. 78 // Set up the signal pin that will be used to trigger the keyboard.
79 let mut signal_pin = Input::new(p.PIN_16, Pull::None); 79 let mut signal_pin = Input::new(p.PIN_16, Pull::None);
80 80
81 // Enable the schmitt trigger to slightly debounce.
82 signal_pin.set_schmitt(true);
83
81 let (reader, mut writer) = hid.split(); 84 let (reader, mut writer) = hid.split();
82 85
83 // Do stuff with the class! 86 // Do stuff with the class!
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs
index 9c5e6897d..791f15e56 100644
--- a/examples/rp/src/bin/usb_logger.rs
+++ b/examples/rp/src/bin/usb_logger.rs
@@ -10,7 +10,7 @@ use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts; 10use embassy_rp::bind_interrupts;
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver, InterruptHandler}; 12use embassy_rp::usb::{Driver, InterruptHandler};
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
@@ -32,6 +32,6 @@ async fn main(spawner: Spawner) {
32 loop { 32 loop {
33 counter += 1; 33 counter += 1;
34 log::info!("Tick {}", counter); 34 log::info!("Tick {}", counter);
35 Timer::after(Duration::from_secs(1)).await; 35 Timer::after_secs(1).await;
36 } 36 }
37} 37}
diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs
new file mode 100644
index 000000000..f0b03c81b
--- /dev/null
+++ b/examples/rp/src/bin/usb_midi.rs
@@ -0,0 +1,110 @@
1//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip.
2//!
3//! This creates a USB MIDI device that echoes MIDI messages back to the host.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use defmt::{info, panic};
10use embassy_executor::Spawner;
11use embassy_futures::join::join;
12use embassy_rp::bind_interrupts;
13use embassy_rp::peripherals::USB;
14use embassy_rp::usb::{Driver, Instance, InterruptHandler};
15use embassy_usb::class::midi::MidiClass;
16use embassy_usb::driver::EndpointError;
17use embassy_usb::{Builder, Config};
18use {defmt_rtt as _, panic_probe as _};
19
20bind_interrupts!(struct Irqs {
21 USBCTRL_IRQ => InterruptHandler<USB>;
22});
23
24#[embassy_executor::main]
25async fn main(_spawner: Spawner) {
26 info!("Hello world!");
27
28 let p = embassy_rp::init(Default::default());
29
30 // Create the driver, from the HAL.
31 let driver = Driver::new(p.USB, Irqs);
32
33 // Create embassy-usb Config
34 let mut config = Config::new(0xc0de, 0xcafe);
35 config.manufacturer = Some("Embassy");
36 config.product = Some("USB-MIDI example");
37 config.serial_number = Some("12345678");
38 config.max_power = 100;
39 config.max_packet_size_0 = 64;
40
41 // Required for windows compatibility.
42 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
43 config.device_class = 0xEF;
44 config.device_sub_class = 0x02;
45 config.device_protocol = 0x01;
46 config.composite_with_iads = true;
47
48 // Create embassy-usb DeviceBuilder using the driver and config.
49 // It needs some buffers for building the descriptors.
50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 64];
54
55 let mut builder = Builder::new(
56 driver,
57 config,
58 &mut device_descriptor,
59 &mut config_descriptor,
60 &mut bos_descriptor,
61 &mut control_buf,
62 );
63
64 // Create classes on the builder.
65 let mut class = MidiClass::new(&mut builder, 1, 1, 64);
66
67 // The `MidiClass` can be split into `Sender` and `Receiver`, to be used in separate tasks.
68 // let (sender, receiver) = class.split();
69
70 // Build the builder.
71 let mut usb = builder.build();
72
73 // Run the USB device.
74 let usb_fut = usb.run();
75
76 // Use the Midi class!
77 let midi_fut = async {
78 loop {
79 class.wait_connection().await;
80 info!("Connected");
81 let _ = midi_echo(&mut class).await;
82 info!("Disconnected");
83 }
84 };
85
86 // Run everything concurrently.
87 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
88 join(usb_fut, midi_fut).await;
89}
90
91struct Disconnected {}
92
93impl From<EndpointError> for Disconnected {
94 fn from(val: EndpointError) -> Self {
95 match val {
96 EndpointError::BufferOverflow => panic!("Buffer overflow"),
97 EndpointError::Disabled => Disconnected {},
98 }
99 }
100}
101
102async fn midi_echo<'d, T: Instance + 'd>(class: &mut MidiClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
103 let mut buf = [0; 64];
104 loop {
105 let n = class.read_packet(&mut buf).await?;
106 let data = &buf[..n];
107 info!("data: {:x}", data);
108 class.write_packet(data).await?;
109 }
110}
diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs
index fe5eaf926..b6af518af 100644
--- a/examples/rp/src/bin/watchdog.rs
+++ b/examples/rp/src/bin/watchdog.rs
@@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
24 24
25 // Set the LED high for 2 seconds so we know when we're about to start the watchdog 25 // Set the LED high for 2 seconds so we know when we're about to start the watchdog
26 led.set_high(); 26 led.set_high();
27 Timer::after(Duration::from_secs(2)).await; 27 Timer::after_secs(2).await;
28 28
29 // Set to watchdog to reset if it's not fed within 1.05 seconds, and start it 29 // Set to watchdog to reset if it's not fed within 1.05 seconds, and start it
30 watchdog.start(Duration::from_millis(1_050)); 30 watchdog.start(Duration::from_millis(1_050));
@@ -33,9 +33,9 @@ async fn main(_spawner: Spawner) {
33 // Blink once a second for 5 seconds, feed the watchdog timer once a second to avoid a reset 33 // Blink once a second for 5 seconds, feed the watchdog timer once a second to avoid a reset
34 for _ in 1..=5 { 34 for _ in 1..=5 {
35 led.set_low(); 35 led.set_low();
36 Timer::after(Duration::from_millis(500)).await; 36 Timer::after_millis(500).await;
37 led.set_high(); 37 led.set_high();
38 Timer::after(Duration::from_millis(500)).await; 38 Timer::after_millis(500).await;
39 info!("Feeding watchdog"); 39 info!("Feeding watchdog");
40 watchdog.feed(); 40 watchdog.feed();
41 } 41 }
@@ -45,8 +45,8 @@ async fn main(_spawner: Spawner) {
45 // The processor should reset in 1.05 seconds. 45 // The processor should reset in 1.05 seconds.
46 loop { 46 loop {
47 led.set_low(); 47 led.set_low();
48 Timer::after(Duration::from_millis(100)).await; 48 Timer::after_millis(100).await;
49 led.set_high(); 49 led.set_high();
50 Timer::after(Duration::from_millis(100)).await; 50 Timer::after_millis(100).await;
51 } 51 }
52} 52}
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs
index cd61ad789..98cae53f6 100644
--- a/examples/rp/src/bin/wifi_ap_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs
@@ -52,7 +52,7 @@ async fn main(spawner: Spawner) {
52 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: 52 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`:
53 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 53 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
54 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 54 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000
55 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 55 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 230321) };
56 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 56 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) };
57 57
58 let pwr = Output::new(p.PIN_23, Level::Low); 58 let pwr = Output::new(p.PIN_23, Level::Low);
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs
index 33d43788c..14ace74e9 100644
--- a/examples/rp/src/bin/wifi_blinky.rs
+++ b/examples/rp/src/bin/wifi_blinky.rs
@@ -38,7 +38,7 @@ async fn main(spawner: Spawner) {
38 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: 38 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`:
39 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 39 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
40 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 40 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000
41 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 41 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 230321) };
42 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 42 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) };
43 43
44 let pwr = Output::new(p.PIN_23, Level::Low); 44 let pwr = Output::new(p.PIN_23, Level::Low);
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs
index 743fab617..dbbbf6c81 100644
--- a/examples/rp/src/bin/wifi_scan.rs
+++ b/examples/rp/src/bin/wifi_scan.rs
@@ -49,7 +49,7 @@ async fn main(spawner: Spawner) {
49 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: 49 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`:
50 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 50 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
51 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 51 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000
52 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 52 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 230321) };
53 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 53 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) };
54 54
55 let pwr = Output::new(p.PIN_23, Level::Low); 55 let pwr = Output::new(p.PIN_23, Level::Low);
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs
index 55fcb4a6a..c00fff216 100644
--- a/examples/rp/src/bin/wifi_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_tcp_server.rs
@@ -18,7 +18,7 @@ use embassy_rp::bind_interrupts;
18use embassy_rp::gpio::{Level, Output}; 18use embassy_rp::gpio::{Level, Output};
19use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 19use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0};
20use embassy_rp::pio::{InterruptHandler, Pio}; 20use embassy_rp::pio::{InterruptHandler, Pio};
21use embassy_time::Duration; 21use embassy_time::{Duration, Timer};
22use embedded_io_async::Write; 22use embedded_io_async::Write;
23use static_cell::make_static; 23use static_cell::make_static;
24use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
@@ -55,7 +55,7 @@ async fn main(spawner: Spawner) {
55 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: 55 // at hardcoded addresses, instead of baking them into the program with `include_bytes!`:
56 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 56 // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
57 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 57 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000
58 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; 58 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 230321) };
59 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; 59 //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) };
60 60
61 let pwr = Output::new(p.PIN_23, Level::Low); 61 let pwr = Output::new(p.PIN_23, Level::Low);
@@ -102,6 +102,13 @@ async fn main(spawner: Spawner) {
102 } 102 }
103 } 103 }
104 104
105 // Wait for DHCP, not necessary when using static IP
106 info!("waiting for DHCP...");
107 while !stack.is_config_up() {
108 Timer::after_millis(100).await;
109 }
110 info!("DHCP is now up!");
111
105 // And now we can use it! 112 // And now we can use it!
106 113
107 let mut rx_buffer = [0; 4096]; 114 let mut rx_buffer = [0; 4096];
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index e54f36980..a5f4c8713 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -7,12 +7,12 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["log"] } 8embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["log"] }
9embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["log", "std", "nightly"] } 10embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["log", "std", "nightly"] }
11embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } 11embassy-net = { version = "0.2.0", path = "../../embassy-net", features=[ "std", "nightly", "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" }
13embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]} 13embassy-net-ppp = { version = "0.1.0", path = "../../embassy-net-ppp", features = ["log"]}
14embedded-io-async = { version = "0.5.0" } 14embedded-io-async = { version = "0.6.0" }
15embedded-io-adapters = { version = "0.5.0", features = ["futures-03"] } 15embedded-io-adapters = { version = "0.6.0", features = ["futures-03"] }
16critical-section = { version = "1.1", features = ["std"] } 16critical-section = { version = "1.1", features = ["std"] }
17smoltcp = { version = "0.10.0", features = ["dns-max-server-count-4"] } 17smoltcp = { version = "0.10.0", features = ["dns-max-server-count-4"] }
18 18
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs
index 9cf6e19df..9ea07b29a 100644
--- a/examples/std/src/bin/net_ppp.rs
+++ b/examples/std/src/bin/net_ppp.rs
@@ -8,7 +8,7 @@
8//! nc 192.168.7.10 1234 8//! nc 192.168.7.10 1234
9 9
10#![feature(type_alias_impl_trait)] 10#![feature(type_alias_impl_trait)]
11#![feature(async_fn_in_trait, impl_trait_projections)] 11#![feature(async_fn_in_trait)]
12 12
13#[path = "../serial_port.rs"] 13#[path = "../serial_port.rs"]
14mod serial_port; 14mod serial_port;
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
index 199e4c9ec..79fa375cd 100644
--- a/examples/std/src/bin/tcp_accept.rs
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -100,7 +100,7 @@ async fn main_task(spawner: Spawner) {
100 return; 100 return;
101 } 101 }
102 102
103 Timer::after(Duration::from_millis(500)).await; 103 Timer::after_millis(500).await;
104 } 104 }
105 info!("Closing the connection"); 105 info!("Closing the connection");
106 socket.abort(); 106 socket.abort();
diff --git a/examples/std/src/bin/tick.rs b/examples/std/src/bin/tick.rs
index b9de9d873..a3f99067e 100644
--- a/examples/std/src/bin/tick.rs
+++ b/examples/std/src/bin/tick.rs
@@ -1,14 +1,14 @@
1#![feature(type_alias_impl_trait)] 1#![feature(type_alias_impl_trait)]
2 2
3use embassy_executor::Spawner; 3use embassy_executor::Spawner;
4use embassy_time::{Duration, Timer}; 4use embassy_time::Timer;
5use log::*; 5use log::*;
6 6
7#[embassy_executor::task] 7#[embassy_executor::task]
8async fn run() { 8async fn run() {
9 loop { 9 loop {
10 info!("tick"); 10 info!("tick");
11 Timer::after(Duration::from_secs(1)).await; 11 Timer::after_secs(1).await;
12 } 12 }
13} 13}
14 14
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index 89ecc4995..b80ccd302 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
15defmt-rtt = "0.4" 15defmt-rtt = "0.4"
diff --git a/examples/stm32c0/src/bin/blinky.rs b/examples/stm32c0/src/bin/blinky.rs
index 8a65b0692..cbeb0dee1 100644
--- a/examples/stm32c0/src/bin/blinky.rs
+++ b/examples/stm32c0/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index db9a24d73..47a95ec1e 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -16,7 +16,7 @@ defmt-rtt = "0.4"
16panic-probe = "0.3" 16panic-probe = "0.3"
17embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 17embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
18embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 18embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
19embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 19embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
20static_cell = { version = "1.1", features = ["nightly"]} 20static_cell = { version = "1.1", features = ["nightly"]}
21 21
22[profile.release] 22[profile.release]
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs
index 1564ecfc0..96f234402 100644
--- a/examples/stm32f0/src/bin/adc.rs
+++ b/examples/stm32f0/src/bin/adc.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::peripherals::ADC; 8use embassy_stm32::peripherals::ADC;
9use embassy_stm32::{adc, bind_interrupts}; 9use embassy_stm32::{adc, bind_interrupts};
10use embassy_time::{Delay, Duration, Timer}; 10use embassy_time::{Delay, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs { 13bind_interrupts!(struct Irqs {
@@ -36,6 +36,6 @@ async fn main(_spawner: Spawner) {
36 loop { 36 loop {
37 let v = adc.read(&mut pin).await; 37 let v = adc.read(&mut pin).await;
38 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 38 info!("--> {} - {} mV", v, convert_to_millivolts(v));
39 Timer::after(Duration::from_millis(100)).await; 39 Timer::after_millis(100).await;
40 } 40 }
41} 41}
diff --git a/examples/stm32f0/src/bin/blinky.rs b/examples/stm32f0/src/bin/blinky.rs
index 9f923399c..899394546 100644
--- a/examples/stm32f0/src/bin/blinky.rs
+++ b/examples/stm32f0/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11// main is itself an async function. 11// main is itself an async function.
@@ -19,10 +19,10 @@ async fn main(_spawner: Spawner) {
19 loop { 19 loop {
20 info!("high"); 20 info!("high");
21 led.set_high(); 21 led.set_high();
22 Timer::after(Duration::from_millis(300)).await; 22 Timer::after_millis(300).await;
23 23
24 info!("low"); 24 info!("low");
25 led.set_low(); 25 led.set_low();
26 Timer::after(Duration::from_millis(300)).await; 26 Timer::after_millis(300).await;
27 } 27 }
28} 28}
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs
index f362c53f5..306df1752 100644
--- a/examples/stm32f0/src/bin/button_controlled_blink.rs
+++ b/examples/stm32f0/src/bin/button_controlled_blink.rs
@@ -10,7 +10,7 @@ use defmt::info;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::exti::ExtiInput; 11use embassy_stm32::exti::ExtiInput;
12use embassy_stm32::gpio::{AnyPin, Input, Level, Output, Pin, Pull, Speed}; 12use embassy_stm32::gpio::{AnyPin, Input, Level, Output, Pin, Pull, Speed};
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16static BLINK_MS: AtomicU32 = AtomicU32::new(0); 16static BLINK_MS: AtomicU32 = AtomicU32::new(0);
@@ -24,7 +24,7 @@ async fn led_task(led: AnyPin) {
24 loop { 24 loop {
25 let del = BLINK_MS.load(Ordering::Relaxed); 25 let del = BLINK_MS.load(Ordering::Relaxed);
26 info!("Value of del is {}", del); 26 info!("Value of del is {}", del);
27 Timer::after(Duration::from_millis(del.into())).await; 27 Timer::after_millis(del.into()).await;
28 info!("LED toggling"); 28 info!("LED toggling");
29 led.toggle(); 29 led.toggle();
30 } 30 }
diff --git a/examples/stm32f0/src/bin/hello.rs b/examples/stm32f0/src/bin/hello.rs
index db78233ea..0f98d9865 100644
--- a/examples/stm32f0/src/bin/hello.rs
+++ b/examples/stm32f0/src/bin/hello.rs
@@ -4,14 +4,14 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_time::{Duration, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) -> ! { 11async fn main(_spawner: Spawner) -> ! {
12 let _p = embassy_stm32::init(Default::default()); 12 let _p = embassy_stm32::init(Default::default());
13 loop { 13 loop {
14 Timer::after(Duration::from_secs(1)).await; 14 Timer::after_secs(1).await;
15 info!("Hello"); 15 info!("Hello");
16 } 16 }
17} 17}
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs
index 988ffeef1..870c7c45b 100644
--- a/examples/stm32f0/src/bin/multiprio.rs
+++ b/examples/stm32f0/src/bin/multiprio.rs
@@ -62,7 +62,7 @@ use defmt::*;
62use embassy_executor::{Executor, InterruptExecutor}; 62use embassy_executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt; 63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::{InterruptExt, Priority}; 64use embassy_stm32::interrupt::{InterruptExt, Priority};
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Instant, Timer};
66use static_cell::StaticCell; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
@@ -70,7 +70,7 @@ use {defmt_rtt as _, panic_probe as _};
70async fn run_high() { 70async fn run_high() {
71 loop { 71 loop {
72 // info!(" [high] tick!"); 72 // info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(27374)).await; 73 Timer::after_ticks(27374).await;
74 } 74 }
75} 75}
76 76
@@ -87,7 +87,7 @@ async fn run_med() {
87 let ms = end.duration_since(start).as_ticks() / 33; 87 let ms = end.duration_since(start).as_ticks() / 33;
88 info!(" [med] done in {} ms", ms); 88 info!(" [med] done in {} ms", ms);
89 89
90 Timer::after(Duration::from_ticks(23421)).await; 90 Timer::after_ticks(23421).await;
91 } 91 }
92} 92}
93 93
@@ -104,7 +104,7 @@ async fn run_low() {
104 let ms = end.duration_since(start).as_ticks() / 33; 104 let ms = end.duration_since(start).as_ticks() / 33;
105 info!("[low] done in {} ms", ms); 105 info!("[low] done in {} ms", ms);
106 106
107 Timer::after(Duration::from_ticks(32983)).await; 107 Timer::after_ticks(32983).await;
108 } 108 }
109} 109}
110 110
diff --git a/examples/stm32f0/src/bin/wdg.rs b/examples/stm32f0/src/bin/wdg.rs
index a44b17528..b51dee8ee 100644
--- a/examples/stm32f0/src/bin/wdg.rs
+++ b/examples/stm32f0/src/bin/wdg.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::wdg::IndependentWatchdog; 7use embassy_stm32::wdg::IndependentWatchdog;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -19,7 +19,7 @@ async fn main(_spawner: Spawner) {
19 wdg.unleash(); 19 wdg.unleash();
20 20
21 loop { 21 loop {
22 Timer::after(Duration::from_secs(1)).await; 22 Timer::after_secs(1).await;
23 wdg.pet(); 23 wdg.pet();
24 } 24 }
25} 25}
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index b032ba817..34319fbd8 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", 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" }
15 15
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs
index 30947c3c2..1edac3d83 100644
--- a/examples/stm32f1/src/bin/adc.rs
+++ b/examples/stm32f1/src/bin/adc.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_stm32::adc::Adc; 7use embassy_stm32::adc::Adc;
8use embassy_stm32::peripherals::ADC1; 8use embassy_stm32::peripherals::ADC1;
9use embassy_stm32::{adc, bind_interrupts}; 9use embassy_stm32::{adc, bind_interrupts};
10use embassy_time::{Delay, Duration, Timer}; 10use embassy_time::{Delay, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs { 13bind_interrupts!(struct Irqs {
@@ -35,6 +35,6 @@ async fn main(_spawner: Spawner) {
35 loop { 35 loop {
36 let v = adc.read(&mut pin).await; 36 let v = adc.read(&mut pin).await;
37 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 37 info!("--> {} - {} mV", v, convert_to_millivolts(v));
38 Timer::after(Duration::from_millis(100)).await; 38 Timer::after_millis(100).await;
39 } 39 }
40} 40}
diff --git a/examples/stm32f1/src/bin/blinky.rs b/examples/stm32f1/src/bin/blinky.rs
index b9b0ac238..3425b0536 100644
--- a/examples/stm32f1/src/bin/blinky.rs
+++ b/examples/stm32f1/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f1/src/bin/hello.rs b/examples/stm32f1/src/bin/hello.rs
index 180b6aabd..e63bcaae0 100644
--- a/examples/stm32f1/src/bin/hello.rs
+++ b/examples/stm32f1/src/bin/hello.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -17,6 +17,6 @@ async fn main(_spawner: Spawner) -> ! {
17 17
18 loop { 18 loop {
19 info!("Hello World!"); 19 info!("Hello World!");
20 Timer::after(Duration::from_secs(1)).await; 20 Timer::after_secs(1).await;
21 } 21 }
22} 22}
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index 663099ff7..60eb5d0e4 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -9,7 +9,7 @@ use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 11use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
14use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
15use embassy_usb::Builder; 15use embassy_usb::Builder;
@@ -35,7 +35,7 @@ async fn main(_spawner: Spawner) {
35 // This forced reset is needed only for development, without it host 35 // This forced reset is needed only for development, without it host
36 // will not reset your device when you upload new firmware. 36 // will not reset your device when you upload new firmware.
37 let _dp = Output::new(&mut p.PA12, Level::Low, Speed::Low); 37 let _dp = Output::new(&mut p.PA12, Level::Low, Speed::Low);
38 Timer::after(Duration::from_millis(10)).await; 38 Timer::after_millis(10).await;
39 } 39 }
40 40
41 // Create the driver, from the HAL. 41 // Create the driver, from the HAL.
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 1314b6b12..fbf508367 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
15defmt-rtt = "0.4" 15defmt-rtt = "0.4"
diff --git a/examples/stm32f2/src/bin/blinky.rs b/examples/stm32f2/src/bin/blinky.rs
index d8c89a519..f6d7a0005 100644
--- a/examples/stm32f2/src/bin/blinky.rs
+++ b/examples/stm32f2/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(1000)).await; 21 Timer::after_millis(1000).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(1000)).await; 25 Timer::after_millis(1000).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs
index 894937614..56591b527 100644
--- a/examples/stm32f2/src/bin/pll.rs
+++ b/examples/stm32f2/src/bin/pll.rs
@@ -7,11 +7,11 @@ use core::convert::TryFrom;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::rcc::{ 9use embassy_stm32::rcc::{
10 APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLL48Div, PLLConfig, PLLMainDiv, PLLMul, PLLPreDiv, PLLSrc, 10 APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc,
11}; 11};
12use embassy_stm32::time::Hertz; 12use embassy_stm32::time::Hertz;
13use embassy_stm32::Config; 13use embassy_stm32::Config;
14use embassy_time::{Duration, Timer}; 14use embassy_time::Timer;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::main] 17#[embassy_executor::main]
@@ -32,9 +32,9 @@ async fn main(_spawner: Spawner) {
32 // 1 MHz PLL input * 240 = 240 MHz PLL VCO 32 // 1 MHz PLL input * 240 = 240 MHz PLL VCO
33 mul: unwrap!(PLLMul::try_from(240)), 33 mul: unwrap!(PLLMul::try_from(240)),
34 // 240 MHz PLL VCO / 2 = 120 MHz main PLL output 34 // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
35 main_div: PLLMainDiv::Div2, 35 p_div: PLLPDiv::DIV2,
36 // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output 36 // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
37 pll48_div: unwrap!(PLL48Div::try_from(5)), 37 q_div: PLLQDiv::DIV5,
38 }; 38 };
39 // System clock comes from PLL (= the 120 MHz main PLL output) 39 // System clock comes from PLL (= the 120 MHz main PLL output)
40 config.rcc.mux = ClockSrc::PLL; 40 config.rcc.mux = ClockSrc::PLL;
@@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) {
46 let _p = embassy_stm32::init(config); 46 let _p = embassy_stm32::init(config);
47 47
48 loop { 48 loop {
49 Timer::after(Duration::from_millis(1000)).await; 49 Timer::after_millis(1000).await;
50 info!("1s elapsed"); 50 info!("1s elapsed");
51 } 51 }
52} 52}
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 534e783de..b3b2b1233 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", 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" }
15 15
diff --git a/examples/stm32f3/src/bin/blinky.rs b/examples/stm32f3/src/bin/blinky.rs
index 185785ceb..e71031b30 100644
--- a/examples/stm32f3/src/bin/blinky.rs
+++ b/examples/stm32f3/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(1000)).await; 21 Timer::after_millis(1000).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(1000)).await; 25 Timer::after_millis(1000).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index 8e97e85eb..9df6d680d 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -65,11 +65,11 @@ impl<'a> Leds<'a> {
65 for led in &mut self.leds { 65 for led in &mut self.leds {
66 led.set_high(); 66 led.set_high();
67 } 67 }
68 Timer::after(Duration::from_millis(500)).await; 68 Timer::after_millis(500).await;
69 for led in &mut self.leds { 69 for led in &mut self.leds {
70 led.set_low(); 70 led.set_low();
71 } 71 }
72 Timer::after(Duration::from_millis(200)).await; 72 Timer::after_millis(200).await;
73 } 73 }
74 } 74 }
75 75
diff --git a/examples/stm32f3/src/bin/hello.rs b/examples/stm32f3/src/bin/hello.rs
index 65773210d..b3285f3c1 100644
--- a/examples/stm32f3/src/bin/hello.rs
+++ b/examples/stm32f3/src/bin/hello.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -18,6 +18,6 @@ async fn main(_spawner: Spawner) -> ! {
18 18
19 loop { 19 loop {
20 info!("Hello World!"); 20 info!("Hello World!");
21 Timer::after(Duration::from_secs(1)).await; 21 Timer::after_secs(1).await;
22 } 22 }
23} 23}
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index 80bf59deb..74f3bb1c5 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -62,7 +62,7 @@ use defmt::*;
62use embassy_executor::{Executor, InterruptExecutor}; 62use embassy_executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt; 63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::{InterruptExt, Priority}; 64use embassy_stm32::interrupt::{InterruptExt, Priority};
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Instant, Timer};
66use static_cell::StaticCell; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
@@ -70,7 +70,7 @@ use {defmt_rtt as _, panic_probe as _};
70async fn run_high() { 70async fn run_high() {
71 loop { 71 loop {
72 info!(" [high] tick!"); 72 info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(27374)).await; 73 Timer::after_ticks(27374).await;
74 } 74 }
75} 75}
76 76
@@ -87,7 +87,7 @@ async fn run_med() {
87 let ms = end.duration_since(start).as_ticks() / 33; 87 let ms = end.duration_since(start).as_ticks() / 33;
88 info!(" [med] done in {} ms", ms); 88 info!(" [med] done in {} ms", ms);
89 89
90 Timer::after(Duration::from_ticks(23421)).await; 90 Timer::after_ticks(23421).await;
91 } 91 }
92} 92}
93 93
@@ -104,7 +104,7 @@ async fn run_low() {
104 let ms = end.duration_since(start).as_ticks() / 33; 104 let ms = end.duration_since(start).as_ticks() / 33;
105 info!("[low] done in {} ms", ms); 105 info!("[low] done in {} ms", ms);
106 106
107 Timer::after(Duration::from_ticks(32983)).await; 107 Timer::after_ticks(32983).await;
108 } 108 }
109} 109}
110 110
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index f15f333b7..a9537c77b 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -9,7 +9,7 @@ use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::usb::{Driver, Instance}; 10use embassy_stm32::usb::{Driver, Instance};
11use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 11use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
14use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
15use embassy_usb::Builder; 15use embassy_usb::Builder;
@@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) {
33 33
34 // Needed for nucleo-stm32f303ze 34 // Needed for nucleo-stm32f303ze
35 let mut dp_pullup = Output::new(p.PG6, Level::Low, Speed::Medium); 35 let mut dp_pullup = Output::new(p.PG6, Level::Low, Speed::Medium);
36 Timer::after(Duration::from_millis(10)).await; 36 Timer::after_millis(10).await;
37 dp_pullup.set_high(); 37 dp_pullup.set_high();
38 38
39 // Create the driver, from the HAL. 39 // Create the driver, from the HAL.
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index ed246a7db..f259135d2 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -6,10 +6,10 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::peripherals::ADC1; 8use embassy_stm32::peripherals::ADC1;
9use embassy_stm32::rcc::AdcClockSource; 9use embassy_stm32::rcc::{AdcClockSource, Adcpres};
10use embassy_stm32::time::mhz; 10use embassy_stm32::time::mhz;
11use embassy_stm32::{adc, bind_interrupts, Config}; 11use embassy_stm32::{adc, bind_interrupts, Config};
12use embassy_time::{Delay, Duration, Timer}; 12use embassy_time::{Delay, Timer};
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) -> ! {
23 config.rcc.hclk = Some(mhz(64)); 23 config.rcc.hclk = Some(mhz(64));
24 config.rcc.pclk1 = Some(mhz(32)); 24 config.rcc.pclk1 = Some(mhz(32));
25 config.rcc.pclk2 = Some(mhz(64)); 25 config.rcc.pclk2 = Some(mhz(64));
26 config.rcc.adc = Some(AdcClockSource::PllDiv1); 26 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
27 27
28 let mut p = embassy_stm32::init(config); 28 let mut p = embassy_stm32::init(config);
29 29
@@ -51,6 +51,6 @@ async fn main(_spawner: Spawner) -> ! {
51 let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; 51 let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095;
52 info!("computed pin mv: {}", pin_mv); 52 info!("computed pin mv: {}", pin_mv);
53 53
54 Timer::after(Duration::from_millis(500)).await; 54 Timer::after_millis(500).await;
55 } 55 }
56} 56}
diff --git a/examples/stm32f334/src/bin/button.rs b/examples/stm32f334/src/bin/button.rs
index 599c0f27d..501fb080c 100644
--- a/examples/stm32f334/src/bin/button.rs
+++ b/examples/stm32f334/src/bin/button.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -17,10 +17,10 @@ async fn main(_spawner: Spawner) {
17 let mut out1 = Output::new(p.PA8, Level::Low, Speed::High); 17 let mut out1 = Output::new(p.PA8, Level::Low, Speed::High);
18 18
19 out1.set_high(); 19 out1.set_high();
20 Timer::after(Duration::from_millis(500)).await; 20 Timer::after_millis(500).await;
21 out1.set_low(); 21 out1.set_low();
22 22
23 Timer::after(Duration::from_millis(500)).await; 23 Timer::after_millis(500).await;
24 info!("end program"); 24 info!("end program");
25 25
26 cortex_m::asm::bkpt(); 26 cortex_m::asm::bkpt();
diff --git a/examples/stm32f334/src/bin/hello.rs b/examples/stm32f334/src/bin/hello.rs
index 65773210d..b3285f3c1 100644
--- a/examples/stm32f334/src/bin/hello.rs
+++ b/examples/stm32f334/src/bin/hello.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -18,6 +18,6 @@ async fn main(_spawner: Spawner) -> ! {
18 18
19 loop { 19 loop {
20 info!("Hello World!"); 20 info!("Hello World!");
21 Timer::after(Duration::from_secs(1)).await; 21 Timer::after_secs(1).await;
22 } 22 }
23} 23}
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
new file mode 100644
index 000000000..128001bf2
--- /dev/null
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -0,0 +1,59 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::opamp::{OpAmp, OpAmpGain};
9use embassy_stm32::peripherals::ADC2;
10use embassy_stm32::rcc::{AdcClockSource, Adcpres};
11use embassy_stm32::time::mhz;
12use embassy_stm32::{adc, bind_interrupts, Config};
13use embassy_time::{Delay, Timer};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 ADC1_2 => adc::InterruptHandler<ADC2>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let mut config = Config::default();
23 config.rcc.sysclk = Some(mhz(64));
24 config.rcc.hclk = Some(mhz(64));
25 config.rcc.pclk1 = Some(mhz(32));
26 config.rcc.pclk2 = Some(mhz(64));
27 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
28
29 let mut p = embassy_stm32::init(config);
30
31 info!("create adc...");
32
33 let mut adc = Adc::new(p.ADC2, Irqs, &mut Delay);
34 let mut opamp = OpAmp::new(p.OPAMP2);
35
36 adc.set_sample_time(SampleTime::Cycles601_5);
37
38 info!("enable vrefint...");
39
40 let mut vrefint = adc.enable_vref(&mut Delay);
41 let mut temperature = adc.enable_temperature();
42 let mut buffer = opamp.buffer_for(&mut p.PA7, OpAmpGain::Mul1);
43
44 loop {
45 let vref = adc.read(&mut vrefint).await;
46 info!("read vref: {} (should be {})", vref, vrefint.value());
47
48 let temp = adc.read(&mut temperature).await;
49 info!("read temperature: {}", temp);
50
51 let buffer = adc.read(&mut buffer).await;
52 info!("read buffer: {}", buffer);
53
54 let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095;
55 info!("computed pin mv: {}", pin_mv);
56
57 Timer::after_millis(500).await;
58 }
59}
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
index aebc421b3..8040c3f18 100644
--- a/examples/stm32f334/src/bin/pwm.rs
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -8,7 +8,7 @@ use embassy_stm32::hrtim::*;
8use embassy_stm32::rcc::HrtimClockSource; 8use embassy_stm32::rcc::HrtimClockSource;
9use embassy_stm32::time::{khz, mhz}; 9use embassy_stm32::time::{khz, mhz};
10use embassy_stm32::Config; 10use embassy_stm32::Config;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
@@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) {
48 // .setr(0) 48 // .setr(0)
49 // .modify(|w| w.set_sst(Activeeffect::SETACTIVE)); 49 // .modify(|w| w.set_sst(Activeeffect::SETACTIVE));
50 // 50 //
51 // Timer::after(Duration::from_millis(500)).await; 51 // Timer::after_millis(500).await;
52 // 52 //
53 // embassy_stm32::pac::HRTIM1 53 // embassy_stm32::pac::HRTIM1
54 // .tim(0) 54 // .tim(0)
@@ -65,7 +65,7 @@ async fn main(_spawner: Spawner) {
65 65
66 buck_converter.start(); 66 buck_converter.start();
67 67
68 Timer::after(Duration::from_millis(500)).await; 68 Timer::after_millis(500).await;
69 69
70 info!("end program"); 70 info!("end program");
71 71
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 4b4fb479b..9b10e9754 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -9,9 +9,9 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "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.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] }
15 15
16defmt = "0.3" 16defmt = "0.3"
17defmt-rtt = "0.4" 17defmt-rtt = "0.4"
@@ -19,8 +19,8 @@ defmt-rtt = "0.4"
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
22embedded-io = { version = "0.5.0" } 22embedded-io = { version = "0.6.0" }
23embedded-io-async = { version = "0.5.0" } 23embedded-io-async = { version = "0.6.0" }
24panic-probe = { version = "0.3", features = ["print-defmt"] } 24panic-probe = { version = "0.3", features = ["print-defmt"] }
25futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 25futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
26heapless = { version = "0.7.5", default-features = false } 26heapless = { version = "0.7.5", default-features = false }
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs
index dd10385c4..f19328727 100644
--- a/examples/stm32f4/src/bin/adc.rs
+++ b/examples/stm32f4/src/bin/adc.rs
@@ -6,7 +6,7 @@ use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, Temperature, VrefInt}; 8use embassy_stm32::adc::{Adc, Temperature, VrefInt};
9use embassy_time::{Delay, Duration, Timer}; 9use embassy_time::{Delay, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -63,6 +63,6 @@ async fn main(_spawner: Spawner) {
63 let v = adc.read(&mut vrefint); 63 let v = adc.read(&mut vrefint);
64 info!("VrefInt: {}", v); 64 info!("VrefInt: {}", v);
65 65
66 Timer::after(Duration::from_millis(100)).await; 66 Timer::after_millis(100).await;
67 } 67 }
68} 68}
diff --git a/examples/stm32f4/src/bin/blinky.rs b/examples/stm32f4/src/bin/blinky.rs
index b27bee4ce..4bfc5a50d 100644
--- a/examples/stm32f4/src/bin/blinky.rs
+++ b/examples/stm32f4/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs
index 16bf5d949..1747bbf4b 100644
--- a/examples/stm32f4/src/bin/eth.rs
+++ b/examples/stm32f4/src/bin/eth.rs
@@ -10,9 +10,9 @@ use embassy_stm32::eth::generic_smi::GenericSMI;
10use embassy_stm32::eth::{Ethernet, PacketQueue}; 10use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::Timer;
16use embedded_io_async::Write; 16use embedded_io_async::Write;
17use static_cell::make_static; 17use static_cell::make_static;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
@@ -32,7 +32,25 @@ async fn net_task(stack: &'static Stack<Device>) -> ! {
32#[embassy_executor::main] 32#[embassy_executor::main]
33async fn main(spawner: Spawner) -> ! { 33async fn main(spawner: Spawner) -> ! {
34 let mut config = Config::default(); 34 let mut config = Config::default();
35 config.rcc.sys_ck = Some(mhz(200)); 35 {
36 use embassy_stm32::rcc::*;
37 config.rcc.hse = Some(Hse {
38 freq: Hertz(8_000_000),
39 mode: HseMode::Bypass,
40 });
41 config.rcc.pll_src = PllSource::HSE;
42 config.rcc.pll = Some(Pll {
43 prediv: PllPreDiv::DIV4,
44 mul: PllMul::MUL180,
45 divp: Some(Pllp::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
46 divq: None,
47 divr: None,
48 });
49 config.rcc.ahb_pre = AHBPrescaler::DIV1;
50 config.rcc.apb1_pre = APBPrescaler::DIV4;
51 config.rcc.apb2_pre = APBPrescaler::DIV2;
52 config.rcc.sys = Sysclk::PLL1_P;
53 }
36 let p = embassy_stm32::init(config); 54 let p = embassy_stm32::init(config);
37 55
38 info!("Hello World!"); 56 info!("Hello World!");
@@ -58,9 +76,8 @@ async fn main(spawner: Spawner) -> ! {
58 p.PG13, 76 p.PG13,
59 p.PB13, 77 p.PB13,
60 p.PG11, 78 p.PG11,
61 GenericSMI::new(), 79 GenericSMI::new(0),
62 mac_addr, 80 mac_addr,
63 0,
64 ); 81 );
65 82
66 let config = embassy_net::Config::dhcpv4(Default::default()); 83 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -100,7 +117,7 @@ async fn main(spawner: Spawner) -> ! {
100 let r = socket.connect(remote_endpoint).await; 117 let r = socket.connect(remote_endpoint).await;
101 if let Err(e) = r { 118 if let Err(e) = r {
102 info!("connect error: {:?}", e); 119 info!("connect error: {:?}", e);
103 Timer::after(Duration::from_secs(1)).await; 120 Timer::after_secs(1).await;
104 continue; 121 continue;
105 } 122 }
106 info!("connected!"); 123 info!("connected!");
@@ -111,7 +128,7 @@ async fn main(spawner: Spawner) -> ! {
111 info!("write error: {:?}", e); 128 info!("write error: {:?}", e);
112 break; 129 break;
113 } 130 }
114 Timer::after(Duration::from_secs(1)).await; 131 Timer::after_secs(1).await;
115 } 132 }
116 } 133 }
117} 134}
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs
index 6c9689d9c..f0a65a725 100644
--- a/examples/stm32f4/src/bin/flash_async.rs
+++ b/examples/stm32f4/src/bin/flash_async.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::flash::{Flash, InterruptHandler}; 8use embassy_stm32::flash::{Flash, InterruptHandler};
9use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; 9use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs { 13bind_interrupts!(struct Irqs {
@@ -35,11 +35,11 @@ async fn blinky(p: AnyPin) {
35 loop { 35 loop {
36 info!("high"); 36 info!("high");
37 led.set_high(); 37 led.set_high();
38 Timer::after(Duration::from_millis(300)).await; 38 Timer::after_millis(300).await;
39 39
40 info!("low"); 40 info!("low");
41 led.set_low(); 41 led.set_low();
42 Timer::after(Duration::from_millis(300)).await; 42 Timer::after_millis(300).await;
43 } 43 }
44} 44}
45 45
diff --git a/examples/stm32f4/src/bin/hello.rs b/examples/stm32f4/src/bin/hello.rs
index c409703f5..a2a287110 100644
--- a/examples/stm32f4/src/bin/hello.rs
+++ b/examples/stm32f4/src/bin/hello.rs
@@ -4,19 +4,17 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config; 7use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
11 10
12#[embassy_executor::main] 11#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! { 12async fn main(_spawner: Spawner) -> ! {
14 let mut config = Config::default(); 13 let config = Config::default();
15 config.rcc.sys_ck = Some(Hertz(84_000_000));
16 let _p = embassy_stm32::init(config); 14 let _p = embassy_stm32::init(config);
17 15
18 loop { 16 loop {
19 info!("Hello World!"); 17 info!("Hello World!");
20 Timer::after(Duration::from_secs(1)).await; 18 Timer::after_secs(1).await;
21 } 19 }
22} 20}
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
index a92957325..032bd97ee 100644
--- a/examples/stm32f4/src/bin/i2c.rs
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -5,10 +5,9 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 8use embassy_stm32::i2c::{Error, I2c};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals}; 10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embassy_time::Duration;
12use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
13 12
14const ADDRESS: u8 = 0x5F; 13const ADDRESS: u8 = 0x5F;
@@ -34,13 +33,9 @@ async fn main(_spawner: Spawner) {
34 Default::default(), 33 Default::default(),
35 ); 34 );
36 35
37 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
38 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
39 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
40
41 let mut data = [0u8; 1]; 36 let mut data = [0u8; 1];
42 37
43 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { 38 match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
44 Ok(()) => info!("Whoami: {}", data[0]), 39 Ok(()) => info!("Whoami: {}", data[0]),
45 Err(Error::Timeout) => error!("Operation timed out"), 40 Err(Error::Timeout) => error!("Operation timed out"),
46 Err(e) => error!("I2c Error: {:?}", e), 41 Err(e) => error!("I2c Error: {:?}", e),
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs
index 2b9ceebc3..3315e7652 100644
--- a/examples/stm32f4/src/bin/mco.rs
+++ b/examples/stm32f4/src/bin/mco.rs
@@ -5,8 +5,8 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoClock}; 8use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::DIV1); 17 let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1);
18 let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::Pll, McoClock::DIV4); 18 let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4);
19 let mut led = Output::new(p.PB7, Level::High, Speed::Low); 19 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
20 20
21 loop { 21 loop {
22 info!("high"); 22 info!("high");
23 led.set_high(); 23 led.set_high();
24 Timer::after(Duration::from_millis(300)).await; 24 Timer::after_millis(300).await;
25 25
26 info!("low"); 26 info!("low");
27 led.set_low(); 27 led.set_low();
28 Timer::after(Duration::from_millis(300)).await; 28 Timer::after_millis(300).await;
29 } 29 }
30} 30}
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index 80bf59deb..74f3bb1c5 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -62,7 +62,7 @@ use defmt::*;
62use embassy_executor::{Executor, InterruptExecutor}; 62use embassy_executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt; 63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::{InterruptExt, Priority}; 64use embassy_stm32::interrupt::{InterruptExt, Priority};
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Instant, Timer};
66use static_cell::StaticCell; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
@@ -70,7 +70,7 @@ use {defmt_rtt as _, panic_probe as _};
70async fn run_high() { 70async fn run_high() {
71 loop { 71 loop {
72 info!(" [high] tick!"); 72 info!(" [high] tick!");
73 Timer::after(Duration::from_ticks(27374)).await; 73 Timer::after_ticks(27374).await;
74 } 74 }
75} 75}
76 76
@@ -87,7 +87,7 @@ async fn run_med() {
87 let ms = end.duration_since(start).as_ticks() / 33; 87 let ms = end.duration_since(start).as_ticks() / 33;
88 info!(" [med] done in {} ms", ms); 88 info!(" [med] done in {} ms", ms);
89 89
90 Timer::after(Duration::from_ticks(23421)).await; 90 Timer::after_ticks(23421).await;
91 } 91 }
92} 92}
93 93
@@ -104,7 +104,7 @@ async fn run_low() {
104 let ms = end.duration_since(start).as_ticks() / 33; 104 let ms = end.duration_since(start).as_ticks() / 33;
105 info!("[low] done in {} ms", ms); 105 info!("[low] done in {} ms", ms);
106 106
107 Timer::after(Duration::from_ticks(32983)).await; 107 Timer::after_ticks(32983).await;
108 } 108 }
109} 109}
110 110
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 139b8de70..8e41d0e78 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -8,7 +8,7 @@ use embassy_stm32::gpio::OutputType;
8use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel; 10use embassy_stm32::timer::Channel;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
@@ -26,12 +26,12 @@ async fn main(_spawner: Spawner) {
26 26
27 loop { 27 loop {
28 pwm.set_duty(Channel::Ch1, 0); 28 pwm.set_duty(Channel::Ch1, 0);
29 Timer::after(Duration::from_millis(300)).await; 29 Timer::after_millis(300).await;
30 pwm.set_duty(Channel::Ch1, max / 4); 30 pwm.set_duty(Channel::Ch1, max / 4);
31 Timer::after(Duration::from_millis(300)).await; 31 Timer::after_millis(300).await;
32 pwm.set_duty(Channel::Ch1, max / 2); 32 pwm.set_duty(Channel::Ch1, max / 2);
33 Timer::after(Duration::from_millis(300)).await; 33 Timer::after_millis(300).await;
34 pwm.set_duty(Channel::Ch1, max - 1); 34 pwm.set_duty(Channel::Ch1, max - 1);
35 Timer::after(Duration::from_millis(300)).await; 35 Timer::after_millis(300).await;
36 } 36 }
37} 37}
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index dabbbf9ac..d925f26d9 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -9,7 +9,7 @@ use embassy_stm32::time::khz;
9use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; 9use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
10use embassy_stm32::timer::simple_pwm::PwmPin; 10use embassy_stm32::timer::simple_pwm::PwmPin;
11use embassy_stm32::timer::Channel; 11use embassy_stm32::timer::Channel;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
@@ -43,12 +43,12 @@ async fn main(_spawner: Spawner) {
43 43
44 loop { 44 loop {
45 pwm.set_duty(Channel::Ch1, 0); 45 pwm.set_duty(Channel::Ch1, 0);
46 Timer::after(Duration::from_millis(300)).await; 46 Timer::after_millis(300).await;
47 pwm.set_duty(Channel::Ch1, max / 4); 47 pwm.set_duty(Channel::Ch1, max / 4);
48 Timer::after(Duration::from_millis(300)).await; 48 Timer::after_millis(300).await;
49 pwm.set_duty(Channel::Ch1, max / 2); 49 pwm.set_duty(Channel::Ch1, max / 2);
50 Timer::after(Duration::from_millis(300)).await; 50 Timer::after_millis(300).await;
51 pwm.set_duty(Channel::Ch1, max - 1); 51 pwm.set_duty(Channel::Ch1, max - 1);
52 Timer::after(Duration::from_millis(300)).await; 52 Timer::after_millis(300).await;
53 } 53 }
54} 54}
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs
index e33746008..44b4303c0 100644
--- a/examples/stm32f4/src/bin/rtc.rs
+++ b/examples/stm32f4/src/bin/rtc.rs
@@ -5,16 +5,14 @@
5use chrono::{NaiveDate, NaiveDateTime}; 5use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; 8use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_stm32::Config; 9use embassy_stm32::Config;
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
15 let mut config = Config::default(); 15 let config = Config::default();
16 config.rcc.lsi = true;
17 config.rcc.rtc = Option::Some(RtcClockSource::LSI);
18 let p = embassy_stm32::init(config); 16 let p = embassy_stm32::init(config);
19 17
20 info!("Hello World!"); 18 info!("Hello World!");
@@ -33,6 +31,6 @@ async fn main(_spawner: Spawner) {
33 31
34 info!("{}", now.timestamp()); 32 info!("{}", now.timestamp());
35 33
36 Timer::after(Duration::from_millis(1000)).await; 34 Timer::after_millis(1000).await;
37 } 35 }
38} 36}
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index 6ec7d0fec..37e42384b 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; 7use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::{mhz, Hertz};
9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -20,8 +20,25 @@ bind_interrupts!(struct Irqs {
20#[embassy_executor::main] 20#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
22 let mut config = Config::default(); 22 let mut config = Config::default();
23 config.rcc.sys_ck = Some(mhz(48)); 23 {
24 config.rcc.pll48 = true; 24 use embassy_stm32::rcc::*;
25 config.rcc.hse = Some(Hse {
26 freq: Hertz(8_000_000),
27 mode: HseMode::Bypass,
28 });
29 config.rcc.pll_src = PllSource::HSE;
30 config.rcc.pll = Some(Pll {
31 prediv: PllPreDiv::DIV4,
32 mul: PllMul::MUL168,
33 divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
34 divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
35 divr: None,
36 });
37 config.rcc.ahb_pre = AHBPrescaler::DIV1;
38 config.rcc.apb1_pre = APBPrescaler::DIV4;
39 config.rcc.apb2_pre = APBPrescaler::DIV2;
40 config.rcc.sys = Sysclk::PLL1_P;
41 }
25 let p = embassy_stm32::init(config); 42 let p = embassy_stm32::init(config);
26 info!("Hello World!"); 43 info!("Hello World!");
27 44
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 763e3a9e7..7c0644aeb 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_net::tcp::TcpSocket; 7use embassy_net::tcp::TcpSocket;
8use embassy_net::{Stack, StackResources}; 8use embassy_net::{Stack, StackResources};
9use embassy_stm32::rng::{self, Rng}; 9use embassy_stm32::rng::{self, Rng};
10use embassy_stm32::time::mhz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::usb_otg::Driver; 11use embassy_stm32::usb_otg::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 12use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 13use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
@@ -46,9 +46,25 @@ async fn main(spawner: Spawner) {
46 info!("Hello World!"); 46 info!("Hello World!");
47 47
48 let mut config = Config::default(); 48 let mut config = Config::default();
49 config.rcc.pll48 = true; 49 {
50 config.rcc.sys_ck = Some(mhz(48)); 50 use embassy_stm32::rcc::*;
51 51 config.rcc.hse = Some(Hse {
52 freq: Hertz(8_000_000),
53 mode: HseMode::Bypass,
54 });
55 config.rcc.pll_src = PllSource::HSE;
56 config.rcc.pll = Some(Pll {
57 prediv: PllPreDiv::DIV4,
58 mul: PllMul::MUL168,
59 divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
60 divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
61 divr: None,
62 });
63 config.rcc.ahb_pre = AHBPrescaler::DIV1;
64 config.rcc.apb1_pre = APBPrescaler::DIV4;
65 config.rcc.apb2_pre = APBPrescaler::DIV2;
66 config.rcc.sys = Sysclk::PLL1_P;
67 }
52 let p = embassy_stm32::init(config); 68 let p = embassy_stm32::init(config);
53 69
54 // Create the driver, from the HAL. 70 // Create the driver, from the HAL.
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index 4ff6452ef..004ff038d 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::{panic, *}; 5use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::usb_otg::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
@@ -22,9 +22,25 @@ async fn main(_spawner: Spawner) {
22 info!("Hello World!"); 22 info!("Hello World!");
23 23
24 let mut config = Config::default(); 24 let mut config = Config::default();
25 config.rcc.pll48 = true; 25 {
26 config.rcc.sys_ck = Some(mhz(48)); 26 use embassy_stm32::rcc::*;
27 27 config.rcc.hse = Some(Hse {
28 freq: Hertz(8_000_000),
29 mode: HseMode::Bypass,
30 });
31 config.rcc.pll_src = PllSource::HSE;
32 config.rcc.pll = Some(Pll {
33 prediv: PllPreDiv::DIV4,
34 mul: PllMul::MUL168,
35 divp: Some(Pllp::DIV2), // 8mhz / 4 * 168 / 2 = 168Mhz.
36 divq: Some(Pllq::DIV7), // 8mhz / 4 * 168 / 7 = 48Mhz.
37 divr: None,
38 });
39 config.rcc.ahb_pre = AHBPrescaler::DIV1;
40 config.rcc.apb1_pre = APBPrescaler::DIV4;
41 config.rcc.apb2_pre = APBPrescaler::DIV2;
42 config.rcc.sys = Sysclk::PLL1_P;
43 }
28 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
29 45
30 // Create the driver, from the HAL. 46 // Create the driver, from the HAL.
diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs
index e5d122af7..0443b61c5 100644
--- a/examples/stm32f4/src/bin/wdt.rs
+++ b/examples/stm32f4/src/bin/wdt.rs
@@ -6,7 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::wdg::IndependentWatchdog; 8use embassy_stm32::wdg::IndependentWatchdog;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -24,11 +24,11 @@ async fn main(_spawner: Spawner) {
24 loop { 24 loop {
25 info!("high"); 25 info!("high");
26 led.set_high(); 26 led.set_high();
27 Timer::after(Duration::from_millis(300)).await; 27 Timer::after_millis(300).await;
28 28
29 info!("low"); 29 info!("low");
30 led.set_low(); 30 led.set_low();
31 Timer::after(Duration::from_millis(300)).await; 31 Timer::after_millis(300).await;
32 32
33 // Pet watchdog for 5 iterations and then stop. 33 // Pet watchdog for 5 iterations and then stop.
34 // MCU should restart in 1 second after the last pet. 34 // MCU should restart in 1 second after the last pet.
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index bf8f413d8..5cbaca461 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -9,9 +9,9 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
14embedded-io-async = { version = "0.5.0" } 14embedded-io-async = { version = "0.6.0" }
15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
16 16
17defmt = "0.3" 17defmt = "0.3"
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs
index bc4ed2892..48c59eaf0 100644
--- a/examples/stm32f7/src/bin/adc.rs
+++ b/examples/stm32f7/src/bin/adc.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::Adc; 7use embassy_stm32::adc::Adc;
8use embassy_time::{Delay, Duration, Timer}; 8use embassy_time::{Delay, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -29,6 +29,6 @@ async fn main(_spawner: Spawner) {
29 loop { 29 loop {
30 let v = adc.read(&mut pin); 30 let v = adc.read(&mut pin);
31 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 31 info!("--> {} - {} mV", v, convert_to_millivolts(v));
32 Timer::after(Duration::from_millis(100)).await; 32 Timer::after_millis(100).await;
33 } 33 }
34} 34}
diff --git a/examples/stm32f7/src/bin/blinky.rs b/examples/stm32f7/src/bin/blinky.rs
index b27bee4ce..4bfc5a50d 100644
--- a/examples/stm32f7/src/bin/blinky.rs
+++ b/examples/stm32f7/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index e9650f23a..78b21ceaa 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -26,7 +26,7 @@ pub async fn send_can_message(tx: &'static mut CanTx<'static, 'static, CAN3>) {
26 loop { 26 loop {
27 let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), [0]); 27 let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), [0]);
28 tx.write(&frame).await; 28 tx.write(&frame).await;
29 embassy_time::Timer::after(embassy_time::Duration::from_secs(1)).await; 29 embassy_time::Timer::after_secs(1).await;
30 } 30 }
31} 31}
32 32
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index 93c97c8ee..7c6c419a6 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -10,9 +10,9 @@ use embassy_stm32::eth::generic_smi::GenericSMI;
10use embassy_stm32::eth::{Ethernet, PacketQueue}; 10use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 14use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::Timer;
16use embedded_io_async::Write; 16use embedded_io_async::Write;
17use rand_core::RngCore; 17use rand_core::RngCore;
18use static_cell::make_static; 18use static_cell::make_static;
@@ -33,7 +33,25 @@ async fn net_task(stack: &'static Stack<Device>) -> ! {
33#[embassy_executor::main] 33#[embassy_executor::main]
34async fn main(spawner: Spawner) -> ! { 34async fn main(spawner: Spawner) -> ! {
35 let mut config = Config::default(); 35 let mut config = Config::default();
36 config.rcc.sys_ck = Some(mhz(200)); 36 {
37 use embassy_stm32::rcc::*;
38 config.rcc.hse = Some(Hse {
39 freq: Hertz(8_000_000),
40 mode: HseMode::Bypass,
41 });
42 config.rcc.pll_src = PllSource::HSE;
43 config.rcc.pll = Some(Pll {
44 prediv: PllPreDiv::DIV4,
45 mul: PllMul::MUL216,
46 divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
47 divq: None,
48 divr: None,
49 });
50 config.rcc.ahb_pre = AHBPrescaler::DIV1;
51 config.rcc.apb1_pre = APBPrescaler::DIV4;
52 config.rcc.apb2_pre = APBPrescaler::DIV2;
53 config.rcc.sys = Sysclk::PLL1_P;
54 }
37 let p = embassy_stm32::init(config); 55 let p = embassy_stm32::init(config);
38 56
39 info!("Hello World!"); 57 info!("Hello World!");
@@ -59,9 +77,8 @@ async fn main(spawner: Spawner) -> ! {
59 p.PG13, 77 p.PG13,
60 p.PB13, 78 p.PB13,
61 p.PG11, 79 p.PG11,
62 GenericSMI::new(), 80 GenericSMI::new(0),
63 mac_addr, 81 mac_addr,
64 0,
65 ); 82 );
66 83
67 let config = embassy_net::Config::dhcpv4(Default::default()); 84 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -101,7 +118,7 @@ async fn main(spawner: Spawner) -> ! {
101 let r = socket.connect(remote_endpoint).await; 118 let r = socket.connect(remote_endpoint).await;
102 if let Err(e) = r { 119 if let Err(e) = r {
103 info!("connect error: {:?}", e); 120 info!("connect error: {:?}", e);
104 Timer::after(Duration::from_secs(1)).await; 121 Timer::after_secs(1).await;
105 continue; 122 continue;
106 } 123 }
107 info!("connected!"); 124 info!("connected!");
@@ -112,7 +129,7 @@ async fn main(spawner: Spawner) -> ! {
112 info!("write error: {:?}", e); 129 info!("write error: {:?}", e);
113 break; 130 break;
114 } 131 }
115 Timer::after(Duration::from_secs(1)).await; 132 Timer::after_secs(1).await;
116 } 133 }
117 } 134 }
118} 135}
diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs
index 35d3059be..06a94f1c8 100644
--- a/examples/stm32f7/src/bin/flash.rs
+++ b/examples/stm32f7/src/bin/flash.rs
@@ -5,7 +5,7 @@
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::flash::Flash; 7use embassy_stm32::flash::Flash;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) {
16 const ADDR: u32 = 0x8_0000; // This is the offset into the third region, the absolute address is 4x32K + 128K + 0x8_0000. 16 const ADDR: u32 = 0x8_0000; // This is the offset into the third region, the absolute address is 4x32K + 128K + 0x8_0000.
17 17
18 // wait a bit before accessing the flash 18 // wait a bit before accessing the flash
19 Timer::after(Duration::from_millis(300)).await; 19 Timer::after_millis(300).await;
20 20
21 let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region3; 21 let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region3;
22 22
diff --git a/examples/stm32f7/src/bin/hello.rs b/examples/stm32f7/src/bin/hello.rs
index c409703f5..a2a287110 100644
--- a/examples/stm32f7/src/bin/hello.rs
+++ b/examples/stm32f7/src/bin/hello.rs
@@ -4,19 +4,17 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::Hertz;
8use embassy_stm32::Config; 7use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
11 10
12#[embassy_executor::main] 11#[embassy_executor::main]
13async fn main(_spawner: Spawner) -> ! { 12async fn main(_spawner: Spawner) -> ! {
14 let mut config = Config::default(); 13 let config = Config::default();
15 config.rcc.sys_ck = Some(Hertz(84_000_000));
16 let _p = embassy_stm32::init(config); 14 let _p = embassy_stm32::init(config);
17 15
18 loop { 16 loop {
19 info!("Hello World!"); 17 info!("Hello World!");
20 Timer::after(Duration::from_secs(1)).await; 18 Timer::after_secs(1).await;
21 } 19 }
22} 20}
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs
index 9d43892a0..430aa781f 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::sdmmc::Sdmmc; 7use embassy_stm32::sdmmc::Sdmmc;
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::{mhz, Hertz};
9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -16,8 +16,25 @@ bind_interrupts!(struct Irqs {
16#[embassy_executor::main] 16#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let mut config = Config::default(); 18 let mut config = Config::default();
19 config.rcc.sys_ck = Some(mhz(200)); 19 {
20 config.rcc.pll48 = true; 20 use embassy_stm32::rcc::*;
21 config.rcc.hse = Some(Hse {
22 freq: Hertz(8_000_000),
23 mode: HseMode::Bypass,
24 });
25 config.rcc.pll_src = PllSource::HSE;
26 config.rcc.pll = Some(Pll {
27 prediv: PllPreDiv::DIV4,
28 mul: PllMul::MUL216,
29 divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
30 divq: Some(Pllq::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
31 divr: None,
32 });
33 config.rcc.ahb_pre = AHBPrescaler::DIV1;
34 config.rcc.apb1_pre = APBPrescaler::DIV4;
35 config.rcc.apb2_pre = APBPrescaler::DIV2;
36 config.rcc.sys = Sysclk::PLL1_P;
37 }
21 let p = embassy_stm32::init(config); 38 let p = embassy_stm32::init(config);
22 39
23 info!("Hello World!"); 40 info!("Hello World!");
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index a2c76178b..2f832c234 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::{panic, *}; 5use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb_otg::{Driver, Instance}; 8use embassy_stm32::usb_otg::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
@@ -22,10 +22,25 @@ async fn main(_spawner: Spawner) {
22 info!("Hello World!"); 22 info!("Hello World!");
23 23
24 let mut config = Config::default(); 24 let mut config = Config::default();
25 config.rcc.hse = Some(mhz(8)); 25 {
26 config.rcc.pll48 = true; 26 use embassy_stm32::rcc::*;
27 config.rcc.sys_ck = Some(mhz(200)); 27 config.rcc.hse = Some(Hse {
28 28 freq: Hertz(8_000_000),
29 mode: HseMode::Bypass,
30 });
31 config.rcc.pll_src = PllSource::HSE;
32 config.rcc.pll = Some(Pll {
33 prediv: PllPreDiv::DIV4,
34 mul: PllMul::MUL216,
35 divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz
36 divq: Some(Pllq::DIV9), // 8mhz / 4 * 216 / 9 = 48Mhz
37 divr: None,
38 });
39 config.rcc.ahb_pre = AHBPrescaler::DIV1;
40 config.rcc.apb1_pre = APBPrescaler::DIV4;
41 config.rcc.apb2_pre = APBPrescaler::DIV2;
42 config.rcc.sys = Sysclk::PLL1_P;
43 }
29 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
30 45
31 // Create the driver, from the HAL. 46 // Create the driver, from the HAL.
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index b4b423d58..d0b7d85f8 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13 13
14defmt = "0.3" 14defmt = "0.3"
15defmt-rtt = "0.4" 15defmt-rtt = "0.4"
diff --git a/examples/stm32g0/src/bin/blinky.rs b/examples/stm32g0/src/bin/blinky.rs
index b27bee4ce..4bfc5a50d 100644
--- a/examples/stm32g0/src/bin/blinky.rs
+++ b/examples/stm32g0/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32g0/src/bin/spi_neopixel.rs b/examples/stm32g0/src/bin/spi_neopixel.rs
index ee7aaf33f..214462d0e 100644
--- a/examples/stm32g0/src/bin/spi_neopixel.rs
+++ b/examples/stm32g0/src/bin/spi_neopixel.rs
@@ -8,7 +8,7 @@ use embassy_stm32::dma::word::U5;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::spi::{Config, Spi}; 9use embassy_stm32::spi::{Config, Spi};
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14const NR_PIXELS: usize = 15; 14const NR_PIXELS: usize = 15;
@@ -96,8 +96,8 @@ async fn main(_spawner: Spawner) {
96 cnt += 1; 96 cnt += 1;
97 // start sending the neopixel bit patters over spi to the neopixel string 97 // start sending the neopixel bit patters over spi to the neopixel string
98 spi.write(&neopixels.bitbuffer).await.ok(); 98 spi.write(&neopixels.bitbuffer).await.ok();
99 Timer::after(Duration::from_millis(500)).await; 99 Timer::after_millis(500).await;
100 } 100 }
101 Timer::after(Duration::from_millis(1000)).await; 101 Timer::after_millis(1000).await;
102 } 102 }
103} 103}
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 59da06283..908c6d19d 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", 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" }
15usbd-hid = "0.6.0" 15usbd-hid = "0.6.0"
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs
index a792748bc..db7f6ecb5 100644
--- a/examples/stm32g4/src/bin/adc.rs
+++ b/examples/stm32g4/src/bin/adc.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; 8use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSrc};
9use embassy_stm32::Config; 9use embassy_stm32::Config;
10use embassy_time::{Delay, Duration, Timer}; 10use embassy_time::{Delay, Timer};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
@@ -16,15 +16,15 @@ async fn main(_spawner: Spawner) {
16 16
17 config.rcc.pll = Some(Pll { 17 config.rcc.pll = Some(Pll {
18 source: PllSrc::HSI16, 18 source: PllSrc::HSI16,
19 prediv_m: PllM::Div4, 19 prediv_m: PllM::DIV4,
20 mul_n: PllN::Mul85, 20 mul_n: PllN::MUL85,
21 div_p: None, 21 div_p: None,
22 div_q: None, 22 div_q: None,
23 // Main system clock at 170 MHz 23 // Main system clock at 170 MHz
24 div_r: Some(PllR::Div2), 24 div_r: Some(PllR::DIV2),
25 }); 25 });
26 26
27 config.rcc.adc12_clock_source = AdcClockSource::SysClk; 27 config.rcc.adc12_clock_source = AdcClockSource::SYS;
28 config.rcc.mux = ClockSrc::PLL; 28 config.rcc.mux = ClockSrc::PLL;
29 29
30 let mut p = embassy_stm32::init(config); 30 let mut p = embassy_stm32::init(config);
@@ -36,6 +36,6 @@ async fn main(_spawner: Spawner) {
36 loop { 36 loop {
37 let measured = adc.read(&mut p.PA7); 37 let measured = adc.read(&mut p.PA7);
38 info!("measured: {}", measured); 38 info!("measured: {}", measured);
39 Timer::after(Duration::from_millis(500)).await; 39 Timer::after_millis(500).await;
40 } 40 }
41} 41}
diff --git a/examples/stm32g4/src/bin/blinky.rs b/examples/stm32g4/src/bin/blinky.rs
index 8a65b0692..cbeb0dee1 100644
--- a/examples/stm32g4/src/bin/blinky.rs
+++ b/examples/stm32g4/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs
index ef7d4800c..43242647f 100644
--- a/examples/stm32g4/src/bin/pll.rs
+++ b/examples/stm32g4/src/bin/pll.rs
@@ -6,7 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; 7use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSrc};
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -15,12 +15,12 @@ async fn main(_spawner: Spawner) {
15 15
16 config.rcc.pll = Some(Pll { 16 config.rcc.pll = Some(Pll {
17 source: PllSrc::HSI16, 17 source: PllSrc::HSI16,
18 prediv_m: PllM::Div4, 18 prediv_m: PllM::DIV4,
19 mul_n: PllN::Mul85, 19 mul_n: PllN::MUL85,
20 div_p: None, 20 div_p: None,
21 div_q: None, 21 div_q: None,
22 // Main system clock at 170 MHz 22 // Main system clock at 170 MHz
23 div_r: Some(PllR::Div2), 23 div_r: Some(PllR::DIV2),
24 }); 24 });
25 25
26 config.rcc.mux = ClockSrc::PLL; 26 config.rcc.mux = ClockSrc::PLL;
@@ -29,7 +29,7 @@ async fn main(_spawner: Spawner) {
29 info!("Hello World!"); 29 info!("Hello World!");
30 30
31 loop { 31 loop {
32 Timer::after(Duration::from_millis(1000)).await; 32 Timer::after_millis(1000).await;
33 info!("1s elapsed"); 33 info!("1s elapsed");
34 } 34 }
35} 35}
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index c62b11d13..a84394005 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -8,7 +8,7 @@ use embassy_stm32::gpio::OutputType;
8use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel; 10use embassy_stm32::timer::Channel;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
@@ -26,12 +26,12 @@ async fn main(_spawner: Spawner) {
26 26
27 loop { 27 loop {
28 pwm.set_duty(Channel::Ch1, 0); 28 pwm.set_duty(Channel::Ch1, 0);
29 Timer::after(Duration::from_millis(300)).await; 29 Timer::after_millis(300).await;
30 pwm.set_duty(Channel::Ch1, max / 4); 30 pwm.set_duty(Channel::Ch1, max / 4);
31 Timer::after(Duration::from_millis(300)).await; 31 Timer::after_millis(300).await;
32 pwm.set_duty(Channel::Ch1, max / 2); 32 pwm.set_duty(Channel::Ch1, max / 2);
33 Timer::after(Duration::from_millis(300)).await; 33 Timer::after_millis(300).await;
34 pwm.set_duty(Channel::Ch1, max - 1); 34 pwm.set_duty(Channel::Ch1, max - 1);
35 Timer::after(Duration::from_millis(300)).await; 35 Timer::after_millis(300).await;
36 } 36 }
37} 37}
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs
index 77cfa67d3..9099b609a 100644
--- a/examples/stm32g4/src/bin/usb_serial.rs
+++ b/examples/stm32g4/src/bin/usb_serial.rs
@@ -25,16 +25,16 @@ async fn main(_spawner: Spawner) {
25 // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. 25 // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
26 const USE_HSI48: bool = true; 26 const USE_HSI48: bool = true;
27 27
28 let pllq_div = if USE_HSI48 { None } else { Some(PllQ::Div6) }; 28 let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
29 29
30 config.rcc.pll = Some(Pll { 30 config.rcc.pll = Some(Pll {
31 source: PllSrc::HSE(Hertz(8_000_000)), 31 source: PllSrc::HSE(Hertz(8_000_000)),
32 prediv_m: PllM::Div2, 32 prediv_m: PllM::DIV2,
33 mul_n: PllN::Mul72, 33 mul_n: PllN::MUL72,
34 div_p: None, 34 div_p: None,
35 div_q: pllq_div, 35 div_q: pllq_div,
36 // Main system clock at 144 MHz 36 // Main system clock at 144 MHz
37 div_r: Some(PllR::Div2), 37 div_r: Some(PllR::DIV2),
38 }); 38 });
39 39
40 config.rcc.mux = ClockSrc::PLL; 40 config.rcc.mux = ClockSrc::PLL;
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 42a426185..f5980d87a 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -9,9 +9,9 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
13embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
14embedded-io-async = { version = "0.5.0" } 14embedded-io-async = { version = "0.6.0" }
15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
16 16
17defmt = "0.3" 17defmt = "0.3"
@@ -22,7 +22,7 @@ cortex-m-rt = "0.7.0"
22embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
23embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } 23embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
24embedded-hal-async = { version = "=1.0.0-rc.1" } 24embedded-hal-async = { version = "=1.0.0-rc.1" }
25embedded-nal-async = { version = "0.5.0" } 25embedded-nal-async = { version = "0.6.0" }
26panic-probe = { version = "0.3", features = ["print-defmt"] } 26panic-probe = { version = "0.3", features = ["print-defmt"] }
27futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 27futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
28heapless = { version = "0.7.5", default-features = false } 28heapless = { version = "0.7.5", default-features = false }
diff --git a/examples/stm32h5/src/bin/blinky.rs b/examples/stm32h5/src/bin/blinky.rs
index f9bf90d2e..1394f03fa 100644
--- a/examples/stm32h5/src/bin/blinky.rs
+++ b/examples/stm32h5/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(500)).await; 25 Timer::after_millis(500).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index 4e92d0647..6e40f0ac0 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -9,11 +9,13 @@ use embassy_net::{Ipv4Address, Stack, StackResources};
9use embassy_stm32::eth::generic_smi::GenericSMI; 9use embassy_stm32::eth::generic_smi::GenericSMI;
10use embassy_stm32::eth::{Ethernet, PacketQueue}; 10use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; 12use embassy_stm32::rcc::{
13 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
14};
13use embassy_stm32::rng::Rng; 15use embassy_stm32::rng::Rng;
14use embassy_stm32::time::Hertz; 16use embassy_stm32::time::Hertz;
15use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 17use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
16use embassy_time::{Duration, Timer}; 18use embassy_time::Timer;
17use embedded_io_async::Write; 19use embedded_io_async::Write;
18use rand_core::RngCore; 20use rand_core::RngCore;
19use static_cell::make_static; 21use static_cell::make_static;
@@ -42,10 +44,10 @@ async fn main(spawner: Spawner) -> ! {
42 }); 44 });
43 config.rcc.pll1 = Some(Pll { 45 config.rcc.pll1 = Some(Pll {
44 source: PllSource::Hse, 46 source: PllSource::Hse,
45 prediv: 2, 47 prediv: PllPreDiv::DIV2,
46 mul: 125, 48 mul: PllMul::MUL125,
47 divp: Some(2), 49 divp: Some(PllDiv::DIV2),
48 divq: Some(2), 50 divq: Some(PllDiv::DIV2),
49 divr: None, 51 divr: None,
50 }); 52 });
51 config.rcc.ahb_pre = AHBPrescaler::DIV1; 53 config.rcc.ahb_pre = AHBPrescaler::DIV1;
@@ -78,9 +80,8 @@ async fn main(spawner: Spawner) -> ! {
78 p.PG13, 80 p.PG13,
79 p.PB15, 81 p.PB15,
80 p.PG11, 82 p.PG11,
81 GenericSMI::new(), 83 GenericSMI::new(0),
82 mac_addr, 84 mac_addr,
83 0,
84 ); 85 );
85 86
86 let config = embassy_net::Config::dhcpv4(Default::default()); 87 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -120,7 +121,7 @@ async fn main(spawner: Spawner) -> ! {
120 let r = socket.connect(remote_endpoint).await; 121 let r = socket.connect(remote_endpoint).await;
121 if let Err(e) = r { 122 if let Err(e) = r {
122 info!("connect error: {:?}", e); 123 info!("connect error: {:?}", e);
123 Timer::after(Duration::from_secs(3)).await; 124 Timer::after_secs(3).await;
124 continue; 125 continue;
125 } 126 }
126 info!("connected!"); 127 info!("connected!");
@@ -130,7 +131,7 @@ async fn main(spawner: Spawner) -> ! {
130 info!("write error: {:?}", e); 131 info!("write error: {:?}", e);
131 break; 132 break;
132 } 133 }
133 Timer::after(Duration::from_secs(1)).await; 134 Timer::after_secs(1).await;
134 } 135 }
135 } 136 }
136} 137}
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs
index 8b6fe71ae..8b1662f39 100644
--- a/examples/stm32h5/src/bin/i2c.rs
+++ b/examples/stm32h5/src/bin/i2c.rs
@@ -4,10 +4,9 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 7use embassy_stm32::i2c::{Error, I2c};
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals}; 9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
13const ADDRESS: u8 = 0x5F; 12const ADDRESS: u8 = 0x5F;
@@ -33,13 +32,9 @@ async fn main(_spawner: Spawner) {
33 Default::default(), 32 Default::default(),
34 ); 33 );
35 34
36 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
37 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
38 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
39
40 let mut data = [0u8; 1]; 35 let mut data = [0u8; 1];
41 36
42 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { 37 match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
43 Ok(()) => info!("Whoami: {}", data[0]), 38 Ok(()) => info!("Whoami: {}", data[0]),
44 Err(Error::Timeout) => error!("Operation timed out"), 39 Err(Error::Timeout) => error!("Operation timed out"),
45 Err(e) => error!("I2c Error: {:?}", e), 40 Err(e) => error!("I2c Error: {:?}", e),
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index cbe540a06..3b3c38e17 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -4,7 +4,9 @@
4 4
5use defmt::{panic, *}; 5use defmt::{panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; 7use embassy_stm32::rcc::{
8 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
9};
8use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
9use embassy_stm32::usb::{Driver, Instance}; 11use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; 12use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config};
@@ -29,9 +31,9 @@ async fn main(_spawner: Spawner) {
29 }); 31 });
30 config.rcc.pll1 = Some(Pll { 32 config.rcc.pll1 = Some(Pll {
31 source: PllSource::Hse, 33 source: PllSource::Hse,
32 prediv: 2, 34 prediv: PllPreDiv::DIV2,
33 mul: 125, 35 mul: PllMul::MUL125,
34 divp: Some(2), // 250mhz 36 divp: Some(PllDiv::DIV2), // 250mhz
35 divq: None, 37 divq: None,
36 divr: None, 38 divr: None,
37 }); 39 });
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index c1d49963c..0855bdfc7 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -6,12 +6,12 @@ license = "MIT OR Apache-2.0"
6 6
7[dependencies] 7[dependencies]
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 = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits", "chrono"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
13embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } 13embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
14embedded-io-async = { version = "0.5.0" } 14embedded-io-async = { version = "0.6.0" }
15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
16 16
17defmt = "0.3" 17defmt = "0.3"
@@ -22,7 +22,7 @@ cortex-m-rt = "0.7.0"
22embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
23embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } 23embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
24embedded-hal-async = { version = "=1.0.0-rc.1" } 24embedded-hal-async = { version = "=1.0.0-rc.1" }
25embedded-nal-async = { version = "0.5.0" } 25embedded-nal-async = { version = "0.6.0" }
26panic-probe = { version = "0.3", features = ["print-defmt"] } 26panic-probe = { version = "0.3", features = ["print-defmt"] }
27futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 27futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
28heapless = { version = "0.7.5", default-features = false } 28heapless = { version = "0.7.5", default-features = false }
@@ -32,6 +32,7 @@ micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.0" 33embedded-storage = "0.3.0"
34static_cell = { version = "1.1", features = ["nightly"]} 34static_cell = { version = "1.1", features = ["nightly"]}
35chrono = { version = "^0.4", default-features = false }
35 36
36# cargo build/run 37# cargo build/run
37[profile.dev] 38[profile.dev]
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs
index 77922d4bc..4a358a35f 100644
--- a/examples/stm32h7/src/bin/adc.rs
+++ b/examples/stm32h7/src/bin/adc.rs
@@ -6,7 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Delay, Duration, Timer}; 9use embassy_time::{Delay, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -18,16 +18,16 @@ async fn main(_spawner: Spawner) {
18 config.rcc.csi = true; 18 config.rcc.csi = true;
19 config.rcc.pll_src = PllSource::Hsi; 19 config.rcc.pll_src = PllSource::Hsi;
20 config.rcc.pll1 = Some(Pll { 20 config.rcc.pll1 = Some(Pll {
21 prediv: 4, 21 prediv: PllPreDiv::DIV4,
22 mul: 50, 22 mul: PllMul::MUL50,
23 divp: Some(2), 23 divp: Some(PllDiv::DIV2),
24 divq: Some(8), // SPI1 cksel defaults to pll1_q 24 divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q
25 divr: None, 25 divr: None,
26 }); 26 });
27 config.rcc.pll2 = Some(Pll { 27 config.rcc.pll2 = Some(Pll {
28 prediv: 4, 28 prediv: PllPreDiv::DIV4,
29 mul: 50, 29 mul: PllMul::MUL50,
30 divp: Some(8), // 100mhz 30 divp: Some(PllDiv::DIV8), // 100mhz
31 divq: None, 31 divq: None,
32 divr: None, 32 divr: None,
33 }); 33 });
@@ -55,6 +55,6 @@ async fn main(_spawner: Spawner) {
55 info!("vrefint: {}", vrefint); 55 info!("vrefint: {}", vrefint);
56 let measured = adc.read(&mut p.PC0); 56 let measured = adc.read(&mut p.PC0);
57 info!("measured: {}", measured); 57 info!("measured: {}", measured);
58 Timer::after(Duration::from_millis(500)).await; 58 Timer::after_millis(500).await;
59 } 59 }
60} 60}
diff --git a/examples/stm32h7/src/bin/blinky.rs b/examples/stm32h7/src/bin/blinky.rs
index 12f08c0fd..a9cab1ff4 100644
--- a/examples/stm32h7/src/bin/blinky.rs
+++ b/examples/stm32h7/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(500)).await; 25 Timer::after_millis(500).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index de8ddc292..8195430b2 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_stm32::dcmi::{self, *}; 6use embassy_stm32::dcmi::{self, *};
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::i2c::I2c; 8use embassy_stm32::i2c::I2c;
9use embassy_stm32::rcc::{Mco, Mco1Source}; 9use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
10use embassy_stm32::time::khz; 10use embassy_stm32::time::khz;
11use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; 11use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use ov7725::*; 13use ov7725::*;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -32,10 +32,10 @@ async fn main(_spawner: Spawner) {
32 config.rcc.csi = true; 32 config.rcc.csi = true;
33 config.rcc.pll_src = PllSource::Hsi; 33 config.rcc.pll_src = PllSource::Hsi;
34 config.rcc.pll1 = Some(Pll { 34 config.rcc.pll1 = Some(Pll {
35 prediv: 4, 35 prediv: PllPreDiv::DIV4,
36 mul: 50, 36 mul: PllMul::MUL50,
37 divp: Some(2), 37 divp: Some(PllDiv::DIV2),
38 divq: Some(8), // 100mhz 38 divq: Some(PllDiv::DIV8), // 100mhz
39 divr: None, 39 divr: None,
40 }); 40 });
41 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 41 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
@@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) {
49 let p = embassy_stm32::init(config); 49 let p = embassy_stm32::init(config);
50 50
51 defmt::info!("Hello World!"); 51 defmt::info!("Hello World!");
52 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 3); 52 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3);
53 53
54 let mut led = Output::new(p.PE3, Level::High, Speed::Low); 54 let mut led = Output::new(p.PE3, Level::High, Speed::Low);
55 let cam_i2c = I2c::new( 55 let cam_i2c = I2c::new(
@@ -86,11 +86,11 @@ async fn main(_spawner: Spawner) {
86 loop { 86 loop {
87 defmt::info!("high"); 87 defmt::info!("high");
88 led.set_high(); 88 led.set_high();
89 Timer::after(Duration::from_millis(500)).await; 89 Timer::after_millis(500).await;
90 90
91 defmt::info!("low"); 91 defmt::info!("low");
92 led.set_low(); 92 led.set_low();
93 Timer::after(Duration::from_millis(500)).await; 93 Timer::after_millis(500).await;
94 } 94 }
95} 95}
96 96
@@ -99,7 +99,7 @@ mod ov7725 {
99 99
100 use defmt::Format; 100 use defmt::Format;
101 use embassy_stm32::rcc::{Mco, McoInstance}; 101 use embassy_stm32::rcc::{Mco, McoInstance};
102 use embassy_time::{Duration, Timer}; 102 use embassy_time::Timer;
103 use embedded_hal_async::i2c::I2c; 103 use embedded_hal_async::i2c::I2c;
104 104
105 #[repr(u8)] 105 #[repr(u8)]
@@ -184,7 +184,7 @@ mod ov7725 {
184 184
185 const CAM_ADDR: u8 = 0x21; 185 const CAM_ADDR: u8 = 0x21;
186 186
187 #[derive(Format)] 187 #[derive(Format, PartialEq, Eq)]
188 pub enum Error<I2cError: Format> { 188 pub enum Error<I2cError: Format> {
189 I2c(I2cError), 189 I2c(I2cError),
190 } 190 }
@@ -210,9 +210,9 @@ mod ov7725 {
210 } 210 }
211 211
212 pub async fn init(&mut self) -> Result<(), Error<Bus::Error>> { 212 pub async fn init(&mut self) -> Result<(), Error<Bus::Error>> {
213 Timer::after(Duration::from_millis(500)).await; 213 Timer::after_millis(500).await;
214 self.reset_regs().await?; 214 self.reset_regs().await?;
215 Timer::after(Duration::from_millis(500)).await; 215 Timer::after_millis(500).await;
216 self.set_pixformat().await?; 216 self.set_pixformat().await?;
217 self.set_resolution().await?; 217 self.set_resolution().await?;
218 Ok(()) 218 Ok(())
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index 93df7a319..821221897 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -20,16 +20,16 @@ fn main() -> ! {
20 config.rcc.csi = true; 20 config.rcc.csi = true;
21 config.rcc.pll_src = PllSource::Hsi; 21 config.rcc.pll_src = PllSource::Hsi;
22 config.rcc.pll1 = Some(Pll { 22 config.rcc.pll1 = Some(Pll {
23 prediv: 4, 23 prediv: PllPreDiv::DIV4,
24 mul: 50, 24 mul: PllMul::MUL50,
25 divp: Some(2), 25 divp: Some(PllDiv::DIV2),
26 divq: Some(8), // SPI1 cksel defaults to pll1_q 26 divq: Some(PllDiv::DIV8), // 100mhz
27 divr: None, 27 divr: None,
28 }); 28 });
29 config.rcc.pll2 = Some(Pll { 29 config.rcc.pll2 = Some(Pll {
30 prediv: 4, 30 prediv: PllPreDiv::DIV4,
31 mul: 50, 31 mul: PllMul::MUL50,
32 divp: Some(8), // 100mhz 32 divp: Some(PllDiv::DIV8), // 100mhz
33 divq: None, 33 divq: None,
34 divr: None, 34 divr: None,
35 }); 35 });
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index 8c921abca..334986a05 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -28,16 +28,16 @@ async fn main(spawner: Spawner) {
28 config.rcc.csi = true; 28 config.rcc.csi = true;
29 config.rcc.pll_src = PllSource::Hsi; 29 config.rcc.pll_src = PllSource::Hsi;
30 config.rcc.pll1 = Some(Pll { 30 config.rcc.pll1 = Some(Pll {
31 prediv: 4, 31 prediv: PllPreDiv::DIV4,
32 mul: 50, 32 mul: PllMul::MUL50,
33 divp: Some(2), 33 divp: Some(PllDiv::DIV2),
34 divq: Some(8), // SPI1 cksel defaults to pll1_q 34 divq: Some(PllDiv::DIV8), // 100mhz
35 divr: None, 35 divr: None,
36 }); 36 });
37 config.rcc.pll2 = Some(Pll { 37 config.rcc.pll2 = Some(Pll {
38 prediv: 4, 38 prediv: PllPreDiv::DIV4,
39 mul: 50, 39 mul: PllMul::MUL50,
40 divp: Some(8), // 100mhz 40 divp: Some(PllDiv::DIV8), // 100mhz
41 divq: None, 41 divq: None,
42 divr: None, 42 divr: None,
43 }); 43 });
@@ -79,7 +79,7 @@ async fn dac_task1(mut dac: Dac1Type) {
79 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap(); 79 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap();
80 dac.enable_channel().unwrap(); 80 dac.enable_channel().unwrap();
81 81
82 TIM6::enable(); 82 TIM6::enable_and_reset();
83 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); 83 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
84 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 84 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
85 TIM6::regs().cr1().modify(|w| { 85 TIM6::regs().cr1().modify(|w| {
@@ -118,7 +118,7 @@ async fn dac_task2(mut dac: Dac2Type) {
118 error!("Reload value {} below threshold!", reload); 118 error!("Reload value {} below threshold!", reload);
119 } 119 }
120 120
121 TIM7::enable(); 121 TIM7::enable_and_reset();
122 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); 122 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
123 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 123 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
124 TIM7::regs().cr1().modify(|w| { 124 TIM7::regs().cr1().modify(|w| {
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 1b5d71ed3..81d9c7347 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
14use embassy_time::{Duration, Timer}; 14use embassy_time::Timer;
15use embedded_io_async::Write; 15use embedded_io_async::Write;
16use rand_core::RngCore; 16use rand_core::RngCore;
17use static_cell::make_static; 17use static_cell::make_static;
@@ -39,9 +39,9 @@ async fn main(spawner: Spawner) -> ! {
39 config.rcc.hsi48 = true; // needed for RNG 39 config.rcc.hsi48 = true; // needed for RNG
40 config.rcc.pll_src = PllSource::Hsi; 40 config.rcc.pll_src = PllSource::Hsi;
41 config.rcc.pll1 = Some(Pll { 41 config.rcc.pll1 = Some(Pll {
42 prediv: 4, 42 prediv: PllPreDiv::DIV4,
43 mul: 50, 43 mul: PllMul::MUL50,
44 divp: Some(2), 44 divp: Some(PllDiv::DIV2),
45 divq: None, 45 divq: None,
46 divr: None, 46 divr: None,
47 }); 47 });
@@ -77,9 +77,8 @@ async fn main(spawner: Spawner) -> ! {
77 p.PG13, 77 p.PG13,
78 p.PB13, 78 p.PB13,
79 p.PG11, 79 p.PG11,
80 GenericSMI::new(), 80 GenericSMI::new(0),
81 mac_addr, 81 mac_addr,
82 0,
83 ); 82 );
84 83
85 let config = embassy_net::Config::dhcpv4(Default::default()); 84 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -119,7 +118,7 @@ async fn main(spawner: Spawner) -> ! {
119 let r = socket.connect(remote_endpoint).await; 118 let r = socket.connect(remote_endpoint).await;
120 if let Err(e) = r { 119 if let Err(e) = r {
121 info!("connect error: {:?}", e); 120 info!("connect error: {:?}", e);
122 Timer::after(Duration::from_secs(1)).await; 121 Timer::after_secs(1).await;
123 continue; 122 continue;
124 } 123 }
125 info!("connected!"); 124 info!("connected!");
@@ -129,7 +128,7 @@ async fn main(spawner: Spawner) -> ! {
129 info!("write error: {:?}", e); 128 info!("write error: {:?}", e);
130 break; 129 break;
131 } 130 }
132 Timer::after(Duration::from_secs(1)).await; 131 Timer::after_secs(1).await;
133 } 132 }
134 } 133 }
135} 134}
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 3abd31c73..338137069 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -11,7 +11,7 @@ use embassy_stm32::eth::{Ethernet, PacketQueue};
11use embassy_stm32::peripherals::ETH; 11use embassy_stm32::peripherals::ETH;
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
14use embassy_time::{Duration, Timer}; 14use embassy_time::Timer;
15use embedded_io_async::Write; 15use embedded_io_async::Write;
16use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; 16use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
17use rand_core::RngCore; 17use rand_core::RngCore;
@@ -40,9 +40,9 @@ async fn main(spawner: Spawner) -> ! {
40 config.rcc.hsi48 = true; // needed for RNG 40 config.rcc.hsi48 = true; // needed for RNG
41 config.rcc.pll_src = PllSource::Hsi; 41 config.rcc.pll_src = PllSource::Hsi;
42 config.rcc.pll1 = Some(Pll { 42 config.rcc.pll1 = Some(Pll {
43 prediv: 4, 43 prediv: PllPreDiv::DIV4,
44 mul: 50, 44 mul: PllMul::MUL50,
45 divp: Some(2), 45 divp: Some(PllDiv::DIV2),
46 divq: None, 46 divq: None,
47 divr: None, 47 divr: None,
48 }); 48 });
@@ -78,9 +78,8 @@ async fn main(spawner: Spawner) -> ! {
78 p.PG13, 78 p.PG13,
79 p.PB13, 79 p.PB13,
80 p.PG11, 80 p.PG11,
81 GenericSMI::new(), 81 GenericSMI::new(0),
82 mac_addr, 82 mac_addr,
83 0,
84 ); 83 );
85 84
86 let config = embassy_net::Config::dhcpv4(Default::default()); 85 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -106,8 +105,8 @@ async fn main(spawner: Spawner) -> ! {
106 105
107 info!("Network task initialized"); 106 info!("Network task initialized");
108 107
109 static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new(); 108 let state: TcpClientState<1, 1024, 1024> = TcpClientState::new();
110 let client = TcpClient::new(&stack, &STATE); 109 let client = TcpClient::new(&stack, &state);
111 110
112 loop { 111 loop {
113 let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000)); 112 let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000));
@@ -116,7 +115,7 @@ async fn main(spawner: Spawner) -> ! {
116 let r = client.connect(addr).await; 115 let r = client.connect(addr).await;
117 if let Err(e) = r { 116 if let Err(e) = r {
118 info!("connect error: {:?}", e); 117 info!("connect error: {:?}", e);
119 Timer::after(Duration::from_secs(1)).await; 118 Timer::after_secs(1).await;
120 continue; 119 continue;
121 } 120 }
122 let mut connection = r.unwrap(); 121 let mut connection = r.unwrap();
@@ -127,7 +126,7 @@ async fn main(spawner: Spawner) -> ! {
127 info!("write error: {:?}", e); 126 info!("write error: {:?}", e);
128 break; 127 break;
129 } 128 }
130 Timer::after(Duration::from_secs(1)).await; 129 Timer::after_secs(1).await;
131 } 130 }
132 } 131 }
133} 132}
diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs
index f66df770b..89c0c8a66 100644
--- a/examples/stm32h7/src/bin/flash.rs
+++ b/examples/stm32h7/src/bin/flash.rs
@@ -5,7 +5,7 @@
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::flash::Flash; 7use embassy_stm32::flash::Flash;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) {
16 const ADDR: u32 = 0; // This is the offset into bank 2, the absolute address is 0x8_0000 16 const ADDR: u32 = 0; // This is the offset into bank 2, the absolute address is 0x8_0000
17 17
18 // wait a bit before accessing the flash 18 // wait a bit before accessing the flash
19 Timer::after(Duration::from_millis(300)).await; 19 Timer::after_millis(300).await;
20 20
21 let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank2_region; 21 let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank2_region;
22 22
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs
index de0b351df..cffd47093 100644
--- a/examples/stm32h7/src/bin/fmc.rs
+++ b/examples/stm32h7/src/bin/fmc.rs
@@ -6,7 +6,7 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::fmc::Fmc; 7use embassy_stm32::fmc::Fmc;
8use embassy_stm32::Config; 8use embassy_stm32::Config;
9use embassy_time::{Delay, Duration, Timer}; 9use embassy_time::{Delay, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 config.rcc.csi = true; 18 config.rcc.csi = true;
19 config.rcc.pll_src = PllSource::Hsi; 19 config.rcc.pll_src = PllSource::Hsi;
20 config.rcc.pll1 = Some(Pll { 20 config.rcc.pll1 = Some(Pll {
21 prediv: 4, 21 prediv: PllPreDiv::DIV4,
22 mul: 50, 22 mul: PllMul::MUL50,
23 divp: Some(2), 23 divp: Some(PllDiv::DIV2),
24 divq: Some(8), // 100mhz 24 divq: Some(PllDiv::DIV8), // 100mhz
25 divr: None, 25 divr: None,
26 }); 26 });
27 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 27 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
@@ -212,6 +212,6 @@ async fn main(_spawner: Spawner) {
212 info!("Assertions succeeded."); 212 info!("Assertions succeeded.");
213 213
214 loop { 214 loop {
215 Timer::after(Duration::from_millis(1000)).await; 215 Timer::after_millis(1000).await;
216 } 216 }
217} 217}
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
index c2979c59b..9aa0ca08b 100644
--- a/examples/stm32h7/src/bin/i2c.rs
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -4,10 +4,9 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; 7use embassy_stm32::i2c::{Error, I2c};
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, i2c, peripherals}; 9use embassy_stm32::{bind_interrupts, i2c, peripherals};
10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
13const ADDRESS: u8 = 0x5F; 12const ADDRESS: u8 = 0x5F;
@@ -33,13 +32,9 @@ async fn main(_spawner: Spawner) {
33 Default::default(), 32 Default::default(),
34 ); 33 );
35 34
36 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
37 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
38 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
39
40 let mut data = [0u8; 1]; 35 let mut data = [0u8; 1];
41 36
42 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { 37 match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
43 Ok(()) => info!("Whoami: {}", data[0]), 38 Ok(()) => info!("Whoami: {}", data[0]),
44 Err(Error::Timeout) => error!("Operation timed out"), 39 Err(Error::Timeout) => error!("Operation timed out"),
45 Err(e) => error!("I2c Error: {:?}", e), 40 Err(e) => error!("I2c Error: {:?}", e),
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index a1e955c39..0355ac073 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -9,7 +9,7 @@ use embassy_stm32::gpio::Speed;
9use embassy_stm32::time::{khz, Hertz}; 9use embassy_stm32::time::{khz, Hertz};
10use embassy_stm32::timer::*; 10use embassy_stm32::timer::*;
11use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; 11use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
@@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) {
22 config.rcc.hsi48 = true; // needed for RNG 22 config.rcc.hsi48 = true; // needed for RNG
23 config.rcc.pll_src = PllSource::Hsi; 23 config.rcc.pll_src = PllSource::Hsi;
24 config.rcc.pll1 = Some(Pll { 24 config.rcc.pll1 = Some(Pll {
25 prediv: 4, 25 prediv: PllPreDiv::DIV4,
26 mul: 50, 26 mul: PllMul::MUL50,
27 divp: Some(2), 27 divp: Some(PllDiv::DIV2),
28 divq: Some(8), // 100 Mhz 28 divq: Some(PllDiv::DIV8), // 100mhz
29 divr: None, 29 divr: None,
30 }); 30 });
31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
@@ -49,13 +49,13 @@ async fn main(_spawner: Spawner) {
49 49
50 loop { 50 loop {
51 pwm.set_duty(Channel::Ch1, 0); 51 pwm.set_duty(Channel::Ch1, 0);
52 Timer::after(Duration::from_millis(300)).await; 52 Timer::after_millis(300).await;
53 pwm.set_duty(Channel::Ch1, max / 4); 53 pwm.set_duty(Channel::Ch1, max / 4);
54 Timer::after(Duration::from_millis(300)).await; 54 Timer::after_millis(300).await;
55 pwm.set_duty(Channel::Ch1, max / 2); 55 pwm.set_duty(Channel::Ch1, max / 2);
56 Timer::after(Duration::from_millis(300)).await; 56 Timer::after_millis(300).await;
57 pwm.set_duty(Channel::Ch1, max - 1); 57 pwm.set_duty(Channel::Ch1, max - 1);
58 Timer::after(Duration::from_millis(300)).await; 58 Timer::after_millis(300).await;
59 } 59 }
60} 60}
61pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { 61pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> {
@@ -73,8 +73,7 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
73 ) -> Self { 73 ) -> Self {
74 into_ref!(tim, ch1, ch2, ch3, ch4); 74 into_ref!(tim, ch1, ch2, ch3, ch4);
75 75
76 T::enable(); 76 T::enable_and_reset();
77 <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset();
78 77
79 ch1.set_speed(Speed::VeryHigh); 78 ch1.set_speed(Speed::VeryHigh);
80 ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); 79 ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull);
diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs
index 9d6d805ae..c023f4584 100644
--- a/examples/stm32h7/src/bin/mco.rs
+++ b/examples/stm32h7/src/bin/mco.rs
@@ -5,8 +5,8 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::rcc::{Mco, Mco1Source}; 8use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -16,15 +16,15 @@ async fn main(_spawner: Spawner) {
16 16
17 let mut led = Output::new(p.PB14, Level::High, Speed::Low); 17 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
18 18
19 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 8); 19 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8);
20 20
21 loop { 21 loop {
22 info!("high"); 22 info!("high");
23 led.set_high(); 23 led.set_high();
24 Timer::after(Duration::from_millis(500)).await; 24 Timer::after_millis(500).await;
25 25
26 info!("low"); 26 info!("low");
27 led.set_low(); 27 led.set_low();
28 Timer::after(Duration::from_millis(500)).await; 28 Timer::after_millis(500).await;
29 } 29 }
30} 30}
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index 84e7df267..973a10cdd 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -9,7 +9,7 @@ use embassy_stm32::time::khz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_stm32::timer::Channel; 10use embassy_stm32::timer::Channel;
11use embassy_stm32::Config; 11use embassy_stm32::Config;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
@@ -21,9 +21,9 @@ async fn main(_spawner: Spawner) {
21 config.rcc.csi = true; 21 config.rcc.csi = true;
22 config.rcc.pll_src = PllSource::Hsi; 22 config.rcc.pll_src = PllSource::Hsi;
23 config.rcc.pll1 = Some(Pll { 23 config.rcc.pll1 = Some(Pll {
24 prediv: 4, 24 prediv: PllPreDiv::DIV4,
25 mul: 50, 25 mul: PllMul::MUL50,
26 divp: Some(2), 26 divp: Some(PllDiv::DIV2),
27 divq: None, 27 divq: None,
28 divr: None, 28 divr: None,
29 }); 29 });
@@ -48,12 +48,12 @@ async fn main(_spawner: Spawner) {
48 48
49 loop { 49 loop {
50 pwm.set_duty(Channel::Ch1, 0); 50 pwm.set_duty(Channel::Ch1, 0);
51 Timer::after(Duration::from_millis(300)).await; 51 Timer::after_millis(300).await;
52 pwm.set_duty(Channel::Ch1, max / 4); 52 pwm.set_duty(Channel::Ch1, max / 4);
53 Timer::after(Duration::from_millis(300)).await; 53 Timer::after_millis(300).await;
54 pwm.set_duty(Channel::Ch1, max / 2); 54 pwm.set_duty(Channel::Ch1, max / 2);
55 Timer::after(Duration::from_millis(300)).await; 55 Timer::after_millis(300).await;
56 pwm.set_duty(Channel::Ch1, max - 1); 56 pwm.set_duty(Channel::Ch1, max - 1);
57 Timer::after(Duration::from_millis(300)).await; 57 Timer::after_millis(300).await;
58 } 58 }
59} 59}
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs
new file mode 100644
index 000000000..78cea9c89
--- /dev/null
+++ b/examples/stm32h7/src/bin/rtc.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::Config;
11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy_executor::main]
15async fn main(_spawner: Spawner) {
16 let mut config = Config::default();
17 config.rcc.ls = LsConfig::default_lse();
18
19 let p = embassy_stm32::init(config);
20 info!("Hello World!");
21
22 let now = NaiveDate::from_ymd_opt(2020, 5, 15)
23 .unwrap()
24 .and_hms_opt(10, 30, 15)
25 .unwrap();
26
27 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
28 info!("Got RTC! {:?}", now.timestamp());
29
30 rtc.set_datetime(now.into()).expect("datetime not set");
31
32 // In reality the delay would be much longer
33 Timer::after_millis(20000).await;
34
35 let then: NaiveDateTime = rtc.now().unwrap().into();
36 info!("Got RTC! {:?}", then.timestamp());
37}
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index 752aefdf7..ecb8d6542 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) -> ! {
22 config.rcc.csi = true; 22 config.rcc.csi = true;
23 config.rcc.pll_src = PllSource::Hsi; 23 config.rcc.pll_src = PllSource::Hsi;
24 config.rcc.pll1 = Some(Pll { 24 config.rcc.pll1 = Some(Pll {
25 prediv: 4, 25 prediv: PllPreDiv::DIV4,
26 mul: 50, 26 mul: PllMul::MUL50,
27 divp: Some(2), 27 divp: Some(PllDiv::DIV2),
28 divq: Some(4), // default clock chosen by SDMMCSEL. 200 Mhz 28 divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz
29 divr: None, 29 divr: None,
30 }); 30 });
31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs
index 6d7c168d5..b5f583289 100644
--- a/examples/stm32h7/src/bin/signal.rs
+++ b/examples/stm32h7/src/bin/signal.rs
@@ -6,7 +6,7 @@ use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::signal::Signal; 8use embassy_sync::signal::Signal;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new(); 12static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new();
@@ -16,7 +16,7 @@ async fn my_sending_task() {
16 let mut counter: u32 = 0; 16 let mut counter: u32 = 0;
17 17
18 loop { 18 loop {
19 Timer::after(Duration::from_secs(1)).await; 19 Timer::after_secs(1).await;
20 20
21 SIGNAL.signal(counter); 21 SIGNAL.signal(counter);
22 22
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index 9fe46f031..f128d4a56 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -44,10 +44,10 @@ fn main() -> ! {
44 config.rcc.csi = true; 44 config.rcc.csi = true;
45 config.rcc.pll_src = PllSource::Hsi; 45 config.rcc.pll_src = PllSource::Hsi;
46 config.rcc.pll1 = Some(Pll { 46 config.rcc.pll1 = Some(Pll {
47 prediv: 4, 47 prediv: PllPreDiv::DIV4,
48 mul: 50, 48 mul: PllMul::MUL50,
49 divp: Some(2), 49 divp: Some(PllDiv::DIV2),
50 divq: Some(4), // used by SPI3. 100Mhz. 50 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
51 divr: None, 51 divr: None,
52 }); 52 });
53 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 53 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 88d65d5be..d4c0bcdbd 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -40,10 +40,10 @@ fn main() -> ! {
40 config.rcc.csi = true; 40 config.rcc.csi = true;
41 config.rcc.pll_src = PllSource::Hsi; 41 config.rcc.pll_src = PllSource::Hsi;
42 config.rcc.pll1 = Some(Pll { 42 config.rcc.pll1 = Some(Pll {
43 prediv: 4, 43 prediv: PllPreDiv::DIV4,
44 mul: 50, 44 mul: PllMul::MUL50,
45 divp: Some(2), 45 divp: Some(PllDiv::DIV2),
46 divq: Some(4), // used by SPI3. 100Mhz. 46 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
47 divr: None, 47 divr: None,
48 }); 48 });
49 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 49 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index 14de43568..c1e5144be 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -28,9 +28,9 @@ async fn main(_spawner: Spawner) {
28 config.rcc.hsi48 = true; // needed for USB 28 config.rcc.hsi48 = true; // needed for USB
29 config.rcc.pll_src = PllSource::Hsi; 29 config.rcc.pll_src = PllSource::Hsi;
30 config.rcc.pll1 = Some(Pll { 30 config.rcc.pll1 = Some(Pll {
31 prediv: 4, 31 prediv: PllPreDiv::DIV4,
32 mul: 50, 32 mul: PllMul::MUL50,
33 divp: Some(2), 33 divp: Some(PllDiv::DIV2),
34 divq: None, 34 divq: None,
35 divr: None, 35 divr: None,
36 }); 36 });
diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs
index 9181dfd67..76fd9dfc0 100644
--- a/examples/stm32h7/src/bin/wdg.rs
+++ b/examples/stm32h7/src/bin/wdg.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::wdg::IndependentWatchdog; 7use embassy_stm32::wdg::IndependentWatchdog;
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) {
18 wdg.unleash(); 18 wdg.unleash();
19 19
20 loop { 20 loop {
21 Timer::after(Duration::from_secs(1)).await; 21 Timer::after_secs(1).await;
22 wdg.pet(); 22 wdg.pet();
23 } 23 }
24} 24}
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 502ebfc8d..03b6d600b 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -14,7 +14,7 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab
14embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 14embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
15embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 15embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
16embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 16embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
17embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 17embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
18embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } 18embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true }
19lora-phy = { version = "2", optional = true } 19lora-phy = { version = "2", optional = true }
20lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"], optional = true } 20lorawan-device = { version = "0.11.0", default-features = false, features = ["async", "external-lora-phy"], optional = true }
@@ -24,8 +24,8 @@ defmt = "0.3"
24defmt-rtt = "0.4" 24defmt-rtt = "0.4"
25 25
26embedded-storage = "0.3.0" 26embedded-storage = "0.3.0"
27embedded-io = { version = "0.5.0" } 27embedded-io = { version = "0.6.0" }
28embedded-io-async = { version = "0.5.0", optional = true } 28embedded-io-async = { version = "0.6.0", optional = true }
29 29
30cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 30cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
31cortex-m-rt = "0.7.0" 31cortex-m-rt = "0.7.0"
diff --git a/examples/stm32l0/src/bin/blinky.rs b/examples/stm32l0/src/bin/blinky.rs
index 07fad07c6..ea40bfc48 100644
--- a/examples/stm32l0/src/bin/blinky.rs
+++ b/examples/stm32l0/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(300)).await; 21 Timer::after_millis(300).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs
index 900848fd8..987cdba01 100644
--- a/examples/stm32l0/src/bin/lora_cad.rs
+++ b/examples/stm32l0/src/bin/lora_cad.rs
@@ -12,7 +12,7 @@ use embassy_stm32::exti::{Channel, ExtiInput};
12use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed}; 12use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed};
13use embassy_stm32::spi; 13use embassy_stm32::spi;
14use embassy_stm32::time::khz; 14use embassy_stm32::time::khz;
15use embassy_time::{Delay, Duration, Timer}; 15use embassy_time::{Delay, Timer};
16use lora_phy::mod_params::*; 16use lora_phy::mod_params::*;
17use lora_phy::sx1276_7_8_9::SX1276_7_8_9; 17use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
18use lora_phy::LoRa; 18use lora_phy::LoRa;
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low); 55 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low);
56 56
57 start_indicator.set_high(); 57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await; 58 Timer::after_secs(5).await;
59 start_indicator.set_low(); 59 start_indicator.set_low();
60 60
61 let mdltn_params = { 61 let mdltn_params = {
@@ -89,7 +89,7 @@ async fn main(_spawner: Spawner) {
89 info!("cad successful without activity detected") 89 info!("cad successful without activity detected")
90 } 90 }
91 debug_indicator.set_high(); 91 debug_indicator.set_high();
92 Timer::after(Duration::from_secs(5)).await; 92 Timer::after_secs(5).await;
93 debug_indicator.set_low(); 93 debug_indicator.set_low();
94 } 94 }
95 Err(err) => info!("cad unsuccessful = {}", err), 95 Err(err) => info!("cad unsuccessful = {}", err),
diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
index edd14bb81..06e2744a4 100644
--- a/examples/stm32l0/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -12,7 +12,7 @@ use embassy_stm32::exti::{Channel, ExtiInput};
12use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed}; 12use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed};
13use embassy_stm32::spi; 13use embassy_stm32::spi;
14use embassy_stm32::time::khz; 14use embassy_stm32::time::khz;
15use embassy_time::{Delay, Duration, Timer}; 15use embassy_time::{Delay, Timer};
16use lora_phy::mod_params::*; 16use lora_phy::mod_params::*;
17use lora_phy::sx1276_7_8_9::SX1276_7_8_9; 17use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
18use lora_phy::LoRa; 18use lora_phy::LoRa;
@@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
55 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low); 55 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low);
56 56
57 start_indicator.set_high(); 57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await; 58 Timer::after_secs(5).await;
59 start_indicator.set_low(); 59 start_indicator.set_low();
60 60
61 let mut receiving_buffer = [00u8; 100]; 61 let mut receiving_buffer = [00u8; 100];
@@ -107,7 +107,7 @@ async fn main(_spawner: Spawner) {
107 { 107 {
108 info!("rx successful"); 108 info!("rx successful");
109 debug_indicator.set_high(); 109 debug_indicator.set_high();
110 Timer::after(Duration::from_secs(5)).await; 110 Timer::after_secs(5).await;
111 debug_indicator.set_low(); 111 debug_indicator.set_low();
112 } else { 112 } else {
113 info!("rx unknown packet"); 113 info!("rx unknown packet");
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs
index edc17304a..29c7e0dc7 100644
--- a/examples/stm32l0/src/bin/raw_spawn.rs
+++ b/examples/stm32l0/src/bin/raw_spawn.rs
@@ -7,21 +7,21 @@ use cortex_m_rt::entry;
7use defmt::*; 7use defmt::*;
8use embassy_executor::raw::TaskStorage; 8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14async fn run1() { 14async fn run1() {
15 loop { 15 loop {
16 info!("BIG INFREQUENT TICK"); 16 info!("BIG INFREQUENT TICK");
17 Timer::after(Duration::from_ticks(64000)).await; 17 Timer::after_ticks(64000).await;
18 } 18 }
19} 19}
20 20
21async fn run2() { 21async fn run2() {
22 loop { 22 loop {
23 info!("tick"); 23 info!("tick");
24 Timer::after(Duration::from_ticks(13000)).await; 24 Timer::after_ticks(13000).await;
25 } 25 }
26} 26}
27 27
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index a75275a0b..70058d49b 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 8embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 9embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
10embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
12 12
13defmt = "0.3" 13defmt = "0.3"
diff --git a/examples/stm32l1/src/bin/blinky.rs b/examples/stm32l1/src/bin/blinky.rs
index 8a345d235..06f732eb7 100644
--- a/examples/stm32l1/src/bin/blinky.rs
+++ b/examples/stm32l1/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(1000)).await; 21 Timer::after_millis(1000).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(1000)).await; 25 Timer::after_millis(1000).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 59e89c537..b420ad563 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -9,14 +9,14 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "unstable-traits", "nightly"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "unstable-traits", "nightly"] }
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"] }
15embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" } 15embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" }
16embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "udp", "tcp", "dhcpv4", "medium-ethernet"] } 16embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "udp", "tcp", "dhcpv4", "medium-ethernet"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18embedded-io-async = { version = "0.5.0", features = ["defmt-03"] } 18embedded-io-async = { version = "0.6.0", features = ["defmt-03"] }
19embedded-io = { version = "0.5.0", features = ["defmt-03"] } 19embedded-io = { version = "0.6.0", features = ["defmt-03"] }
20 20
21defmt = "0.3" 21defmt = "0.3"
22defmt-rtt = "0.4" 22defmt-rtt = "0.4"
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs
index 1771e5202..a0ec5c33e 100644
--- a/examples/stm32l4/src/bin/adc.rs
+++ b/examples/stm32l4/src/bin/adc.rs
@@ -13,7 +13,7 @@ fn main() -> ! {
13 info!("Hello World!"); 13 info!("Hello World!");
14 14
15 pac::RCC.ccipr().modify(|w| { 15 pac::RCC.ccipr().modify(|w| {
16 w.set_adcsel(0b11); 16 w.set_adcsel(pac::rcc::vals::Adcsel::SYS);
17 }); 17 });
18 pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); 18 pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
19 19
diff --git a/examples/stm32l4/src/bin/blinky.rs b/examples/stm32l4/src/bin/blinky.rs
index 033292fff..6202fe2f7 100644
--- a/examples/stm32l4/src/bin/blinky.rs
+++ b/examples/stm32l4/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -17,8 +17,8 @@ async fn main(_spawner: Spawner) {
17 17
18 loop { 18 loop {
19 led.set_high(); 19 led.set_high();
20 Timer::after(Duration::from_millis(300)).await; 20 Timer::after_millis(300).await;
21 led.set_low(); 21 led.set_low();
22 Timer::after(Duration::from_millis(300)).await; 22 Timer::after_millis(300).await;
23 } 23 }
24} 24}
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index c27cc03e1..98f37f906 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -51,7 +51,7 @@ async fn dac_task1(mut dac: Dac1Type) {
51 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap(); 51 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap();
52 dac.enable_channel().unwrap(); 52 dac.enable_channel().unwrap();
53 53
54 TIM6::enable(); 54 TIM6::enable_and_reset();
55 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); 55 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
56 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 56 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
57 TIM6::regs().cr1().modify(|w| { 57 TIM6::regs().cr1().modify(|w| {
@@ -90,7 +90,7 @@ async fn dac_task2(mut dac: Dac2Type) {
90 error!("Reload value {} below threshold!", reload); 90 error!("Reload value {} below threshold!", reload);
91 } 91 }
92 92
93 TIM7::enable(); 93 TIM7::enable_and_reset();
94 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); 94 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
95 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); 95 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
96 TIM7::regs().cr1().modify(|w| { 96 TIM7::regs().cr1().modify(|w| {
diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs
index dea0c66e0..504879887 100644
--- a/examples/stm32l4/src/bin/mco.rs
+++ b/examples/stm32l4/src/bin/mco.rs
@@ -5,8 +5,8 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; 8use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -14,14 +14,14 @@ async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let _mco = Mco::new(p.MCO, p.PA8, Mco1Source::Hsi16, McoClock::DIV1); 17 let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI, McoPrescaler::DIV1);
18 18
19 let mut led = Output::new(p.PB14, Level::High, Speed::Low); 19 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
20 20
21 loop { 21 loop {
22 led.set_high(); 22 led.set_high();
23 Timer::after(Duration::from_millis(300)).await; 23 Timer::after_millis(300).await;
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(300)).await; 25 Timer::after_millis(300).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs
index 806e49f59..d8a4e825f 100644
--- a/examples/stm32l4/src/bin/rng.rs
+++ b/examples/stm32l4/src/bin/rng.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 7use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv};
8use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
9use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -16,14 +16,16 @@ bind_interrupts!(struct Irqs {
16#[embassy_executor::main] 16#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let mut config = Config::default(); 18 let mut config = Config::default();
19 // 72Mhz clock (16 / 1 * 18 / 4) 19 config.rcc.mux = ClockSrc::PLL1_R;
20 config.rcc.mux = ClockSrc::PLL( 20 config.rcc.hsi16 = true;
21 PLLSource::HSI16, 21 config.rcc.pll = Some(Pll {
22 PLLClkDiv::Div4, 22 source: PLLSource::HSI,
23 PLLSrcDiv::Div1, 23 prediv: PllPreDiv::DIV1,
24 PLLMul::Mul18, 24 mul: PllMul::MUL18,
25 Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) 25 divp: None,
26 ); 26 divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
27 divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
28 });
27 let p = embassy_stm32::init(config); 29 let p = embassy_stm32::init(config);
28 30
29 info!("Hello World!"); 31 info!("Hello World!");
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index eb1eed012..fec0a349d 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -5,28 +5,29 @@
5use chrono::{NaiveDate, NaiveDateTime}; 5use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rcc::{self, ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 8use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::time::Hertz; 10use embassy_stm32::time::Hertz;
11use embassy_stm32::Config; 11use embassy_stm32::Config;
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15#[embassy_executor::main] 15#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
17 let p = { 17 let mut config = Config::default();
18 let mut config = Config::default(); 18 config.rcc.mux = ClockSrc::PLL1_R;
19 config.rcc.mux = ClockSrc::PLL( 19 config.rcc.hse = Some(Hertz::mhz(8));
20 PLLSource::HSE(Hertz::mhz(8)), 20 config.rcc.pll = Some(Pll {
21 PLLClkDiv::Div2, 21 source: PLLSource::HSE,
22 PLLSrcDiv::Div1, 22 prediv: PllPreDiv::DIV1,
23 PLLMul::Mul20, 23 mul: PllMul::MUL20,
24 None, 24 divp: None,
25 ); 25 divq: None,
26 config.rcc.lse = Some(Hertz(32_768)); 26 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
27 config.rcc.rtc_mux = rcc::RtcClockSource::LSE; 27 });
28 embassy_stm32::init(config) 28 config.rcc.ls = LsConfig::default_lse();
29 }; 29 let p = embassy_stm32::init(config);
30
30 info!("Hello World!"); 31 info!("Hello World!");
31 32
32 let now = NaiveDate::from_ymd_opt(2020, 5, 15) 33 let now = NaiveDate::from_ymd_opt(2020, 5, 15)
@@ -40,7 +41,7 @@ async fn main(_spawner: Spawner) {
40 rtc.set_datetime(now.into()).expect("datetime not set"); 41 rtc.set_datetime(now.into()).expect("datetime not set");
41 42
42 // In reality the delay would be much longer 43 // In reality the delay would be much longer
43 Timer::after(Duration::from_millis(20000)).await; 44 Timer::after_millis(20000).await;
44 45
45 let then: NaiveDateTime = rtc.now().unwrap().into(); 46 let then: NaiveDateTime = rtc.now().unwrap().into();
46 info!("Got RTC! {:?}", then.timestamp()); 47 info!("Got RTC! {:?}", then.timestamp());
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 287521582..3c9d2cfc0 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -32,7 +32,6 @@ use embedded_io::Write as bWrite;
32use embedded_io_async::Write; 32use embedded_io_async::Write;
33use hal::gpio::{Input, Level, Output, Speed}; 33use hal::gpio::{Input, Level, Output, Speed};
34use hal::i2c::{self, I2c}; 34use hal::i2c::{self, I2c};
35use hal::rcc::{self};
36use hal::rng::{self, Rng}; 35use hal::rng::{self, Rng};
37use hal::{bind_interrupts, exti, pac, peripherals}; 36use hal::{bind_interrupts, exti, pac, peripherals};
38use heapless::Vec; 37use heapless::Vec;
@@ -49,7 +48,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
49use embedded_hal_bus::spi::ExclusiveDevice; 48use embedded_hal_bus::spi::ExclusiveDevice;
50use hal::gpio::Pull; 49use hal::gpio::Pull;
51use hal::i2c::Config as I2C_Config; 50use hal::i2c::Config as I2C_Config;
52use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 51use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
53use hal::spi::{Config as SPI_Config, Spi}; 52use hal::spi::{Config as SPI_Config, Spi};
54use hal::time::Hertz; 53use hal::time::Hertz;
55 54
@@ -78,15 +77,17 @@ async fn main(spawner: Spawner) {
78 77
79 // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) 78 // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
80 // 80MHz highest frequency for flash 0 wait. 79 // 80MHz highest frequency for flash 0 wait.
81 config.rcc.mux = ClockSrc::PLL( 80 config.rcc.mux = ClockSrc::PLL1_R;
82 PLLSource::HSE(Hertz(8_000_000)), 81 config.rcc.hse = Some(Hertz::mhz(8));
83 PLLClkDiv::Div2, 82 config.rcc.pll = Some(Pll {
84 PLLSrcDiv::Div1, 83 source: PLLSource::HSE,
85 PLLMul::Mul20, 84 prediv: PllPreDiv::DIV1,
86 None, 85 mul: PllMul::MUL20,
87 ); 86 divp: None,
87 divq: None,
88 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
89 });
88 config.rcc.hsi48 = true; // needed for rng 90 config.rcc.hsi48 = true; // needed for rng
89 config.rcc.rtc_mux = rcc::RtcClockSource::LSI;
90 91
91 let dp = embassy_stm32::init(config); 92 let dp = embassy_stm32::init(config);
92 93
@@ -308,7 +309,7 @@ async fn temp_task(temp_dev_i2c: TempSensI2c, mut led: Output<'static, periphera
308 309
309 loop { 310 loop {
310 led.set_low(); 311 led.set_low();
311 match select(temp_sens.read_temp(), Timer::after(Duration::from_millis(500))).await { 312 match select(temp_sens.read_temp(), Timer::after_millis(500)).await {
312 Either::First(i2c_ret) => match i2c_ret { 313 Either::First(i2c_ret) => match i2c_ret {
313 Ok(value) => { 314 Ok(value) => {
314 led.set_high(); 315 led.set_high();
@@ -366,7 +367,7 @@ pub struct ADT7422<'d, BUS: I2cBus> {
366 bus: BUS, 367 bus: BUS,
367} 368}
368 369
369#[derive(Debug, Format)] 370#[derive(Debug, Format, PartialEq, Eq)]
370pub enum Error<I2cError: Format> { 371pub enum Error<I2cError: Format> {
371 I2c(I2cError), 372 I2c(I2cError),
372 Address, 373 Address,
@@ -426,7 +427,7 @@ where
426 // Start: One shot 427 // Start: One shot
427 let cfg = 0b01 << 5; 428 let cfg = 0b01 << 5;
428 self.write_cfg(cfg).await?; 429 self.write_cfg(cfg).await?;
429 Timer::after(Duration::from_millis(250)).await; 430 Timer::after_millis(250).await;
430 self.bus 431 self.bus
431 .write_read(self.addr, &[Registers::Temp_MSB as u8], &mut buffer) 432 .write_read(self.addr, &[Registers::Temp_MSB as u8], &mut buffer)
432 .await 433 .await
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index 410d6891b..282476547 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -23,8 +23,17 @@ async fn main(_spawner: Spawner) {
23 info!("Hello World!"); 23 info!("Hello World!");
24 24
25 let mut config = Config::default(); 25 let mut config = Config::default();
26 config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None);
27 config.rcc.hsi48 = true; 26 config.rcc.hsi48 = true;
27 config.rcc.mux = ClockSrc::PLL1_R;
28 config.rcc.hsi16 = true;
29 config.rcc.pll = Some(Pll {
30 source: PLLSource::HSI,
31 prediv: PllPreDiv::DIV1,
32 mul: PllMul::MUL10,
33 divp: None,
34 divq: None,
35 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
36 });
28 37
29 let p = embassy_stm32::init(config); 38 let p = embassy_stm32::init(config);
30 39
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 583e1a776..ecf88d7e6 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -9,9 +9,9 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", 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.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
16usbd-hid = "0.6.0" 16usbd-hid = "0.6.0"
17 17
@@ -25,7 +25,7 @@ embedded-hal = "0.2.6"
25futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 25futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
26heapless = { version = "0.7.5", default-features = false } 26heapless = { version = "0.7.5", 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.5.0" } 28embedded-io-async = { version = "0.6.0" }
29static_cell = { version = "1.1", features = ["nightly"]} 29static_cell = { version = "1.1", features = ["nightly"]}
30 30
31[profile.release] 31[profile.release]
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs
index 9549d64d8..b57f438ff 100644
--- a/examples/stm32l5/src/bin/rng.rs
+++ b/examples/stm32l5/src/bin/rng.rs
@@ -4,7 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; 7use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
8use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
9use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 9use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -16,13 +16,17 @@ bind_interrupts!(struct Irqs {
16#[embassy_executor::main] 16#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let mut config = Config::default(); 18 let mut config = Config::default();
19 config.rcc.mux = ClockSrc::PLL( 19 config.rcc.hsi16 = true;
20 PLLSource::HSI16, 20 config.rcc.mux = ClockSrc::PLL1_R;
21 PLLClkDiv::Div2, 21 config.rcc.pll = Some(Pll {
22 PLLSrcDiv::Div1, 22 // 64Mhz clock (16 / 1 * 8 / 2)
23 PLLMul::Mul8, 23 source: PLLSource::HSI,
24 Some(PLLClkDiv::Div2), 24 prediv: PllPreDiv::DIV1,
25 ); 25 mul: PllMul::MUL8,
26 divp: None,
27 divq: None,
28 divr: Some(PllRDiv::DIV2),
29 });
26 let p = embassy_stm32::init(config); 30 let p = embassy_stm32::init(config);
27 31
28 info!("Hello World!"); 32 info!("Hello World!");
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 15b84761b..bbe44642b 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -45,8 +45,17 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
45#[embassy_executor::main] 45#[embassy_executor::main]
46async fn main(spawner: Spawner) { 46async fn main(spawner: Spawner) {
47 let mut config = Config::default(); 47 let mut config = Config::default();
48 config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); 48 config.rcc.hsi16 = true;
49 config.rcc.hsi48 = true; 49 config.rcc.mux = ClockSrc::PLL1_R;
50 config.rcc.pll = Some(Pll {
51 // 80Mhz clock (16 / 1 * 10 / 2)
52 source: PLLSource::HSI,
53 prediv: PllPreDiv::DIV1,
54 mul: PllMul::MUL10,
55 divp: None,
56 divq: None,
57 divr: Some(PllRDiv::DIV2),
58 });
50 let p = embassy_stm32::init(config); 59 let p = embassy_stm32::init(config);
51 60
52 // Create the driver, from the HAL. 61 // Create the driver, from the HAL.
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index 7e894e407..44e29ee9c 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -8,7 +8,7 @@ use embassy_futures::join::join;
8use embassy_stm32::rcc::*; 8use embassy_stm32::rcc::*;
9use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
10use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 10use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 12use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
13use embassy_usb::control::OutResponse; 13use embassy_usb::control::OutResponse;
14use embassy_usb::Builder; 14use embassy_usb::Builder;
@@ -22,8 +22,17 @@ bind_interrupts!(struct Irqs {
22#[embassy_executor::main] 22#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
24 let mut config = Config::default(); 24 let mut config = Config::default();
25 config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); 25 config.rcc.hsi16 = true;
26 config.rcc.hsi48 = true; 26 config.rcc.mux = ClockSrc::PLL1_R;
27 config.rcc.pll = Some(Pll {
28 // 80Mhz clock (16 / 1 * 10 / 2)
29 source: PLLSource::HSI,
30 prediv: PllPreDiv::DIV1,
31 mul: PllMul::MUL10,
32 divp: None,
33 divq: None,
34 divr: Some(PllRDiv::DIV2),
35 });
27 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
28 37
29 // Create the driver, from the HAL. 38 // Create the driver, from the HAL.
@@ -76,7 +85,7 @@ async fn main(_spawner: Spawner) {
76 let hid_fut = async { 85 let hid_fut = async {
77 let mut y: i8 = 5; 86 let mut y: i8 = 5;
78 loop { 87 loop {
79 Timer::after(Duration::from_millis(500)).await; 88 Timer::after_millis(500).await;
80 89
81 y = -y; 90 y = -y;
82 let report = MouseReport { 91 let report = MouseReport {
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index 0c719560f..612b891ac 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -20,8 +20,17 @@ bind_interrupts!(struct Irqs {
20#[embassy_executor::main] 20#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
22 let mut config = Config::default(); 22 let mut config = Config::default();
23 config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); 23 config.rcc.hsi16 = true;
24 config.rcc.hsi48 = true; 24 config.rcc.mux = ClockSrc::PLL1_R;
25 config.rcc.pll = Some(Pll {
26 // 80Mhz clock (16 / 1 * 10 / 2)
27 source: PLLSource::HSI,
28 prediv: PllPreDiv::DIV1,
29 mul: PllMul::MUL10,
30 divp: None,
31 divq: None,
32 divr: Some(PllRDiv::DIV2),
33 });
25 let p = embassy_stm32::init(config); 34 let p = embassy_stm32::init(config);
26 35
27 info!("Hello World!"); 36 info!("Hello World!");
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index e361856c5..de60b3b19 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", 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
15defmt = "0.3" 15defmt = "0.3"
diff --git a/examples/stm32u5/src/bin/blinky.rs b/examples/stm32u5/src/bin/blinky.rs
index 976fb0b9a..4b44cb12b 100644
--- a/examples/stm32u5/src/bin/blinky.rs
+++ b/examples/stm32u5/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) -> ! {
18 loop { 18 loop {
19 defmt::info!("on!"); 19 defmt::info!("on!");
20 led.set_low(); 20 led.set_low();
21 Timer::after(Duration::from_millis(200)).await; 21 Timer::after_millis(200).await;
22 22
23 defmt::info!("off!"); 23 defmt::info!("off!");
24 led.set_high(); 24 led.set_high();
25 Timer::after(Duration::from_millis(200)).await; 25 Timer::after_millis(200).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index 9e47fb18a..9b2adb0ac 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -23,7 +23,12 @@ async fn main(_spawner: Spawner) {
23 info!("Hello World!"); 23 info!("Hello World!");
24 24
25 let mut config = Config::default(); 25 let mut config = Config::default();
26 config.rcc.mux = ClockSrc::PLL1R(PllSrc::HSI16, PllM::Div2, PllN::Mul10, PllClkDiv::NotDivided); 26 config.rcc.mux = ClockSrc::PLL1R(PllConfig {
27 source: PllSrc::HSI16,
28 m: Pllm::DIV2,
29 n: Plln::MUL10,
30 r: Plldiv::DIV1,
31 });
27 //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); 32 //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz);
28 config.rcc.hsi48 = true; 33 config.rcc.hsi48 = true;
29 34
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 320678ddc..fa2cc63fa 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -10,8 +10,8 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["
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.3.0", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
13embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true } 14embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true }
15 15
16defmt = "0.3" 16defmt = "0.3"
17defmt-rtt = "0.4" 17defmt-rtt = "0.4"
diff --git a/examples/stm32wb/src/bin/blinky.rs b/examples/stm32wb/src/bin/blinky.rs
index f9bf90d2e..1394f03fa 100644
--- a/examples/stm32wb/src/bin/blinky.rs
+++ b/examples/stm32wb/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(500)).await; 25 Timer::after_millis(500).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 2f53f5df8..9d0e0070c 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -8,7 +8,7 @@ use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32::rcc::WPAN_DEFAULT; 9use embassy_stm32::rcc::WPAN_DEFAULT;
10use embassy_stm32_wpan::TlMbox; 10use embassy_stm32_wpan::TlMbox;
11use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs{ 14bind_interrupts!(struct Irqs{
@@ -71,7 +71,7 @@ async fn main(_spawner: Spawner) {
71 } 71 }
72 } 72 }
73 73
74 Timer::after(Duration::from_millis(50)).await; 74 Timer::after_millis(50).await;
75 } 75 }
76 76
77 info!("Test OK"); 77 info!("Test OK");
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml
index 26fcce26b..68ab5a468 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0"
8embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] } 8embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] }
9embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 10embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
11embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 11embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
12embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true } 12embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", "nightly"], optional=true }
13 13
14defmt = "0.3" 14defmt = "0.3"
15defmt-rtt = "0.4" 15defmt-rtt = "0.4"
diff --git a/examples/stm32wba/src/bin/blinky.rs b/examples/stm32wba/src/bin/blinky.rs
index 530746296..6b9635e66 100644
--- a/examples/stm32wba/src/bin/blinky.rs
+++ b/examples/stm32wba/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(500)).await; 25 Timer::after_millis(500).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index f47a9a906..6a338af40 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } 9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["nightly", "unstable-traits", "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-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } 14embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
15lora-phy = { version = "2" } 15lora-phy = { version = "2" }
diff --git a/examples/stm32wl/src/bin/blinky.rs b/examples/stm32wl/src/bin/blinky.rs
index 6af5099ce..5bd5745f0 100644
--- a/examples/stm32wl/src/bin/blinky.rs
+++ b/examples/stm32wl/src/bin/blinky.rs
@@ -5,7 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_time::{Duration, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 loop { 18 loop {
19 info!("high"); 19 info!("high");
20 led.set_high(); 20 led.set_high();
21 Timer::after(Duration::from_millis(500)).await; 21 Timer::after_millis(500).await;
22 22
23 info!("low"); 23 info!("low");
24 led.set_low(); 24 led.set_low();
25 Timer::after(Duration::from_millis(500)).await; 25 Timer::after_millis(500).await;
26 } 26 }
27} 27}
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index fb2495326..8c789afbc 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -33,8 +33,7 @@ bind_interrupts!(struct Irqs{
33#[embassy_executor::main] 33#[embassy_executor::main]
34async fn main(_spawner: Spawner) { 34async fn main(_spawner: Spawner) {
35 let mut config = embassy_stm32::Config::default(); 35 let mut config = embassy_stm32::Config::default();
36 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; 36 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
37 config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI;
38 let p = embassy_stm32::init(config); 37 let p = embassy_stm32::init(config);
39 38
40 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); 39 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs
index 3d8c31ff3..be33f39c1 100644
--- a/examples/stm32wl/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs
@@ -11,7 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_stm32::bind_interrupts; 11use embassy_stm32::bind_interrupts;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::spi::Spi; 13use embassy_stm32::spi::Spi;
14use embassy_time::{Delay, Duration, Timer}; 14use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
@@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{
26#[embassy_executor::main] 26#[embassy_executor::main]
27async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default(); 28 let mut config = embassy_stm32::Config::default();
29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; 29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
30 let p = embassy_stm32::init(config); 30 let p = embassy_stm32::init(config);
31 31
32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
@@ -51,7 +51,7 @@ async fn main(_spawner: Spawner) {
51 let mut start_indicator = Output::new(p.PB15, Level::Low, Speed::Low); 51 let mut start_indicator = Output::new(p.PB15, Level::Low, Speed::Low);
52 52
53 start_indicator.set_high(); 53 start_indicator.set_high();
54 Timer::after(Duration::from_secs(5)).await; 54 Timer::after_secs(5).await;
55 start_indicator.set_low(); 55 start_indicator.set_low();
56 56
57 let mut receiving_buffer = [00u8; 100]; 57 let mut receiving_buffer = [00u8; 100];
@@ -103,7 +103,7 @@ async fn main(_spawner: Spawner) {
103 { 103 {
104 info!("rx successful"); 104 info!("rx successful");
105 debug_indicator.set_high(); 105 debug_indicator.set_high();
106 Timer::after(Duration::from_secs(5)).await; 106 Timer::after_secs(5).await;
107 debug_indicator.set_low(); 107 debug_indicator.set_low();
108 } else { 108 } else {
109 info!("rx unknown packet"); 109 info!("rx unknown packet");
diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs
index fbd0b0320..85f6a84b7 100644
--- a/examples/stm32wl/src/bin/lora_p2p_send.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_send.rs
@@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{
26#[embassy_executor::main] 26#[embassy_executor::main]
27async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default(); 28 let mut config = embassy_stm32::Config::default();
29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; 29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
30 let p = embassy_stm32::init(config); 30 let p = embassy_stm32::init(config);
31 31
32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 18eeac4fa..70676c704 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -4,6 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, MSIRange};
7use embassy_stm32::rng::{self, Rng}; 8use embassy_stm32::rng::{self, Rng};
8use embassy_stm32::{bind_interrupts, pac, peripherals}; 9use embassy_stm32::{bind_interrupts, pac, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -15,13 +16,10 @@ bind_interrupts!(struct Irqs{
15#[embassy_executor::main] 16#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
17 let mut config = embassy_stm32::Config::default(); 18 let mut config = embassy_stm32::Config::default();
18 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; 19 config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
19 config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI;
20
21 let p = embassy_stm32::init(config); 20 let p = embassy_stm32::init(config);
22 pac::RCC.ccipr().modify(|w| { 21
23 w.set_rngsel(0b01); 22 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b11)); // msi
24 });
25 23
26 info!("Hello World!"); 24 info!("Hello World!");
27 25
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index 11734e4b6..9ebb05f22 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -5,20 +5,18 @@
5use chrono::{NaiveDate, NaiveDateTime}; 5use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rcc::ClockSrc; 8use embassy_stm32::rcc::{ClockSrc, LsConfig};
9use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::time::Hertz;
11use embassy_stm32::Config; 10use embassy_stm32::Config;
12use embassy_time::{Duration, Timer}; 11use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
14 13
15#[embassy_executor::main] 14#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
17 let p = { 16 let p = {
18 let mut config = Config::default(); 17 let mut config = Config::default();
19 config.rcc.mux = ClockSrc::HSE32; 18 config.rcc.mux = ClockSrc::HSE;
20 config.rcc.lse = Some(Hertz(32_768)); 19 config.rcc.ls = LsConfig::default_lse();
21 config.rcc.rtc_mux = RtcClockSource::LSE;
22 embassy_stm32::init(config) 20 embassy_stm32::init(config)
23 }; 21 };
24 info!("Hello World!"); 22 info!("Hello World!");
@@ -34,7 +32,7 @@ async fn main(_spawner: Spawner) {
34 rtc.set_datetime(now.into()).expect("datetime not set"); 32 rtc.set_datetime(now.into()).expect("datetime not set");
35 33
36 // In reality the delay would be much longer 34 // In reality the delay would be much longer
37 Timer::after(Duration::from_millis(20000)).await; 35 Timer::after_millis(20000).await;
38 36
39 let then: NaiveDateTime = rtc.now().unwrap().into(); 37 let then: NaiveDateTime = rtc.now().unwrap().into();
40 info!("Got RTC! {:?}", then.timestamp()); 38 info!("Got RTC! {:?}", then.timestamp());
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs
index 2c9b7c691..44e8f83a2 100644
--- a/examples/stm32wl/src/bin/uart_async.rs
+++ b/examples/stm32wl/src/bin/uart_async.rs
@@ -21,7 +21,7 @@ but can be surely changed for your needs.
21#[embassy_executor::main] 21#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
23 let mut config = embassy_stm32::Config::default(); 23 let mut config = embassy_stm32::Config::default();
24 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; 24 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
25 let p = embassy_stm32::init(config); 25 let p = embassy_stm32::init(config);
26 26
27 defmt::info!("Starting system"); 27 defmt::info!("Starting system");
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index 12b2e2bd4..29339295a 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -10,7 +10,7 @@ crate-type = ["cdylib"]
10[dependencies] 10[dependencies]
11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["log"] } 11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["log"] }
12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } 12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] }
13embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } 13embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["log", "wasm", "nightly"] }
14 14
15wasm-logger = "0.2.0" 15wasm-logger = "0.2.0"
16wasm-bindgen = "0.2" 16wasm-bindgen = "0.2"
diff --git a/examples/wasm/src/lib.rs b/examples/wasm/src/lib.rs
index edfe8bafc..1141096fb 100644
--- a/examples/wasm/src/lib.rs
+++ b/examples/wasm/src/lib.rs
@@ -1,7 +1,7 @@
1#![feature(type_alias_impl_trait)] 1#![feature(type_alias_impl_trait)]
2 2
3use embassy_executor::Spawner; 3use embassy_executor::Spawner;
4use embassy_time::{Duration, Timer}; 4use embassy_time::Timer;
5 5
6#[embassy_executor::task] 6#[embassy_executor::task]
7async fn ticker() { 7async fn ticker() {
@@ -19,7 +19,7 @@ async fn ticker() {
19 log::info!("tick {}", counter); 19 log::info!("tick {}", counter);
20 counter += 1; 20 counter += 1;
21 21
22 Timer::after(Duration::from_secs(1)).await; 22 Timer::after_secs(1).await;
23 } 23 }
24} 24}
25 25
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 7b34afa2b..755a92075 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,8 +1,8 @@
1# Before upgrading check that everything is available on all tier1 targets here: 1# Before upgrading check that everything is available on all tier1 targets here:
2# https://rust-lang.github.io/rustup-components-history 2# https://rust-lang.github.io/rustup-components-history
3[toolchain] 3[toolchain]
4channel = "nightly-2023-08-19" 4channel = "nightly-2023-10-02"
5components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] 5components = [ "rust-src", "rustfmt", "llvm-tools" ]
6targets = [ 6targets = [
7 "thumbv7em-none-eabi", 7 "thumbv7em-none-eabi",
8 "thumbv7m-none-eabi", 8 "thumbv7m-none-eabi",
diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml
index 08fe1a4b5..96a5871e3 100644
--- a/tests/nrf/Cargo.toml
+++ b/tests/nrf/Cargo.toml
@@ -10,10 +10,10 @@ teleprobe-meta = "1"
10embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 10embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt", "nightly"] } 11embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt", "nightly"] }
12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } 12embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] }
13embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] }
14embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 14embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
15embedded-io-async = { version = "0.5.0" } 15embedded-io-async = { version = "0.6.0" }
16embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } 16embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] }
17embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } 17embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] }
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.1" } 19embedded-hal-async = { version = "1.0.0-rc.1" }
diff --git a/tests/nrf/src/bin/buffered_uart_spam.rs b/tests/nrf/src/bin/buffered_uart_spam.rs
index 8abeae6d4..65b9d76d1 100644
--- a/tests/nrf/src/bin/buffered_uart_spam.rs
+++ b/tests/nrf/src/bin/buffered_uart_spam.rs
@@ -13,7 +13,7 @@ use embassy_nrf::gpio::{Level, Output, OutputDrive};
13use embassy_nrf::ppi::{Event, Ppi, Task}; 13use embassy_nrf::ppi::{Event, Ppi, Task};
14use embassy_nrf::uarte::Uarte; 14use embassy_nrf::uarte::Uarte;
15use embassy_nrf::{bind_interrupts, pac, peripherals, uarte}; 15use embassy_nrf::{bind_interrupts, pac, peripherals, uarte};
16use embassy_time::{Duration, Timer}; 16use embassy_time::Timer;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) {
50 info!("uarte initialized!"); 50 info!("uarte initialized!");
51 51
52 // uarte needs some quiet time to start rxing properly. 52 // uarte needs some quiet time to start rxing properly.
53 Timer::after(Duration::from_millis(10)).await; 53 Timer::after_millis(10).await;
54 54
55 // Tx spam in a loop. 55 // Tx spam in a loop.
56 const NSPAM: usize = 17; 56 const NSPAM: usize = 17;
diff --git a/tests/nrf/src/bin/timer.rs b/tests/nrf/src/bin/timer.rs
index c00f35fd1..5723acb01 100644
--- a/tests/nrf/src/bin/timer.rs
+++ b/tests/nrf/src/bin/timer.rs
@@ -5,7 +5,7 @@ teleprobe_meta::target!(b"nrf52840-dk");
5 5
6use defmt::{assert, info}; 6use defmt::{assert, info};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_time::{Duration, Instant, Timer}; 8use embassy_time::{Instant, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
14 info!("Hello World!"); 14 info!("Hello World!");
15 15
16 let start = Instant::now(); 16 let start = Instant::now();
17 Timer::after(Duration::from_millis(100)).await; 17 Timer::after_millis(100).await;
18 let end = Instant::now(); 18 let end = Instant::now();
19 let ms = (end - start).as_millis(); 19 let ms = (end - start).as_millis();
20 info!("slept for {} ms", ms); 20 info!("slept for {} ms", ms);
diff --git a/tests/perf-client/Cargo.toml b/tests/perf-client/Cargo.toml
index 3284664d9..bab5ac492 100644
--- a/tests/perf-client/Cargo.toml
+++ b/tests/perf-client/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 7
8[dependencies] 8[dependencies]
9embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] } 9embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4"] }
10embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits"] } 10embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits"] }
11embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 11embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
12defmt = "0.3.0" 12defmt = "0.3.0"
diff --git a/tests/perf-client/src/lib.rs b/tests/perf-client/src/lib.rs
index a36147dbb..54762379a 100644
--- a/tests/perf-client/src/lib.rs
+++ b/tests/perf-client/src/lib.rs
@@ -16,7 +16,7 @@ pub struct Expected {
16pub async fn run<D: Driver>(stack: &Stack<D>, expected: Expected) { 16pub async fn run<D: Driver>(stack: &Stack<D>, expected: Expected) {
17 info!("Waiting for DHCP up..."); 17 info!("Waiting for DHCP up...");
18 while stack.config_v4().is_none() { 18 while stack.config_v4().is_none() {
19 Timer::after(Duration::from_millis(100)).await; 19 Timer::after_millis(100).await;
20 } 20 }
21 info!("IP addressing up!"); 21 info!("IP addressing up!");
22 22
@@ -30,6 +30,7 @@ pub async fn run<D: Driver>(stack: &Stack<D>, expected: Expected) {
30} 30}
31 31
32const TEST_DURATION: usize = 10; 32const TEST_DURATION: usize = 10;
33const IO_BUFFER_SIZE: usize = 1024;
33const RX_BUFFER_SIZE: usize = 4096; 34const RX_BUFFER_SIZE: usize = 4096;
34const TX_BUFFER_SIZE: usize = 4096; 35const TX_BUFFER_SIZE: usize = 4096;
35const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2); 36const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2);
@@ -52,7 +53,7 @@ async fn test_download<D: Driver>(stack: &Stack<D>) -> usize {
52 } 53 }
53 info!("connected, testing..."); 54 info!("connected, testing...");
54 55
55 let mut rx_buf = [0; 4096]; 56 let mut rx_buf = [0; IO_BUFFER_SIZE];
56 let mut total: usize = 0; 57 let mut total: usize = 0;
57 with_timeout(Duration::from_secs(TEST_DURATION as _), async { 58 with_timeout(Duration::from_secs(TEST_DURATION as _), async {
58 loop { 59 loop {
@@ -92,7 +93,7 @@ async fn test_upload<D: Driver>(stack: &Stack<D>) -> usize {
92 } 93 }
93 info!("connected, testing..."); 94 info!("connected, testing...");
94 95
95 let buf = [0; 4096]; 96 let buf = [0; IO_BUFFER_SIZE];
96 let mut total: usize = 0; 97 let mut total: usize = 0;
97 with_timeout(Duration::from_secs(TEST_DURATION as _), async { 98 with_timeout(Duration::from_secs(TEST_DURATION as _), async {
98 loop { 99 loop {
@@ -134,8 +135,8 @@ async fn test_upload_download<D: Driver>(stack: &Stack<D>) -> usize {
134 135
135 let (mut reader, mut writer) = socket.split(); 136 let (mut reader, mut writer) = socket.split();
136 137
137 let tx_buf = [0; 4096]; 138 let tx_buf = [0; IO_BUFFER_SIZE];
138 let mut rx_buf = [0; 4096]; 139 let mut rx_buf = [0; IO_BUFFER_SIZE];
139 let mut total: usize = 0; 140 let mut total: usize = 0;
140 let tx_fut = async { 141 let tx_fut = async {
141 loop { 142 loop {
diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml
index 490f037b9..3bb46d37d 100644
--- a/tests/riscv32/Cargo.toml
+++ b/tests/riscv32/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
8critical-section = { version = "1.1.1", features = ["restore-state-bool"] } 8critical-section = { version = "1.1.1", features = ["restore-state-bool"] }
9embassy-sync = { version = "0.3.0", path = "../../embassy-sync" } 9embassy-sync = { version = "0.3.0", path = "../../embassy-sync" }
10embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } 10embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] }
11embassy-time = { version = "0.1.3", path = "../../embassy-time" } 11embassy-time = { version = "0.1.5", path = "../../embassy-time" }
12embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 12embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
13 13
14riscv-rt = "0.11" 14riscv-rt = "0.11"
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 8bb0de6c6..1fb73857a 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -9,10 +9,10 @@ teleprobe-meta = "1.1"
9 9
10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits"] } 12embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
17cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] } 17cyw43 = { path = "../../cyw43", features = ["defmt", "firmware-logs"] }
18cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] } 18cyw43-pio = { path = "../../cyw43-pio", features = ["defmt", "overclock"] }
@@ -29,7 +29,7 @@ embedded-hal-async = { version = "=1.0.0-rc.1" }
29embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] } 29embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] }
30panic-probe = { version = "0.3.0", features = ["print-defmt"] } 30panic-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.5.0" } 32embedded-io-async = { version = "0.6.0" }
33embedded-storage = { version = "0.3" } 33embedded-storage = { version = "0.3" }
34static_cell = { version = "1.1", features = ["nightly"]} 34static_cell = { version = "1.1", features = ["nightly"]}
35pio = "0.2" 35pio = "0.2"
diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs
index 0250fd5f4..0c04a55f9 100644
--- a/tests/rp/src/bin/adc.rs
+++ b/tests/rp/src/bin/adc.rs
@@ -93,6 +93,7 @@ async fn main(_spawner: Spawner) {
93 adc.read_many( 93 adc.read_many(
94 &mut Channel::new_pin(&mut p.PIN_29, Pull::Down), 94 &mut Channel::new_pin(&mut p.PIN_29, Pull::Down),
95 &mut low, 95 &mut low,
96 1,
96 &mut p.DMA_CH0, 97 &mut p.DMA_CH0,
97 ) 98 )
98 .await 99 .await
@@ -100,12 +101,18 @@ async fn main(_spawner: Spawner) {
100 adc.read_many( 101 adc.read_many(
101 &mut Channel::new_pin(&mut p.PIN_29, Pull::None), 102 &mut Channel::new_pin(&mut p.PIN_29, Pull::None),
102 &mut none, 103 &mut none,
104 1,
103 &mut p.DMA_CH0, 105 &mut p.DMA_CH0,
104 ) 106 )
105 .await 107 .await
106 .unwrap(); 108 .unwrap();
107 adc.read_many_raw(&mut Channel::new_pin(&mut p.PIN_29, Pull::Up), &mut up, &mut p.DMA_CH0) 109 adc.read_many_raw(
108 .await; 110 &mut Channel::new_pin(&mut p.PIN_29, Pull::Up),
111 &mut up,
112 1,
113 &mut p.DMA_CH0,
114 )
115 .await;
109 defmt::assert!(low.iter().zip(none.iter()).all(|(l, n)| *l >> 4 < *n as u16)); 116 defmt::assert!(low.iter().zip(none.iter()).all(|(l, n)| *l >> 4 < *n as u16));
110 defmt::assert!(up.iter().all(|s| s.good())); 117 defmt::assert!(up.iter().all(|s| s.good()));
111 defmt::assert!(none.iter().zip(up.iter()).all(|(n, u)| (*n as u16) < u.value())); 118 defmt::assert!(none.iter().zip(up.iter()).all(|(n, u)| (*n as u16) < u.value()));
@@ -115,6 +122,7 @@ async fn main(_spawner: Spawner) {
115 adc.read_many( 122 adc.read_many(
116 &mut Channel::new_temp_sensor(&mut p.ADC_TEMP_SENSOR), 123 &mut Channel::new_temp_sensor(&mut p.ADC_TEMP_SENSOR),
117 &mut temp, 124 &mut temp,
125 1,
118 &mut p.DMA_CH0, 126 &mut p.DMA_CH0,
119 ) 127 )
120 .await 128 .await
diff --git a/tests/rp/src/bin/bootsel.rs b/tests/rp/src/bin/bootsel.rs
new file mode 100644
index 000000000..4678775eb
--- /dev/null
+++ b/tests/rp/src/bin/bootsel.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4teleprobe_meta::target!(b"rpi-pico");
5
6use defmt::{assert_eq, *};
7use embassy_executor::Spawner;
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut p = embassy_rp::init(Default::default());
14 info!("Hello World!");
15
16 // add some delay to give an attached debug probe time to parse the
17 // defmt RTT header. Reading that header might touch flash memory, which
18 // interferes with flash write operations.
19 // https://github.com/knurling-rs/defmt/pull/683
20 Timer::after_millis(10).await;
21
22 assert_eq!(p.BOOTSEL.is_pressed(), false);
23
24 info!("Test OK");
25 cortex_m::asm::bkpt();
26}
diff --git a/tests/rp/src/bin/flash.rs b/tests/rp/src/bin/flash.rs
index 75be2bf06..2d85135de 100644
--- a/tests/rp/src/bin/flash.rs
+++ b/tests/rp/src/bin/flash.rs
@@ -6,7 +6,7 @@ teleprobe_meta::target!(b"rpi-pico");
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE}; 8use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE};
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12const ADDR_OFFSET: u32 = 0x8000; 12const ADDR_OFFSET: u32 = 0x8000;
@@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
20 // defmt RTT header. Reading that header might touch flash memory, which 20 // defmt RTT header. Reading that header might touch flash memory, which
21 // interferes with flash write operations. 21 // interferes with flash write operations.
22 // https://github.com/knurling-rs/defmt/pull/683 22 // https://github.com/knurling-rs/defmt/pull/683
23 Timer::after(Duration::from_millis(10)).await; 23 Timer::after_millis(10).await;
24 24
25 let mut flash = embassy_rp::flash::Flash::<_, Async, { 2 * 1024 * 1024 }>::new(p.FLASH, p.DMA_CH0); 25 let mut flash = embassy_rp::flash::Flash::<_, Async, { 2 * 1024 * 1024 }>::new(p.FLASH, p.DMA_CH0);
26 26
diff --git a/tests/rp/src/bin/float.rs b/tests/rp/src/bin/float.rs
index 2874aa910..1e89c10f8 100644
--- a/tests/rp/src/bin/float.rs
+++ b/tests/rp/src/bin/float.rs
@@ -6,7 +6,7 @@ teleprobe_meta::target!(b"rpi-pico");
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_rp::pac; 8use embassy_rp::pac;
9use embassy_time::{Duration, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -40,7 +40,7 @@ async fn main(_spawner: Spawner) {
40 rad_d + PI_D, 40 rad_d + PI_D,
41 rad_d % PI_D 41 rad_d % PI_D
42 ); 42 );
43 Timer::after(Duration::from_millis(10)).await; 43 Timer::after_millis(10).await;
44 } 44 }
45 45
46 let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr(); 46 let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr();
diff --git a/tests/rp/src/bin/gpio_async.rs b/tests/rp/src/bin/gpio_async.rs
index 60c65b7a0..26582f74b 100644
--- a/tests/rp/src/bin/gpio_async.rs
+++ b/tests/rp/src/bin/gpio_async.rs
@@ -27,7 +27,7 @@ async fn main(_spawner: Spawner) {
27 27
28 let set_high_future = async { 28 let set_high_future = async {
29 // Allow time for wait_for_high_future to await wait_for_high(). 29 // Allow time for wait_for_high_future to await wait_for_high().
30 Timer::after(Duration::from_millis(10)).await; 30 Timer::after_millis(10).await;
31 output.set_high(); 31 output.set_high();
32 }; 32 };
33 let wait_for_high_future = async { 33 let wait_for_high_future = async {
@@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) {
47 assert!(input.is_high(), "input was expected to be high"); 47 assert!(input.is_high(), "input was expected to be high");
48 48
49 let set_low_future = async { 49 let set_low_future = async {
50 Timer::after(Duration::from_millis(10)).await; 50 Timer::after_millis(10).await;
51 output.set_low(); 51 output.set_low();
52 }; 52 };
53 let wait_for_low_future = async { 53 let wait_for_low_future = async {
@@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) {
67 assert!(input.is_low(), "input was expected to be low"); 67 assert!(input.is_low(), "input was expected to be low");
68 68
69 let set_high_future = async { 69 let set_high_future = async {
70 Timer::after(Duration::from_millis(10)).await; 70 Timer::after_millis(10).await;
71 output.set_high(); 71 output.set_high();
72 }; 72 };
73 let wait_for_rising_edge_future = async { 73 let wait_for_rising_edge_future = async {
@@ -87,7 +87,7 @@ async fn main(_spawner: Spawner) {
87 assert!(input.is_high(), "input was expected to be high"); 87 assert!(input.is_high(), "input was expected to be high");
88 88
89 let set_low_future = async { 89 let set_low_future = async {
90 Timer::after(Duration::from_millis(10)).await; 90 Timer::after_millis(10).await;
91 output.set_low(); 91 output.set_low();
92 }; 92 };
93 let wait_for_falling_edge_future = async { 93 let wait_for_falling_edge_future = async {
@@ -107,7 +107,7 @@ async fn main(_spawner: Spawner) {
107 assert!(input.is_high(), "input was expected to be high"); 107 assert!(input.is_high(), "input was expected to be high");
108 108
109 let set_low_future = async { 109 let set_low_future = async {
110 Timer::after(Duration::from_millis(10)).await; 110 Timer::after_millis(10).await;
111 output.set_low(); 111 output.set_low();
112 }; 112 };
113 let wait_for_any_edge_future = async { 113 let wait_for_any_edge_future = async {
@@ -127,7 +127,7 @@ async fn main(_spawner: Spawner) {
127 assert!(input.is_low(), "input was expected to be low"); 127 assert!(input.is_low(), "input was expected to be low");
128 128
129 let set_high_future = async { 129 let set_high_future = async {
130 Timer::after(Duration::from_millis(10)).await; 130 Timer::after_millis(10).await;
131 output.set_high(); 131 output.set_high();
132 }; 132 };
133 let wait_for_any_edge_future = async { 133 let wait_for_any_edge_future = async {
diff --git a/tests/rp/src/bin/pwm.rs b/tests/rp/src/bin/pwm.rs
index 8c02b8441..8c9db1158 100644
--- a/tests/rp/src/bin/pwm.rs
+++ b/tests/rp/src/bin/pwm.rs
@@ -7,7 +7,7 @@ use defmt::{assert, assert_eq, assert_ne, *};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_rp::gpio::{Input, Level, Output, Pull}; 8use embassy_rp::gpio::{Input, Level, Output, Pull};
9use embassy_rp::pwm::{Config, InputMode, Pwm}; 9use embassy_rp::pwm::{Config, InputMode, Pwm};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
@@ -48,13 +48,13 @@ async fn main(_spawner: Spawner) {
48 { 48 {
49 let pin1 = Input::new(&mut p9, Pull::None); 49 let pin1 = Input::new(&mut p9, Pull::None);
50 let _pwm = Pwm::new_output_a(&mut p.PWM_CH3, &mut p6, cfg.clone()); 50 let _pwm = Pwm::new_output_a(&mut p.PWM_CH3, &mut p6, cfg.clone());
51 Timer::after(Duration::from_millis(1)).await; 51 Timer::after_millis(1).await;
52 assert_eq!(pin1.is_low(), invert_a); 52 assert_eq!(pin1.is_low(), invert_a);
53 Timer::after(Duration::from_millis(5)).await; 53 Timer::after_millis(5).await;
54 assert_eq!(pin1.is_high(), invert_a); 54 assert_eq!(pin1.is_high(), invert_a);
55 Timer::after(Duration::from_millis(5)).await; 55 Timer::after_millis(5).await;
56 assert_eq!(pin1.is_low(), invert_a); 56 assert_eq!(pin1.is_low(), invert_a);
57 Timer::after(Duration::from_millis(5)).await; 57 Timer::after_millis(5).await;
58 assert_eq!(pin1.is_high(), invert_a); 58 assert_eq!(pin1.is_high(), invert_a);
59 } 59 }
60 60
@@ -62,13 +62,13 @@ async fn main(_spawner: Spawner) {
62 { 62 {
63 let pin2 = Input::new(&mut p11, Pull::None); 63 let pin2 = Input::new(&mut p11, Pull::None);
64 let _pwm = Pwm::new_output_b(&mut p.PWM_CH3, &mut p7, cfg.clone()); 64 let _pwm = Pwm::new_output_b(&mut p.PWM_CH3, &mut p7, cfg.clone());
65 Timer::after(Duration::from_millis(1)).await; 65 Timer::after_millis(1).await;
66 assert_ne!(pin2.is_low(), invert_a); 66 assert_ne!(pin2.is_low(), invert_a);
67 Timer::after(Duration::from_millis(5)).await; 67 Timer::after_millis(5).await;
68 assert_ne!(pin2.is_high(), invert_a); 68 assert_ne!(pin2.is_high(), invert_a);
69 Timer::after(Duration::from_millis(5)).await; 69 Timer::after_millis(5).await;
70 assert_ne!(pin2.is_low(), invert_a); 70 assert_ne!(pin2.is_low(), invert_a);
71 Timer::after(Duration::from_millis(5)).await; 71 Timer::after_millis(5).await;
72 assert_ne!(pin2.is_high(), invert_a); 72 assert_ne!(pin2.is_high(), invert_a);
73 } 73 }
74 74
@@ -77,16 +77,16 @@ async fn main(_spawner: Spawner) {
77 let pin1 = Input::new(&mut p9, Pull::None); 77 let pin1 = Input::new(&mut p9, Pull::None);
78 let pin2 = Input::new(&mut p11, Pull::None); 78 let pin2 = Input::new(&mut p11, Pull::None);
79 let _pwm = Pwm::new_output_ab(&mut p.PWM_CH3, &mut p6, &mut p7, cfg.clone()); 79 let _pwm = Pwm::new_output_ab(&mut p.PWM_CH3, &mut p6, &mut p7, cfg.clone());
80 Timer::after(Duration::from_millis(1)).await; 80 Timer::after_millis(1).await;
81 assert_eq!(pin1.is_low(), invert_a); 81 assert_eq!(pin1.is_low(), invert_a);
82 assert_ne!(pin2.is_low(), invert_a); 82 assert_ne!(pin2.is_low(), invert_a);
83 Timer::after(Duration::from_millis(5)).await; 83 Timer::after_millis(5).await;
84 assert_eq!(pin1.is_high(), invert_a); 84 assert_eq!(pin1.is_high(), invert_a);
85 assert_ne!(pin2.is_high(), invert_a); 85 assert_ne!(pin2.is_high(), invert_a);
86 Timer::after(Duration::from_millis(5)).await; 86 Timer::after_millis(5).await;
87 assert_eq!(pin1.is_low(), invert_a); 87 assert_eq!(pin1.is_low(), invert_a);
88 assert_ne!(pin2.is_low(), invert_a); 88 assert_ne!(pin2.is_low(), invert_a);
89 Timer::after(Duration::from_millis(5)).await; 89 Timer::after_millis(5).await;
90 assert_eq!(pin1.is_high(), invert_a); 90 assert_eq!(pin1.is_high(), invert_a);
91 assert_ne!(pin2.is_high(), invert_a); 91 assert_ne!(pin2.is_high(), invert_a);
92 } 92 }
@@ -97,14 +97,14 @@ async fn main(_spawner: Spawner) {
97 let mut pin2 = Output::new(&mut p11, Level::Low); 97 let mut pin2 = Output::new(&mut p11, Level::Low);
98 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::Level, cfg.clone()); 98 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::Level, cfg.clone());
99 assert_eq!(pwm.counter(), 0); 99 assert_eq!(pwm.counter(), 0);
100 Timer::after(Duration::from_millis(5)).await; 100 Timer::after_millis(5).await;
101 assert_eq!(pwm.counter(), 0); 101 assert_eq!(pwm.counter(), 0);
102 pin2.set_high(); 102 pin2.set_high();
103 Timer::after(Duration::from_millis(1)).await; 103 Timer::after_millis(1).await;
104 pin2.set_low(); 104 pin2.set_low();
105 let ctr = pwm.counter(); 105 let ctr = pwm.counter();
106 assert!(ctr >= 1000); 106 assert!(ctr >= 1000);
107 Timer::after(Duration::from_millis(1)).await; 107 Timer::after_millis(1).await;
108 assert_eq!(pwm.counter(), ctr); 108 assert_eq!(pwm.counter(), ctr);
109 } 109 }
110 110
@@ -113,13 +113,13 @@ async fn main(_spawner: Spawner) {
113 let mut pin2 = Output::new(&mut p11, Level::Low); 113 let mut pin2 = Output::new(&mut p11, Level::Low);
114 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::RisingEdge, cfg.clone()); 114 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::RisingEdge, cfg.clone());
115 assert_eq!(pwm.counter(), 0); 115 assert_eq!(pwm.counter(), 0);
116 Timer::after(Duration::from_millis(5)).await; 116 Timer::after_millis(5).await;
117 assert_eq!(pwm.counter(), 0); 117 assert_eq!(pwm.counter(), 0);
118 pin2.set_high(); 118 pin2.set_high();
119 Timer::after(Duration::from_millis(1)).await; 119 Timer::after_millis(1).await;
120 pin2.set_low(); 120 pin2.set_low();
121 assert_eq!(pwm.counter(), 1); 121 assert_eq!(pwm.counter(), 1);
122 Timer::after(Duration::from_millis(1)).await; 122 Timer::after_millis(1).await;
123 assert_eq!(pwm.counter(), 1); 123 assert_eq!(pwm.counter(), 1);
124 } 124 }
125 125
@@ -128,13 +128,13 @@ async fn main(_spawner: Spawner) {
128 let mut pin2 = Output::new(&mut p11, Level::High); 128 let mut pin2 = Output::new(&mut p11, Level::High);
129 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::FallingEdge, cfg.clone()); 129 let pwm = Pwm::new_input(&mut p.PWM_CH3, &mut p7, InputMode::FallingEdge, cfg.clone());
130 assert_eq!(pwm.counter(), 0); 130 assert_eq!(pwm.counter(), 0);
131 Timer::after(Duration::from_millis(5)).await; 131 Timer::after_millis(5).await;
132 assert_eq!(pwm.counter(), 0); 132 assert_eq!(pwm.counter(), 0);
133 pin2.set_low(); 133 pin2.set_low();
134 Timer::after(Duration::from_millis(1)).await; 134 Timer::after_millis(1).await;
135 pin2.set_high(); 135 pin2.set_high();
136 assert_eq!(pwm.counter(), 1); 136 assert_eq!(pwm.counter(), 1);
137 Timer::after(Duration::from_millis(1)).await; 137 Timer::after_millis(1).await;
138 assert_eq!(pwm.counter(), 1); 138 assert_eq!(pwm.counter(), 1);
139 } 139 }
140 140
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs
index 00f3e1949..8d351a3a7 100644
--- a/tests/rp/src/bin/uart.rs
+++ b/tests/rp/src/bin/uart.rs
@@ -7,7 +7,7 @@ use defmt::{assert_eq, *};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_rp::gpio::{Level, Output}; 8use embassy_rp::gpio::{Level, Output};
9use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx}; 9use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx};
10use embassy_time::{Duration, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> { 13fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
@@ -24,14 +24,14 @@ fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Resu
24 24
25async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { 25async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
26 pin.set_low(); 26 pin.set_low();
27 Timer::after(Duration::from_millis(1)).await; 27 Timer::after_millis(1).await;
28 for i in 0..8 { 28 for i in 0..8 {
29 if v & (1 << i) == 0 { 29 if v & (1 << i) == 0 {
30 pin.set_low(); 30 pin.set_low();
31 } else { 31 } else {
32 pin.set_high(); 32 pin.set_high();
33 } 33 }
34 Timer::after(Duration::from_millis(1)).await; 34 Timer::after_millis(1).await;
35 } 35 }
36 if let Some(b) = parity { 36 if let Some(b) = parity {
37 if b { 37 if b {
@@ -39,10 +39,10 @@ async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: O
39 } else { 39 } else {
40 pin.set_low(); 40 pin.set_low();
41 } 41 }
42 Timer::after(Duration::from_millis(1)).await; 42 Timer::after_millis(1).await;
43 } 43 }
44 pin.set_high(); 44 pin.set_high();
45 Timer::after(Duration::from_millis(1)).await; 45 Timer::after_millis(1).await;
46} 46}
47 47
48#[embassy_executor::main] 48#[embassy_executor::main]
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs
index 6ab7de29e..6a9c910ff 100644
--- a/tests/rp/src/bin/uart_buffered.rs
+++ b/tests/rp/src/bin/uart_buffered.rs
@@ -9,7 +9,7 @@ use embassy_rp::bind_interrupts;
9use embassy_rp::gpio::{Level, Output}; 9use embassy_rp::gpio::{Level, Output};
10use embassy_rp::peripherals::UART0; 10use embassy_rp::peripherals::UART0;
11use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity}; 11use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use embedded_io_async::{Read, ReadExactError, Write}; 13use embedded_io_async::{Read, ReadExactError, Write};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -39,14 +39,14 @@ async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) ->
39 39
40async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { 40async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
41 pin.set_low(); 41 pin.set_low();
42 Timer::after(Duration::from_millis(1)).await; 42 Timer::after_millis(1).await;
43 for i in 0..8 { 43 for i in 0..8 {
44 if v & (1 << i) == 0 { 44 if v & (1 << i) == 0 {
45 pin.set_low(); 45 pin.set_low();
46 } else { 46 } else {
47 pin.set_high(); 47 pin.set_high();
48 } 48 }
49 Timer::after(Duration::from_millis(1)).await; 49 Timer::after_millis(1).await;
50 } 50 }
51 if let Some(b) = parity { 51 if let Some(b) = parity {
52 if b { 52 if b {
@@ -54,10 +54,10 @@ async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: O
54 } else { 54 } else {
55 pin.set_low(); 55 pin.set_low();
56 } 56 }
57 Timer::after(Duration::from_millis(1)).await; 57 Timer::after_millis(1).await;
58 } 58 }
59 pin.set_high(); 59 pin.set_high();
60 Timer::after(Duration::from_millis(1)).await; 60 Timer::after_millis(1).await;
61} 61}
62 62
63#[embassy_executor::main] 63#[embassy_executor::main]
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
index cd4af1ef2..e79fcde60 100644
--- a/tests/rp/src/bin/uart_dma.rs
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -9,7 +9,7 @@ use embassy_rp::bind_interrupts;
9use embassy_rp::gpio::{Level, Output}; 9use embassy_rp::gpio::{Level, Output};
10use embassy_rp::peripherals::UART0; 10use embassy_rp::peripherals::UART0;
11use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx}; 11use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
12use embassy_time::{Duration, Timer}; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
@@ -30,14 +30,14 @@ async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> R
30 30
31async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) { 31async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
32 pin.set_low(); 32 pin.set_low();
33 Timer::after(Duration::from_millis(1)).await; 33 Timer::after_millis(1).await;
34 for i in 0..8 { 34 for i in 0..8 {
35 if v & (1 << i) == 0 { 35 if v & (1 << i) == 0 {
36 pin.set_low(); 36 pin.set_low();
37 } else { 37 } else {
38 pin.set_high(); 38 pin.set_high();
39 } 39 }
40 Timer::after(Duration::from_millis(1)).await; 40 Timer::after_millis(1).await;
41 } 41 }
42 if let Some(b) = parity { 42 if let Some(b) = parity {
43 if b { 43 if b {
@@ -45,10 +45,10 @@ async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: O
45 } else { 45 } else {
46 pin.set_low(); 46 pin.set_low();
47 } 47 }
48 Timer::after(Duration::from_millis(1)).await; 48 Timer::after_millis(1).await;
49 } 49 }
50 pin.set_high(); 50 pin.set_high();
51 Timer::after(Duration::from_millis(1)).await; 51 Timer::after_millis(1).await;
52} 52}
53 53
54#[embassy_executor::main] 54#[embassy_executor::main]
@@ -105,7 +105,7 @@ async fn main(_spawner: Spawner) {
105 // new data is accepted, latest overrunning byte first 105 // new data is accepted, latest overrunning byte first
106 assert_eq!(read(&mut uart).await, Ok([3])); 106 assert_eq!(read(&mut uart).await, Ok([3]));
107 uart.blocking_write(&[8, 9]).unwrap(); 107 uart.blocking_write(&[8, 9]).unwrap();
108 Timer::after(Duration::from_millis(1)).await; 108 Timer::after_millis(1).await;
109 assert_eq!(read(&mut uart).await, Ok([8, 9])); 109 assert_eq!(read(&mut uart).await, Ok([8, 9]));
110 } 110 }
111 111
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bfe5bc823..b1b2f55c3 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -6,21 +6,28 @@ license = "MIT OR Apache-2.0"
6autobins = false 6autobins = false
7 7
8[features] 8[features]
9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill 9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"]
10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "stop", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" 10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin", "rng"]
11stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo 11stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"]
12stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo 12stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"]
13stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo 13stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma", "rng"]
14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma", "dac-adc-pin"] # Nucleo 14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin", "rng"]
15stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo 15stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" , "rng"]
16stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo 16stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"]
17stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board 17stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng"]
18stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma"] # Nucleo 18stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma", "rng"]
19stm32l152re = ["embassy-stm32/stm32l152re", "not-gpdma"] # Nucleo 19stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
20stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "not-gpdma"] # Nucleo 20stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng"]
21stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "not-gpdma"] # Nucleo 21stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"]
22stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma"] # Nucleo 22stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma", "rng"]
23 23stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
24stm32f207zg = ["embassy-stm32/stm32f207zg", "chrono", "not-gpdma", "eth", "rng"]
25stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"]
26stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
27stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
28
29eth = []
30rng = []
24sdmmc = [] 31sdmmc = []
25stop = ["embassy-stm32/low-power"] 32stop = ["embassy-stm32/low-power"]
26chrono = ["embassy-stm32/chrono", "dep:chrono"] 33chrono = ["embassy-stm32/chrono", "dep:chrono"]
@@ -36,10 +43,12 @@ teleprobe-meta = "1"
36 43
37embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } 44embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] }
38embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 45embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
39embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } 46embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "tick-hz-131_072", "defmt-timestamp-uptime"] }
40embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } 47embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] }
41embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 48embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
42embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } 49embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] }
50embassy-net = { version = "0.2.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
51perf-client = { path = "../perf-client" }
43 52
44defmt = "0.3.0" 53defmt = "0.3.0"
45defmt-rtt = "0.4" 54defmt-rtt = "0.4"
@@ -70,11 +79,21 @@ path = "src/bin/dac.rs"
70required-features = [ "dac-adc-pin",] 79required-features = [ "dac-adc-pin",]
71 80
72[[bin]] 81[[bin]]
82name = "eth"
83path = "src/bin/eth.rs"
84required-features = [ "eth",]
85
86[[bin]]
73name = "gpio" 87name = "gpio"
74path = "src/bin/gpio.rs" 88path = "src/bin/gpio.rs"
75required-features = [] 89required-features = []
76 90
77[[bin]] 91[[bin]]
92name = "rng"
93path = "src/bin/rng.rs"
94required-features = [ "rng",]
95
96[[bin]]
78name = "rtc" 97name = "rtc"
79path = "src/bin/rtc.rs" 98path = "src/bin/rtc.rs"
80required-features = [ "chrono",] 99required-features = [ "chrono",]
diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs
index 9aabf8541..c5d0e40d6 100644
--- a/tests/stm32/build.rs
+++ b/tests/stm32/build.rs
@@ -8,12 +8,14 @@ fn main() -> Result<(), Box<dyn Error>> {
8 println!("cargo:rustc-link-search={}", out.display()); 8 println!("cargo:rustc-link-search={}", out.display());
9 println!("cargo:rustc-link-arg-bins=--nmagic"); 9 println!("cargo:rustc-link-arg-bins=--nmagic");
10 10
11 // too little RAM to run from RAM.
12 if cfg!(any( 11 if cfg!(any(
12 // too little RAM to run from RAM.
13 feature = "stm32f103c8", 13 feature = "stm32f103c8",
14 feature = "stm32c031c6", 14 feature = "stm32c031c6",
15 feature = "stm32wb55rg", 15 feature = "stm32wb55rg",
16 feature = "stm32l073rz", 16 feature = "stm32l073rz",
17 // wrong ram size in stm32-data
18 feature = "stm32wl55jc",
17 )) { 19 )) {
18 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 20 println!("cargo:rustc-link-arg-bins=-Tlink.x");
19 println!("cargo:rerun-if-changed=link.x"); 21 println!("cargo:rerun-if-changed=link.x");
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
index 67a7d5b59..10e3c3e81 100644
--- a/tests/stm32/src/bin/dac.rs
+++ b/tests/stm32/src/bin/dac.rs
@@ -12,7 +12,7 @@ use embassy_executor::Spawner;
12use embassy_stm32::adc::Adc; 12use embassy_stm32::adc::Adc;
13use embassy_stm32::dac::{DacCh1, DacChannel, Value}; 13use embassy_stm32::dac::{DacCh1, DacChannel, Value};
14use embassy_stm32::dma::NoDma; 14use embassy_stm32::dma::NoDma;
15use embassy_time::{Delay, Duration, Timer}; 15use embassy_time::{Delay, Timer};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18#[embassy_executor::main] 18#[embassy_executor::main]
@@ -38,7 +38,7 @@ async fn main(_spawner: Spawner) {
38 38
39 unwrap!(dac.set(Value::Bit8(0))); 39 unwrap!(dac.set(Value::Bit8(0)));
40 // Now wait a little to obtain a stable value 40 // Now wait a little to obtain a stable value
41 Timer::after(Duration::from_millis(30)).await; 41 Timer::after_millis(30).await;
42 let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); 42 let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
43 43
44 for v in 0..=255 { 44 for v in 0..=255 {
@@ -47,14 +47,14 @@ async fn main(_spawner: Spawner) {
47 unwrap!(dac.set(Value::Bit8(dac_output_val))); 47 unwrap!(dac.set(Value::Bit8(dac_output_val)));
48 48
49 // Now wait a little to obtain a stable value 49 // Now wait a little to obtain a stable value
50 Timer::after(Duration::from_millis(30)).await; 50 Timer::after_millis(30).await;
51 51
52 // Need to steal the peripherals here because PA4 is obviously in use already 52 // Need to steal the peripherals here because PA4 is obviously in use already
53 let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); 53 let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4);
54 // Calibrate and normalize the measurement to get close to the dac_output_val 54 // Calibrate and normalize the measurement to get close to the dac_output_val
55 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; 55 let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16;
56 56
57 info!("value / measured: {} / {}", dac_output_val, measured_normalized); 57 //info!("value / measured: {} / {}", dac_output_val, measured_normalized);
58 58
59 // The deviations are quite enormous but that does not matter since this is only a quick test 59 // The deviations are quite enormous but that does not matter since this is only a quick test
60 assert!((dac_output_val as i16 - measured_normalized).abs() < 15); 60 assert!((dac_output_val as i16 - measured_normalized).abs() < 15);
diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs
new file mode 100644
index 000000000..6d5e05cd6
--- /dev/null
+++ b/tests/stm32/src/bin/eth.rs
@@ -0,0 +1,122 @@
1// required-features: eth
2#![no_std]
3#![no_main]
4#![feature(type_alias_impl_trait)]
5
6#[path = "../common.rs"]
7mod common;
8use common::*;
9use embassy_executor::Spawner;
10use embassy_net::{Stack, StackResources};
11use embassy_stm32::eth::generic_smi::GenericSMI;
12use embassy_stm32::eth::{Ethernet, PacketQueue};
13use embassy_stm32::peripherals::ETH;
14use embassy_stm32::rng::Rng;
15use embassy_stm32::{bind_interrupts, eth, peripherals, rng};
16use rand_core::RngCore;
17use static_cell::make_static;
18use {defmt_rtt as _, panic_probe as _};
19
20teleprobe_meta::timeout!(120);
21
22#[cfg(not(any(feature = "stm32h563zi", feature = "stm32f767zi", feature = "stm32f207zg")))]
23bind_interrupts!(struct Irqs {
24 ETH => eth::InterruptHandler;
25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
26});
27#[cfg(any(feature = "stm32h563zi", feature = "stm32f767zi", feature = "stm32f207zg"))]
28bind_interrupts!(struct Irqs {
29 ETH => eth::InterruptHandler;
30 RNG => rng::InterruptHandler<peripherals::RNG>;
31});
32
33type Device = Ethernet<'static, ETH, GenericSMI>;
34
35#[embassy_executor::task]
36async fn net_task(stack: &'static Stack<Device>) -> ! {
37 stack.run().await
38}
39
40#[embassy_executor::main]
41async fn main(spawner: Spawner) {
42 let p = embassy_stm32::init(config());
43 info!("Hello World!");
44
45 // Generate random seed.
46 let mut rng = Rng::new(p.RNG, Irqs);
47 let mut seed = [0; 8];
48 rng.fill_bytes(&mut seed);
49 let seed = u64::from_le_bytes(seed);
50
51 // Ensure different boards get different MAC
52 // so running tests concurrently doesn't break (they're all in the same LAN)
53 #[cfg(feature = "stm32f429zi")]
54 let n = 1;
55 #[cfg(feature = "stm32h755zi")]
56 let n = 2;
57 #[cfg(feature = "stm32h563zi")]
58 let n = 3;
59 #[cfg(feature = "stm32f767zi")]
60 let n = 4;
61 #[cfg(feature = "stm32f207zg")]
62 let n = 5;
63
64 let mac_addr = [0x00, n, 0xDE, 0xAD, 0xBE, 0xEF];
65
66 // F2 runs out of RAM
67 #[cfg(feature = "stm32f207zg")]
68 const PACKET_QUEUE_SIZE: usize = 2;
69 #[cfg(not(feature = "stm32f207zg"))]
70 const PACKET_QUEUE_SIZE: usize = 4;
71
72 let device = Ethernet::new(
73 make_static!(PacketQueue::<PACKET_QUEUE_SIZE, PACKET_QUEUE_SIZE>::new()),
74 p.ETH,
75 Irqs,
76 p.PA1,
77 p.PA2,
78 p.PC1,
79 p.PA7,
80 p.PC4,
81 p.PC5,
82 p.PG13,
83 #[cfg(not(feature = "stm32h563zi"))]
84 p.PB13,
85 #[cfg(feature = "stm32h563zi")]
86 p.PB15,
87 p.PG11,
88 GenericSMI::new(0),
89 mac_addr,
90 );
91
92 let config = embassy_net::Config::dhcpv4(Default::default());
93 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
94 // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24),
95 // dns_servers: Vec::new(),
96 // gateway: Some(Ipv4Address::new(10, 42, 0, 1)),
97 //});
98
99 // Init network stack
100 let stack = &*make_static!(Stack::new(
101 device,
102 config,
103 make_static!(StackResources::<2>::new()),
104 seed
105 ));
106
107 // Launch network task
108 unwrap!(spawner.spawn(net_task(&stack)));
109
110 perf_client::run(
111 stack,
112 perf_client::Expected {
113 down_kbps: 1000,
114 up_kbps: 1000,
115 updown_kbps: 1000,
116 },
117 )
118 .await;
119
120 info!("Test OK");
121 cortex_m::asm::bkpt();
122}
diff --git a/tests/stm32/src/bin/rng.rs b/tests/stm32/src/bin/rng.rs
new file mode 100644
index 000000000..65da737d0
--- /dev/null
+++ b/tests/stm32/src/bin/rng.rs
@@ -0,0 +1,50 @@
1// required-features: rng
2#![no_std]
3#![no_main]
4#![feature(type_alias_impl_trait)]
5
6#[path = "../common.rs"]
7mod common;
8use common::*;
9use embassy_executor::Spawner;
10use embassy_stm32::rng::Rng;
11use embassy_stm32::{bind_interrupts, peripherals, rng};
12use {defmt_rtt as _, panic_probe as _};
13
14#[cfg(any(feature = "stm32l4a6zg", feature = "stm32h755zi", feature = "stm32f429zi"))]
15bind_interrupts!(struct Irqs {
16 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
17});
18#[cfg(any(feature = "stm32l073rz"))]
19bind_interrupts!(struct Irqs {
20 RNG_LPUART1 => rng::InterruptHandler<peripherals::RNG>;
21});
22#[cfg(not(any(
23 feature = "stm32l4a6zg",
24 feature = "stm32l073rz",
25 feature = "stm32h755zi",
26 feature = "stm32f429zi"
27)))]
28bind_interrupts!(struct Irqs {
29 RNG => rng::InterruptHandler<peripherals::RNG>;
30});
31
32#[embassy_executor::main]
33async fn main(_spawner: Spawner) {
34 let p: embassy_stm32::Peripherals = embassy_stm32::init(config());
35
36 let mut rng = Rng::new(p.RNG, Irqs);
37
38 let mut buf1 = [0u8; 16];
39 unwrap!(rng.async_fill_bytes(&mut buf1).await);
40 info!("random bytes: {:02x}", buf1);
41
42 let mut buf2 = [0u8; 16];
43 unwrap!(rng.async_fill_bytes(&mut buf2).await);
44 info!("random bytes: {:02x}", buf2);
45
46 defmt::assert!(buf1 != buf2);
47
48 info!("Test OK");
49 cortex_m::asm::bkpt();
50}
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs
index 22be6fac5..64f1122a6 100644
--- a/tests/stm32/src/bin/rtc.rs
+++ b/tests/stm32/src/bin/rtc.rs
@@ -10,17 +10,14 @@ use chrono::{NaiveDate, NaiveDateTime};
10use common::*; 10use common::*;
11use defmt::assert; 11use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::rcc::RtcClockSource; 13use embassy_stm32::rcc::LsConfig;
14use embassy_stm32::rtc::{Rtc, RtcConfig}; 14use embassy_stm32::rtc::{Rtc, RtcConfig};
15use embassy_stm32::time::Hertz; 15use embassy_time::Timer;
16use embassy_time::{Duration, Timer};
17 16
18#[embassy_executor::main] 17#[embassy_executor::main]
19async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
20 let mut config = config(); 19 let mut config = config();
21 20 config.rcc.ls = LsConfig::default_lse();
22 config.rcc.lse = Some(Hertz(32_768));
23 config.rcc.rtc = Some(RtcClockSource::LSE);
24 21
25 let p = embassy_stm32::init(config); 22 let p = embassy_stm32::init(config);
26 info!("Hello World!"); 23 info!("Hello World!");
@@ -35,12 +32,12 @@ async fn main(_spawner: Spawner) {
35 rtc.set_datetime(now.into()).expect("datetime not set"); 32 rtc.set_datetime(now.into()).expect("datetime not set");
36 33
37 info!("Waiting 5 seconds"); 34 info!("Waiting 5 seconds");
38 Timer::after(Duration::from_millis(5000)).await; 35 Timer::after_millis(5000).await;
39 36
40 let then: NaiveDateTime = rtc.now().unwrap().into(); 37 let then: NaiveDateTime = rtc.now().unwrap().into();
41 let seconds = (then - now).num_seconds(); 38 let seconds = (then - now).num_seconds();
42 39
43 defmt::info!("measured = {}", seconds); 40 info!("measured = {}", seconds);
44 41
45 assert!(seconds > 3 && seconds < 7); 42 assert!(seconds > 3 && seconds < 7);
46 43
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs
index 48d59b794..f38924c90 100644
--- a/tests/stm32/src/bin/stop.rs
+++ b/tests/stm32/src/bin/stop.rs
@@ -11,10 +11,10 @@ use common::*;
11use cortex_m_rt::entry; 11use cortex_m_rt::entry;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::low_power::{stop_with_rtc, Executor}; 13use embassy_stm32::low_power::{stop_with_rtc, Executor};
14use embassy_stm32::rcc::RtcClockSource; 14use embassy_stm32::rcc::LsConfig;
15use embassy_stm32::rtc::{Rtc, RtcConfig}; 15use embassy_stm32::rtc::{Rtc, RtcConfig};
16use embassy_stm32::time::Hertz; 16use embassy_stm32::Config;
17use embassy_time::{Duration, Timer}; 17use embassy_time::Timer;
18use static_cell::make_static; 18use static_cell::make_static;
19 19
20#[entry] 20#[entry]
@@ -28,7 +28,7 @@ fn main() -> ! {
28async fn task_1() { 28async fn task_1() {
29 for _ in 0..9 { 29 for _ in 0..9 {
30 info!("task 1: waiting for 500ms..."); 30 info!("task 1: waiting for 500ms...");
31 Timer::after(Duration::from_millis(500)).await; 31 Timer::after_millis(500).await;
32 } 32 }
33} 33}
34 34
@@ -36,7 +36,7 @@ async fn task_1() {
36async fn task_2() { 36async fn task_2() {
37 for _ in 0..5 { 37 for _ in 0..5 {
38 info!("task 2: waiting for 1000ms..."); 38 info!("task 2: waiting for 1000ms...");
39 Timer::after(Duration::from_millis(1000)).await; 39 Timer::after_millis(1000).await;
40 } 40 }
41 41
42 info!("Test OK"); 42 info!("Test OK");
@@ -45,10 +45,10 @@ async fn task_2() {
45 45
46#[embassy_executor::task] 46#[embassy_executor::task]
47async fn async_main(spawner: Spawner) { 47async fn async_main(spawner: Spawner) {
48 let mut config = config(); 48 let _ = config();
49 49
50 config.rcc.lse = Some(Hertz(32_768)); 50 let mut config = Config::default();
51 config.rcc.rtc = Some(RtcClockSource::LSE); 51 config.rcc.ls = LsConfig::default_lse();
52 52
53 let p = embassy_stm32::init(config); 53 let p = embassy_stm32::init(config);
54 info!("Hello World!"); 54 info!("Hello World!");
diff --git a/tests/stm32/src/bin/timer.rs b/tests/stm32/src/bin/timer.rs
index f8b453cda..4efeb0a49 100644
--- a/tests/stm32/src/bin/timer.rs
+++ b/tests/stm32/src/bin/timer.rs
@@ -7,7 +7,7 @@ mod common;
7use common::*; 7use common::*;
8use defmt::assert; 8use defmt::assert;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_time::{Duration, Instant, Timer}; 10use embassy_time::{Instant, Timer};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
@@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let start = Instant::now(); 17 let start = Instant::now();
18 Timer::after(Duration::from_millis(100)).await; 18 Timer::after_millis(100).await;
19 let end = Instant::now(); 19 let end = Instant::now();
20 let ms = (end - start).as_millis(); 20 let ms = (end - start).as_millis();
21 info!("slept for {} ms", ms); 21 info!("slept for {} ms", ms);
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
index 1ee7e596d..7e15f64b6 100644
--- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs
+++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
@@ -10,7 +10,7 @@ use common::*;
10use defmt::{assert_eq, panic}; 10use defmt::{assert_eq, panic};
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; 12use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
13use embassy_time::{Duration, Timer}; 13use embassy_time::Timer;
14use rand_chacha::ChaCha8Rng; 14use rand_chacha::ChaCha8Rng;
15use rand_core::{RngCore, SeedableRng}; 15use rand_core::{RngCore, SeedableRng};
16 16
@@ -54,7 +54,7 @@ async fn main(spawner: Spawner) {
54#[embassy_executor::task] 54#[embassy_executor::task]
55async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>) { 55async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>) {
56 // workaround https://github.com/embassy-rs/embassy/issues/1426 56 // workaround https://github.com/embassy-rs/embassy/issues/1426
57 Timer::after(Duration::from_millis(100) as _).await; 57 Timer::after_millis(100).await;
58 58
59 let mut rng = ChaCha8Rng::seed_from_u64(1337); 59 let mut rng = ChaCha8Rng::seed_from_u64(1337);
60 60
@@ -70,7 +70,7 @@ async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>)
70 } 70 }
71 71
72 tx.write(&buf[..len]).await.unwrap(); 72 tx.write(&buf[..len]).await.unwrap();
73 Timer::after(Duration::from_micros((rng.next_u32() % 1000) as _)).await; 73 Timer::after_micros((rng.next_u32() % 1000) as _).await;
74 } 74 }
75} 75}
76 76
@@ -98,7 +98,7 @@ async fn receive_task(mut rx: RingBufferedUartRx<'static, peris::UART, peris::UA
98 } 98 }
99 99
100 if received < max_len { 100 if received < max_len {
101 Timer::after(Duration::from_micros((rng.next_u32() % 1000) as _)).await; 101 Timer::after_micros((rng.next_u32() % 1000) as _).await;
102 } 102 }
103 103
104 i += received; 104 i += received;
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 9c0b8c39e..8dde71fb3 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -34,6 +34,16 @@ teleprobe_meta::target!(b"nucleo-stm32l4a6zg");
34teleprobe_meta::target!(b"nucleo-stm32l4r5zi"); 34teleprobe_meta::target!(b"nucleo-stm32l4r5zi");
35#[cfg(feature = "stm32l552ze")] 35#[cfg(feature = "stm32l552ze")]
36teleprobe_meta::target!(b"nucleo-stm32l552ze"); 36teleprobe_meta::target!(b"nucleo-stm32l552ze");
37#[cfg(feature = "stm32f767zi")]
38teleprobe_meta::target!(b"nucleo-stm32f767zi");
39#[cfg(feature = "stm32f207zg")]
40teleprobe_meta::target!(b"nucleo-stm32f207zg");
41#[cfg(feature = "stm32f303ze")]
42teleprobe_meta::target!(b"nucleo-stm32f303ze");
43#[cfg(feature = "stm32l496zg")]
44teleprobe_meta::target!(b"nucleo-stm32l496zg");
45#[cfg(feature = "stm32wl55jc")]
46teleprobe_meta::target!(b"nucleo-stm32wl55jc");
37 47
38macro_rules! define_peris { 48macro_rules! define_peris {
39 ($($name:ident = $peri:ident,)* $(@irq $irq_name:ident = $irq_code:tt,)*) => { 49 ($($name:ident = $peri:ident,)* $(@irq $irq_name:ident = $irq_code:tt,)*) => {
@@ -119,6 +129,12 @@ define_peris!(
119 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2, 129 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2,
120 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;}, 130 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
121); 131);
132#[cfg(feature = "stm32l496zg")]
133define_peris!(
134 UART = USART3, UART_TX = PD8, UART_RX = PD9, UART_TX_DMA = DMA1_CH2, UART_RX_DMA = DMA1_CH3,
135 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
136 @irq UART = {USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;},
137);
122#[cfg(feature = "stm32l4a6zg")] 138#[cfg(feature = "stm32l4a6zg")]
123define_peris!( 139define_peris!(
124 UART = USART3, UART_TX = PD8, UART_RX = PD9, UART_TX_DMA = DMA1_CH2, UART_RX_DMA = DMA1_CH3, 140 UART = USART3, UART_TX = PD8, UART_RX = PD9, UART_TX_DMA = DMA1_CH2, UART_RX_DMA = DMA1_CH3,
@@ -149,28 +165,148 @@ define_peris!(
149 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2, 165 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH1, SPI_RX_DMA = DMA1_CH2,
150 @irq UART = {USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;}, 166 @irq UART = {USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;},
151); 167);
168#[cfg(feature = "stm32f767zi")]
169define_peris!(
170 UART = USART6, UART_TX = PG14, UART_RX = PG9, UART_TX_DMA = DMA2_CH6, UART_RX_DMA = DMA2_CH1,
171 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA2_CH3, SPI_RX_DMA = DMA2_CH2,
172 @irq UART = {USART6 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART6>;},
173);
174#[cfg(feature = "stm32f207zg")]
175define_peris!(
176 UART = USART6, UART_TX = PG14, UART_RX = PG9, UART_TX_DMA = DMA2_CH6, UART_RX_DMA = DMA2_CH1,
177 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA2_CH3, SPI_RX_DMA = DMA2_CH2,
178 @irq UART = {USART6 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART6>;},
179);
180#[cfg(feature = "stm32f303ze")]
181define_peris!(
182 UART = USART1, UART_TX = PC4, UART_RX = PC5, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5,
183 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
184 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
185);
186#[cfg(feature = "stm32wl55jc")]
187define_peris!(
188 UART = USART1, UART_TX = PB6, UART_RX = PB7, UART_TX_DMA = DMA1_CH4, UART_RX_DMA = DMA1_CH5,
189 SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
190 @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
191);
152 192
153pub fn config() -> Config { 193pub fn config() -> Config {
154 #[allow(unused_mut)] 194 #[allow(unused_mut)]
155 let mut config = Config::default(); 195 let mut config = Config::default();
156 196
197 #[cfg(feature = "stm32f207zg")]
198 {
199 use embassy_stm32::rcc::*;
200 // By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
201 config.rcc.hse = Some(HSEConfig {
202 frequency: Hertz(8_000_000),
203 source: HSESrc::Bypass,
204 });
205 // PLL uses HSE as the clock source
206 config.rcc.pll_mux = PLLSrc::HSE;
207 config.rcc.pll = PLLConfig {
208 // 8 MHz clock source / 8 = 1 MHz PLL input
209 pre_div: unwrap!(PLLPreDiv::try_from(8)),
210 // 1 MHz PLL input * 240 = 240 MHz PLL VCO
211 mul: unwrap!(PLLMul::try_from(240)),
212 // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
213 p_div: PLLPDiv::DIV2,
214 // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
215 q_div: PLLQDiv::DIV5,
216 };
217 // System clock comes from PLL (= the 120 MHz main PLL output)
218 config.rcc.mux = ClockSrc::PLL;
219 // 120 MHz / 4 = 30 MHz APB1 frequency
220 config.rcc.apb1_pre = APBPrescaler::DIV4;
221 // 120 MHz / 2 = 60 MHz APB2 frequency
222 config.rcc.apb2_pre = APBPrescaler::DIV2;
223 }
224
225 #[cfg(feature = "stm32f429zi")]
226 {
227 use embassy_stm32::rcc::*;
228 config.rcc.hse = Some(Hse {
229 freq: Hertz(8_000_000),
230 mode: HseMode::Bypass,
231 });
232 config.rcc.pll_src = PllSource::HSE;
233 config.rcc.pll = Some(Pll {
234 prediv: PllPreDiv::DIV4,
235 mul: PllMul::MUL180,
236 divp: Some(Pllp::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
237 divq: None,
238 divr: None,
239 });
240 config.rcc.ahb_pre = AHBPrescaler::DIV1;
241 config.rcc.apb1_pre = APBPrescaler::DIV4;
242 config.rcc.apb2_pre = APBPrescaler::DIV2;
243 config.rcc.sys = Sysclk::PLL1_P;
244 }
245
246 #[cfg(feature = "stm32f767zi")]
247 {
248 use embassy_stm32::rcc::*;
249 config.rcc.hse = Some(Hse {
250 freq: Hertz(8_000_000),
251 mode: HseMode::Bypass,
252 });
253 config.rcc.pll_src = PllSource::HSE;
254 config.rcc.pll = Some(Pll {
255 prediv: PllPreDiv::DIV4,
256 mul: PllMul::MUL216,
257 divp: Some(Pllp::DIV2), // 8mhz / 4 * 216 / 2 = 216Mhz.
258 divq: None,
259 divr: None,
260 });
261 config.rcc.ahb_pre = AHBPrescaler::DIV1;
262 config.rcc.apb1_pre = APBPrescaler::DIV4;
263 config.rcc.apb2_pre = APBPrescaler::DIV2;
264 config.rcc.sys = Sysclk::PLL1_P;
265 }
266
267 #[cfg(feature = "stm32h563zi")]
268 {
269 use embassy_stm32::rcc::*;
270 config.rcc.hsi = None;
271 config.rcc.hsi48 = true; // needed for rng
272 config.rcc.hse = Some(Hse {
273 freq: Hertz(8_000_000),
274 mode: HseMode::BypassDigital,
275 });
276 config.rcc.pll1 = Some(Pll {
277 source: PllSource::Hse,
278 prediv: PllPreDiv::DIV2,
279 mul: PllMul::MUL125,
280 divp: Some(PllDiv::DIV2),
281 divq: Some(PllDiv::DIV2),
282 divr: None,
283 });
284 config.rcc.ahb_pre = AHBPrescaler::DIV1;
285 config.rcc.apb1_pre = APBPrescaler::DIV1;
286 config.rcc.apb2_pre = APBPrescaler::DIV1;
287 config.rcc.apb3_pre = APBPrescaler::DIV1;
288 config.rcc.sys = Sysclk::Pll1P;
289 config.rcc.voltage_scale = VoltageScale::Scale0;
290 }
291
157 #[cfg(feature = "stm32h755zi")] 292 #[cfg(feature = "stm32h755zi")]
158 { 293 {
159 use embassy_stm32::rcc::*; 294 use embassy_stm32::rcc::*;
160 config.rcc.hsi = Some(Hsi::Mhz64); 295 config.rcc.hsi = Some(Hsi::Mhz64);
161 config.rcc.csi = true; 296 config.rcc.csi = true;
297 config.rcc.hsi48 = true; // needed for RNG
162 config.rcc.pll_src = PllSource::Hsi; 298 config.rcc.pll_src = PllSource::Hsi;
163 config.rcc.pll1 = Some(Pll { 299 config.rcc.pll1 = Some(Pll {
164 prediv: 4, 300 prediv: PllPreDiv::DIV4,
165 mul: 50, 301 mul: PllMul::MUL50,
166 divp: Some(2), 302 divp: Some(PllDiv::DIV2),
167 divq: Some(8), // SPI1 cksel defaults to pll1_q 303 divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q
168 divr: None, 304 divr: None,
169 }); 305 });
170 config.rcc.pll2 = Some(Pll { 306 config.rcc.pll2 = Some(Pll {
171 prediv: 4, 307 prediv: PllPreDiv::DIV4,
172 mul: 50, 308 mul: PllMul::MUL50,
173 divp: Some(8), // 100mhz 309 divp: Some(PllDiv::DIV8), // 100mhz
174 divq: None, 310 divq: None,
175 divr: None, 311 divr: None,
176 }); 312 });
@@ -184,36 +320,57 @@ pub fn config() -> Config {
184 config.rcc.adc_clock_source = AdcClockSource::PLL2_P; 320 config.rcc.adc_clock_source = AdcClockSource::PLL2_P;
185 } 321 }
186 322
187 #[cfg(any(feature = "stm32l4a6zg", feature = "stm32l4r5zi"))] 323 #[cfg(any(feature = "stm32l496zg", feature = "stm32l4a6zg", feature = "stm32l4r5zi"))]
188 { 324 {
189 use embassy_stm32::rcc::*; 325 use embassy_stm32::rcc::*;
190 config.rcc.mux = ClockSrc::PLL( 326 #[cfg(feature = "stm32l4r5zi")]
191 // 72Mhz clock (16 / 1 * 18 / 4) 327 {
192 PLLSource::HSI16, 328 config.rcc.mux = ClockSrc::PLL1_R;
193 PLLClkDiv::Div4, 329 }
194 PLLSrcDiv::Div1, 330 #[cfg(not(feature = "stm32l4r5zi"))]
195 PLLMul::Mul18, 331 {
196 Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) 332 config.rcc.mux = ClockSrc::PLL1_P;
197 ); 333 }
334 config.rcc.hsi16 = true;
335 config.rcc.pll = Some(Pll {
336 source: PLLSource::HSI,
337 prediv: PllPreDiv::DIV1,
338 mul: PllMul::MUL18,
339 divp: None,
340 divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
341 divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
342 });
343 }
344
345 #[cfg(feature = "stm32wl55jc")]
346 {
347 use embassy_stm32::rcc::*;
348 config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
349 embassy_stm32::pac::RCC.ccipr().modify(|w| {
350 w.set_rngsel(0b11); // msi
351 });
198 } 352 }
199 353
200 #[cfg(any(feature = "stm32l552ze"))] 354 #[cfg(any(feature = "stm32l552ze"))]
201 { 355 {
202 use embassy_stm32::rcc::*; 356 use embassy_stm32::rcc::*;
203 config.rcc.mux = ClockSrc::PLL( 357 config.rcc.hsi16 = true;
358 config.rcc.mux = ClockSrc::PLL1_R;
359 config.rcc.pll = Some(Pll {
204 // 110Mhz clock (16 / 4 * 55 / 2) 360 // 110Mhz clock (16 / 4 * 55 / 2)
205 PLLSource::HSI16, 361 source: PLLSource::HSI,
206 PLLClkDiv::Div2, 362 prediv: PllPreDiv::DIV4,
207 PLLSrcDiv::Div4, 363 mul: PllMul::MUL55,
208 PLLMul::Mul55, 364 divp: None,
209 None, 365 divq: None,
210 ); 366 divr: Some(PllRDiv::DIV2),
367 });
211 } 368 }
212 369
213 #[cfg(feature = "stm32u585ai")] 370 #[cfg(feature = "stm32u585ai")]
214 { 371 {
215 use embassy_stm32::rcc::*; 372 use embassy_stm32::rcc::*;
216 config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); 373 config.rcc.mux = ClockSrc::MSI(Msirange::RANGE_48MHZ);
217 } 374 }
218 375
219 #[cfg(feature = "stm32l073rz")] 376 #[cfg(feature = "stm32l073rz")]
@@ -222,8 +379,8 @@ pub fn config() -> Config {
222 config.rcc.mux = ClockSrc::PLL( 379 config.rcc.mux = ClockSrc::PLL(
223 // 32Mhz clock (16 * 4 / 2) 380 // 32Mhz clock (16 * 4 / 2)
224 PLLSource::HSI16, 381 PLLSource::HSI16,
225 PLLMul::Mul4, 382 PLLMul::MUL4,
226 PLLDiv::Div2, 383 PLLDiv::DIV2,
227 ); 384 );
228 } 385 }
229 386
@@ -232,9 +389,9 @@ pub fn config() -> Config {
232 use embassy_stm32::rcc::*; 389 use embassy_stm32::rcc::*;
233 config.rcc.mux = ClockSrc::PLL( 390 config.rcc.mux = ClockSrc::PLL(
234 // 32Mhz clock (16 * 4 / 2) 391 // 32Mhz clock (16 * 4 / 2)
235 PLLSource::HSI, 392 PLLSource::HSI16,
236 PLLMul::Mul4, 393 PLLMul::MUL4,
237 PLLDiv::Div2, 394 PLLDiv::DIV2,
238 ); 395 );
239 } 396 }
240 397