aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/boot/application/nrf/Cargo.toml18
-rw-r--r--examples/boot/application/nrf/README.md2
-rw-r--r--examples/boot/application/nrf/src/bin/a.rs25
-rw-r--r--examples/boot/application/nrf/src/bin/b.rs4
-rw-r--r--examples/boot/application/rp/Cargo.toml6
-rw-r--r--examples/boot/application/stm32f3/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f3/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32f7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f7/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32h7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32h7/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l0/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l0/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l1/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l1/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l4/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l4/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32wb-dfu/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wb-dfu/src/main.rs4
-rw-r--r--examples/boot/application/stm32wba-dfu/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wba-dfu/src/main.rs4
-rw-r--r--examples/boot/application/stm32wl/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wl/src/bin/a.rs11
-rw-r--r--examples/boot/application/stm32wl/src/bin/b.rs2
-rw-r--r--examples/boot/bootloader/nrf/Cargo.toml6
-rw-r--r--examples/boot/bootloader/nrf/src/main.rs9
-rw-r--r--examples/boot/bootloader/rp/Cargo.toml2
-rw-r--r--examples/boot/bootloader/rp/src/main.rs6
-rw-r--r--examples/boot/bootloader/stm32-dual-bank/Cargo.toml2
-rw-r--r--examples/boot/bootloader/stm32-dual-bank/src/main.rs8
-rw-r--r--examples/boot/bootloader/stm32/Cargo.toml2
-rw-r--r--examples/boot/bootloader/stm32/src/main.rs8
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/Cargo.toml2
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/src/main.rs12
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/Cargo.toml2
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/src/main.rs14
-rw-r--r--examples/lpc55s69/Cargo.toml2
-rw-r--r--examples/lpc55s69/src/bin/pwm.rs18
-rw-r--r--examples/lpc55s69/src/bin/usart_async.rs4
-rw-r--r--examples/mcxa/.cargo/config.toml17
-rw-r--r--examples/mcxa/.gitignore1
-rw-r--r--examples/mcxa/Cargo.toml35
-rw-r--r--examples/mcxa/build.rs20
-rw-r--r--examples/mcxa/memory.x5
-rw-r--r--examples/mcxa/src/bin/adc_interrupt.rs65
-rw-r--r--examples/mcxa/src/bin/adc_polling.rs78
-rw-r--r--examples/mcxa/src/bin/blinky.rs36
-rw-r--r--examples/mcxa/src/bin/button.rs23
-rw-r--r--examples/mcxa/src/bin/button_async.rs29
-rw-r--r--examples/mcxa/src/bin/clkout.rs68
-rw-r--r--examples/mcxa/src/bin/crc.rs154
-rw-r--r--examples/mcxa/src/bin/dma_mem_to_mem.rs118
-rw-r--r--examples/mcxa/src/bin/dma_scatter_gather_builder.rs130
-rw-r--r--examples/mcxa/src/bin/dma_wrap_transfer.rs184
-rw-r--r--examples/mcxa/src/bin/hello.rs119
-rw-r--r--examples/mcxa/src/bin/i2c-async.rs39
-rw-r--r--examples/mcxa/src/bin/i2c-blocking.rs31
-rw-r--r--examples/mcxa/src/bin/i2c-scan-blocking.rs40
-rw-r--r--examples/mcxa/src/bin/lpuart_buffered.rs62
-rw-r--r--examples/mcxa/src/bin/lpuart_dma.rs68
-rw-r--r--examples/mcxa/src/bin/lpuart_polling.rs47
-rw-r--r--examples/mcxa/src/bin/lpuart_ring_buffer.rs115
-rw-r--r--examples/mcxa/src/bin/raw_dma_channel_link.rs278
-rw-r--r--examples/mcxa/src/bin/raw_dma_interleave_transfer.rs141
-rw-r--r--examples/mcxa/src/bin/raw_dma_memset.rs129
-rw-r--r--examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs244
-rw-r--r--examples/mcxa/src/bin/raw_dma_scatter_gather.rs165
-rw-r--r--examples/mcxa/src/bin/reset-reason.rs15
-rw-r--r--examples/mcxa/src/bin/rtc_alarm.rs47
-rw-r--r--examples/mcxa/src/bin/trng.rs106
-rw-r--r--examples/mimxrt1011/Cargo.toml2
-rw-r--r--examples/mimxrt1011/src/lib.rs2
-rw-r--r--examples/mimxrt1062-evk/Cargo.toml2
-rw-r--r--examples/mimxrt1062-evk/src/lib.rs4
-rw-r--r--examples/mimxrt6/Cargo.toml4
-rw-r--r--examples/mimxrt6/src/bin/button.rs2
-rw-r--r--examples/mimxrt6/src/bin/dma.rs26
-rw-r--r--examples/mimxrt6/src/bin/spi-async.rs35
-rw-r--r--examples/mimxrt6/src/bin/spi.rs51
-rw-r--r--examples/mspm0c1104/Cargo.toml2
-rw-r--r--examples/mspm0c1104/src/bin/blinky.rs2
-rw-r--r--examples/mspm0c1104/src/bin/button.rs2
-rw-r--r--examples/mspm0g3507/Cargo.toml2
-rw-r--r--examples/mspm0g3507/src/bin/adc.rs2
-rw-r--r--examples/mspm0g3507/src/bin/blinky.rs2
-rw-r--r--examples/mspm0g3507/src/bin/button.rs2
-rw-r--r--examples/mspm0g3507/src/bin/i2c_target.rs63
-rw-r--r--examples/mspm0g3507/src/bin/mathacl_ops.rs39
-rw-r--r--examples/mspm0g3519/Cargo.toml2
-rw-r--r--examples/mspm0g3519/src/bin/blinky.rs2
-rw-r--r--examples/mspm0g3519/src/bin/button.rs2
-rw-r--r--examples/mspm0g5187/.cargo/config.toml9
-rw-r--r--examples/mspm0g5187/Cargo.toml27
-rw-r--r--examples/mspm0g5187/README.md27
-rw-r--r--examples/mspm0g5187/build.rs37
-rw-r--r--examples/mspm0g5187/memory.x6
-rw-r--r--examples/mspm0g5187/src/bin/blinky.rs25
-rw-r--r--examples/mspm0g5187/src/bin/button.rs33
-rw-r--r--examples/mspm0g5187/src/bin/wwdt.rs54
-rw-r--r--examples/mspm0l1306/Cargo.toml2
-rw-r--r--examples/mspm0l1306/src/bin/adc.rs2
-rw-r--r--examples/mspm0l1306/src/bin/blinky.rs2
-rw-r--r--examples/mspm0l1306/src/bin/button.rs2
-rw-r--r--examples/mspm0l1306/src/bin/i2c_target.rs63
-rw-r--r--examples/mspm0l2228/Cargo.toml2
-rw-r--r--examples/mspm0l2228/src/bin/blinky.rs2
-rw-r--r--examples/mspm0l2228/src/bin/button.rs2
-rw-r--r--examples/nrf-rtos-trace/Cargo.toml4
-rw-r--r--examples/nrf51/Cargo.toml4
-rw-r--r--examples/nrf52810/Cargo.toml4
-rw-r--r--examples/nrf52840-edf/Cargo.toml4
-rw-r--r--examples/nrf52840-edf/src/bin/basic.rs2
-rw-r--r--examples/nrf52840-rtic/Cargo.toml4
-rw-r--r--examples/nrf52840-rtic/src/bin/blinky.rs2
-rw-r--r--examples/nrf52840/Cargo.toml6
-rw-r--r--examples/nrf52840/src/bin/channel_sender_receiver.rs2
-rw-r--r--examples/nrf52840/src/bin/egu.rs15
-rw-r--r--examples/nrf52840/src/bin/ethernet_enc28j60.rs2
-rw-r--r--examples/nrf52840/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf52840/src/bin/i2s_effect.rs8
-rw-r--r--examples/nrf52840/src/bin/i2s_monitor.rs11
-rw-r--r--examples/nrf52840/src/bin/i2s_waveform.rs8
-rw-r--r--examples/nrf52840/src/bin/multiprio.rs4
-rw-r--r--examples/nrf52840/src/bin/ppi.rs34
-rw-r--r--examples/nrf52840/src/bin/pwm.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_sequence_ppi.rs14
-rw-r--r--examples/nrf52840/src/bin/pwm_servo.rs14
-rw-r--r--examples/nrf52840/src/bin/raw_spawn.rs4
-rw-r--r--examples/nrf52840/src/bin/rtc.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs4
-rw-r--r--examples/nrf52840/src/bin/usb_hid_keyboard.rs66
-rw-r--r--examples/nrf52840/src/bin/usb_hid_mouse.rs58
-rw-r--r--examples/nrf52840/src/bin/usb_serial.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_serial_winusb.rs2
-rw-r--r--examples/nrf52840/src/bin/wifi_esp_hosted.rs18
-rw-r--r--examples/nrf5340/Cargo.toml6
-rw-r--r--examples/nrf5340/src/bin/gpiote_channel.rs26
-rw-r--r--examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs30
-rw-r--r--examples/nrf54l15/Cargo.toml13
-rw-r--r--examples/nrf54l15/memory.x2
-rw-r--r--examples/nrf54l15/src/bin/buffered_uart.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_channel.rs49
-rw-r--r--examples/nrf54l15/src/bin/gpiote_port.rs33
-rw-r--r--examples/nrf54l15/src/bin/pwm.rs86
-rw-r--r--examples/nrf54l15/src/bin/rng.rs28
-rw-r--r--examples/nrf54l15/src/bin/rramc.rs (renamed from examples/nrf54l15/src/bin/nvmc.rs)0
-rw-r--r--examples/nrf54l15/src/bin/rramc_buffered.rs59
-rw-r--r--examples/nrf54l15/src/bin/saadc.rs28
-rw-r--r--examples/nrf54l15/src/bin/spim.rs30
-rw-r--r--examples/nrf54l15/src/bin/timer.rs30
-rw-r--r--examples/nrf54l15/src/bin/twim.rs37
-rw-r--r--examples/nrf54l15/src/bin/twis.rs47
-rw-r--r--examples/nrf54l15/src/bin/uart.rs37
-rw-r--r--examples/nrf54lm20/.cargo/config.toml9
-rw-r--r--examples/nrf54lm20/Cargo.toml37
-rw-r--r--examples/nrf54lm20/build.rs35
-rw-r--r--examples/nrf54lm20/memory.x5
-rw-r--r--examples/nrf54lm20/src/bin/blinky.rs23
-rw-r--r--examples/nrf54lm20/src/bin/gpio.rs23
-rw-r--r--examples/nrf54lm20/src/bin/gpiote_channel.rs49
-rw-r--r--examples/nrf54lm20/src/bin/gpiote_port.rs33
-rw-r--r--examples/nrf54lm20/src/bin/timer.rs30
-rw-r--r--examples/nrf9151/ns/Cargo.toml4
-rw-r--r--examples/nrf9151/s/Cargo.toml4
-rw-r--r--examples/nrf9160/Cargo.toml4
-rw-r--r--examples/nrf9160/src/bin/modem_tcp_client.rs6
-rw-r--r--examples/rp/Cargo.toml10
-rw-r--r--examples/rp/src/bin/assign_resources.rs2
-rw-r--r--examples/rp/src/bin/debounce.rs2
-rw-r--r--examples/rp/src/bin/ethernet_w5500_icmp_ping.rs4
-rw-r--r--examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs2
-rw-r--r--examples/rp/src/bin/interrupt.rs2
-rw-r--r--examples/rp/src/bin/multicore.rs2
-rw-r--r--examples/rp/src/bin/multiprio.rs6
-rw-r--r--examples/rp/src/bin/orchestrate_tasks.rs4
-rw-r--r--examples/rp/src/bin/overclock.rs2
-rw-r--r--examples/rp/src/bin/overclock_manual.rs2
-rw-r--r--examples/rp/src/bin/pio_async.rs2
-rw-r--r--examples/rp/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/rp/src/bin/pio_stepper.rs2
-rw-r--r--examples/rp/src/bin/pwm.rs4
-rw-r--r--examples/rp/src/bin/rtc_alarm.rs2
-rw-r--r--examples/rp/src/bin/sharing.rs2
-rw-r--r--examples/rp/src/bin/spi_display.rs12
-rw-r--r--examples/rp/src/bin/spi_gc9a01.rs4
-rw-r--r--examples/rp/src/bin/uart_r503.rs2
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs2
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs86
-rwxr-xr-xexamples/rp/src/bin/usb_hid_mouse.rs60
-rw-r--r--examples/rp/src/bin/usb_serial.rs2
-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.rs4
-rw-r--r--examples/rp/src/bin/wifi_webrequest.rs94
-rw-r--r--examples/rp/src/bin/zerocopy.rs2
-rw-r--r--examples/rp235x/Cargo.toml10
-rw-r--r--examples/rp235x/src/bin/assign_resources.rs2
-rw-r--r--examples/rp235x/src/bin/debounce.rs2
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs4
-rw-r--r--examples/rp235x/src/bin/interrupt.rs2
-rw-r--r--examples/rp235x/src/bin/multicore.rs2
-rw-r--r--examples/rp235x/src/bin/multicore_stack_overflow.rs2
-rw-r--r--examples/rp235x/src/bin/multiprio.rs6
-rw-r--r--examples/rp235x/src/bin/overclock.rs2
-rw-r--r--examples/rp235x/src/bin/pio_async.rs2
-rw-r--r--examples/rp235x/src/bin/pio_i2s.rs4
-rw-r--r--examples/rp235x/src/bin/pio_i2s_rx.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire.rs2
-rw-r--r--examples/rp235x/src/bin/pio_onewire_parasite.rs2
-rw-r--r--examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs2
-rw-r--r--examples/rp235x/src/bin/pio_stepper.rs2
-rw-r--r--examples/rp235x/src/bin/pwm.rs4
-rw-r--r--examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs2
-rw-r--r--examples/rp235x/src/bin/sharing.rs2
-rw-r--r--examples/rp235x/src/bin/spi_display.rs12
-rw-r--r--examples/rp235x/src/bin/uart_r503.rs2
-rw-r--r--examples/rp235x/src/bin/usb_hid_keyboard.rs85
-rw-r--r--examples/rp235x/src/bin/zerocopy.rs2
-rw-r--r--examples/std/Cargo.toml2
-rw-r--r--examples/std/src/bin/net_ppp.rs9
-rw-r--r--examples/std/src/bin/tick_cancel.rs47
-rw-r--r--examples/stm32c0/Cargo.toml2
-rw-r--r--examples/stm32c0/src/bin/adc.rs26
-rw-r--r--examples/stm32c0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32c0/src/bin/rtc.rs6
-rw-r--r--examples/stm32f0/Cargo.toml3
-rw-r--r--examples/stm32f0/src/bin/adc-watchdog.rs6
-rw-r--r--examples/stm32f0/src/bin/adc.rs5
-rw-r--r--examples/stm32f0/src/bin/button_controlled_blink.rs11
-rw-r--r--examples/stm32f0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f0/src/bin/i2c_master.rs609
-rw-r--r--examples/stm32f0/src/bin/multiprio.rs4
-rw-r--r--examples/stm32f1/Cargo.toml2
-rw-r--r--examples/stm32f1/src/bin/adc.rs6
-rw-r--r--examples/stm32f1/src/bin/can.rs6
-rw-r--r--examples/stm32f1/src/bin/input_capture.rs2
-rw-r--r--examples/stm32f1/src/bin/pwm_input.rs2
-rw-r--r--examples/stm32f1/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f2/Cargo.toml2
-rw-r--r--examples/stm32f2/src/bin/pll.rs2
-rw-r--r--examples/stm32f3/Cargo.toml2
-rw-r--r--examples/stm32f3/src/bin/button_events.rs12
-rw-r--r--examples/stm32f3/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs4
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f334/Cargo.toml2
-rw-r--r--examples/stm32f334/src/bin/adc.rs14
-rw-r--r--examples/stm32f334/src/bin/opamp.rs14
-rw-r--r--examples/stm32f334/src/bin/pwm.rs2
-rw-r--r--examples/stm32f4/Cargo.toml4
-rw-r--r--examples/stm32f4/src/bin/adc.rs12
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs35
-rw-r--r--examples/stm32f4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f4/src/bin/eth.rs14
-rw-r--r--examples/stm32f4/src/bin/eth_compliance_test.rs14
-rw-r--r--examples/stm32f4/src/bin/eth_w5500.rs10
-rw-r--r--examples/stm32f4/src/bin/flash_async.rs2
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_async.rs135
-rw-r--r--examples/stm32f4/src/bin/i2c_slave_blocking.rs132
-rw-r--r--examples/stm32f4/src/bin/input_capture.rs2
-rw-r--r--examples/stm32f4/src/bin/mco.rs18
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs4
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs4
-rw-r--r--examples/stm32f4/src/bin/pwm_input.rs2
-rw-r--r--examples/stm32f4/src/bin/rtc.rs6
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs42
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs4
-rw-r--r--examples/stm32f4/src/bin/usb_hid_keyboard.rs91
-rw-r--r--examples/stm32f4/src/bin/usb_hid_mouse.rs60
-rw-r--r--examples/stm32f4/src/bin/usb_raw.rs2
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f4/src/bin/usb_uac_speaker.rs4
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm.rs4
-rw-r--r--examples/stm32f469/Cargo.toml2
-rw-r--r--examples/stm32f469/src/bin/dsi_bsp.rs18
-rw-r--r--examples/stm32f7/Cargo.toml2
-rw-r--r--examples/stm32f7/src/bin/adc.rs6
-rw-r--r--examples/stm32f7/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f7/src/bin/can.rs2
-rw-r--r--examples/stm32f7/src/bin/cryp.rs4
-rw-r--r--examples/stm32f7/src/bin/eth.rs14
-rw-r--r--examples/stm32f7/src/bin/hash.rs2
-rw-r--r--examples/stm32f7/src/bin/pwm.rs61
-rw-r--r--examples/stm32f7/src/bin/pwm_ringbuffer.rs153
-rw-r--r--examples/stm32f7/src/bin/qspi.rs2
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs15
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32g0/Cargo.toml2
-rw-r--r--examples/stm32g0/src/bin/adc.rs5
-rw-r--r--examples/stm32g0/src/bin/adc_oversampling.rs17
-rw-r--r--examples/stm32g0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32g0/src/bin/hf_timer.rs4
-rw-r--r--examples/stm32g0/src/bin/input_capture.rs4
-rw-r--r--examples/stm32g0/src/bin/onewire_ds18b20.rs2
-rw-r--r--examples/stm32g0/src/bin/pwm_complementary.rs2
-rw-r--r--examples/stm32g0/src/bin/pwm_input.rs2
-rw-r--r--examples/stm32g0/src/bin/rtc.rs6
-rw-r--r--examples/stm32g0/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32g4/Cargo.toml17
-rw-r--r--examples/stm32g4/src/bin/adc.rs12
-rw-r--r--examples/stm32g4/src/bin/adc_differential.rs11
-rw-r--r--examples/stm32g4/src/bin/adc_dma.rs8
-rw-r--r--examples/stm32g4/src/bin/adc_injected_and_regular.rs154
-rw-r--r--examples/stm32g4/src/bin/adc_oversampling.rs18
-rw-r--r--examples/stm32g4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32g4/src/bin/can.rs2
-rw-r--r--examples/stm32g4/src/bin/usb_c_pd.rs6
-rw-r--r--examples/stm32g4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h5/Cargo.toml4
-rw-r--r--examples/stm32h5/src/bin/adc.rs8
-rw-r--r--examples/stm32h5/src/bin/adc_dma.rs11
-rw-r--r--examples/stm32h5/src/bin/backup_sram.rs31
-rw-r--r--examples/stm32h5/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h5/src/bin/can.rs2
-rw-r--r--examples/stm32h5/src/bin/dts.rs2
-rw-r--r--examples/stm32h5/src/bin/eth.rs14
-rw-r--r--examples/stm32h5/src/bin/mco.rs29
-rw-r--r--examples/stm32h5/src/bin/sai.rs2
-rw-r--r--examples/stm32h5/src/bin/stop.rs20
-rw-r--r--examples/stm32h5/src/bin/usb_c_pd.rs6
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h5/src/bin/usb_uac_speaker.rs4
-rw-r--r--examples/stm32h7/Cargo.toml4
-rw-r--r--examples/stm32h7/src/bin/adc.rs8
-rw-r--r--examples/stm32h7/src/bin/adc_dma.rs2
-rw-r--r--examples/stm32h7/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h7/src/bin/camera.rs13
-rw-r--r--examples/stm32h7/src/bin/can.rs2
-rw-r--r--examples/stm32h7/src/bin/dac.rs2
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs2
-rw-r--r--examples/stm32h7/src/bin/eth.rs14
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs16
-rw-r--r--examples/stm32h7/src/bin/eth_client_mii.rs16
-rw-r--r--examples/stm32h7/src/bin/flash_async.rs84
-rw-r--r--examples/stm32h7/src/bin/fmc.rs2
-rw-r--r--examples/stm32h7/src/bin/i2c_shared.rs2
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs2
-rw-r--r--examples/stm32h7/src/bin/mco.rs10
-rw-r--r--examples/stm32h7/src/bin/multiprio.rs4
-rw-r--r--examples/stm32h7/src/bin/pwm.rs2
-rw-r--r--examples/stm32h7/src/bin/rng.rs2
-rw-r--r--examples/stm32h7/src/bin/rtc.rs6
-rw-r--r--examples/stm32h7/src/bin/sai.rs2
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs15
-rw-r--r--examples/stm32h7/src/bin/spi.rs4
-rw-r--r--examples/stm32h7/src/bin/spi_bdma.rs4
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs4
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h723/Cargo.toml2
-rw-r--r--examples/stm32h723/src/bin/spdifrx.rs7
-rw-r--r--examples/stm32h735/Cargo.toml2
-rw-r--r--examples/stm32h735/src/bin/ltdc.rs4
-rw-r--r--examples/stm32h742/Cargo.toml2
-rw-r--r--examples/stm32h742/src/bin/qspi.rs2
-rw-r--r--examples/stm32h755cm4/Cargo.toml4
-rw-r--r--examples/stm32h755cm4/src/bin/blinky.rs2
-rw-r--r--examples/stm32h755cm4/src/bin/intercore.rs6
-rw-r--r--examples/stm32h755cm7/Cargo.toml4
-rw-r--r--examples/stm32h755cm7/src/bin/blinky.rs2
-rw-r--r--examples/stm32h755cm7/src/bin/intercore.rs4
-rw-r--r--examples/stm32h7b0/Cargo.toml4
-rw-r--r--examples/stm32h7b0/src/bin/ospi_memory_mapped.rs2
-rw-r--r--examples/stm32h7rs/Cargo.toml4
-rw-r--r--examples/stm32h7rs/src/bin/blinky.rs2
-rw-r--r--examples/stm32h7rs/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h7rs/src/bin/can.rs2
-rw-r--r--examples/stm32h7rs/src/bin/eth.rs14
-rw-r--r--examples/stm32h7rs/src/bin/mco.rs10
-rw-r--r--examples/stm32h7rs/src/bin/multiprio.rs4
-rw-r--r--examples/stm32h7rs/src/bin/rng.rs2
-rw-r--r--examples/stm32h7rs/src/bin/rtc.rs6
-rw-r--r--examples/stm32h7rs/src/bin/spi.rs2
-rw-r--r--examples/stm32h7rs/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32h7rs/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h7rs/src/bin/xspi_memory_mapped.rs2
-rw-r--r--examples/stm32l0/Cargo.toml2
-rw-r--r--examples/stm32l0/src/bin/adc.rs5
-rw-r--r--examples/stm32l0/src/bin/button_exti.rs11
-rw-r--r--examples/stm32l0/src/bin/dds.rs2
-rw-r--r--examples/stm32l0/src/bin/eeprom.rs2
-rw-r--r--examples/stm32l0/src/bin/raw_spawn.rs4
-rw-r--r--examples/stm32l0/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32l1/Cargo.toml2
-rw-r--r--examples/stm32l1/src/bin/eeprom.rs2
-rw-r--r--examples/stm32l1/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32l4/Cargo.toml2
-rw-r--r--examples/stm32l4/src/bin/adc.rs11
-rw-r--r--examples/stm32l4/src/bin/adc_dma.rs48
-rw-r--r--examples/stm32l4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32l4/src/bin/can.rs2
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs2
-rw-r--r--examples/stm32l4/src/bin/mco.rs10
-rw-r--r--examples/stm32l4/src/bin/rng.rs2
-rw-r--r--examples/stm32l4/src/bin/rtc.rs6
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs19
-rw-r--r--examples/stm32l4/src/bin/spi_dma.rs4
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32l432/Cargo.toml2
-rw-r--r--examples/stm32l5/Cargo.toml4
-rw-r--r--examples/stm32l5/src/bin/button_exti.rs10
-rw-r--r--examples/stm32l5/src/bin/rng.rs2
-rw-r--r--examples/stm32l5/src/bin/stop.rs20
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs4
-rw-r--r--examples/stm32l5/src/bin/usb_hid_mouse.rs60
-rw-r--r--examples/stm32l5/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32n6/.cargo/config.toml8
-rw-r--r--examples/stm32n6/Cargo.toml80
-rw-r--r--examples/stm32n6/build.rs5
-rw-r--r--examples/stm32n6/memory.x5
-rw-r--r--examples/stm32n6/src/bin/blinky.rs42
-rw-r--r--examples/stm32n6/src/bin/crc.rs31
-rw-r--r--examples/stm32n6/src/bin/hash.rs78
-rw-r--r--examples/stm32u0/.cargo/config.toml4
-rw-r--r--examples/stm32u0/Cargo.toml8
-rw-r--r--examples/stm32u0/src/bin/adc.rs9
-rw-r--r--examples/stm32u0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32u0/src/bin/lcd.rs412
-rw-r--r--examples/stm32u0/src/bin/rng.rs2
-rw-r--r--examples/stm32u0/src/bin/rtc.rs6
-rw-r--r--examples/stm32u0/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32u5/Cargo.toml2
-rw-r--r--examples/stm32u5/src/bin/adc.rs49
-rw-r--r--examples/stm32u5/src/bin/ltdc.rs6
-rw-r--r--examples/stm32u5/src/bin/usb_hs_serial.rs4
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32wb/Cargo.toml8
-rw-r--r--examples/stm32wb/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wb/src/bin/eddystone_beacon.rs120
-rw-r--r--examples/stm32wb/src/bin/gatt_server.rs120
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs49
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs194
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs42
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_ble.rs21
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs14
-rw-r--r--examples/stm32wba/Cargo.toml10
-rw-r--r--examples/stm32wba/src/bin/adc.rs23
-rw-r--r--examples/stm32wba/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wba/src/bin/mac_ffd.rs58
-rw-r--r--examples/stm32wba/src/bin/pwm.rs2
-rw-r--r--examples/stm32wba/src/bin/rtc.rs62
-rw-r--r--examples/stm32wba6/Cargo.toml2
-rw-r--r--examples/stm32wba6/src/bin/adc.rs50
-rw-r--r--examples/stm32wba6/src/bin/blinky.rs33
-rw-r--r--examples/stm32wba6/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wba6/src/bin/pwm.rs2
-rw-r--r--examples/stm32wba6/src/bin/rtc.rs62
-rw-r--r--examples/stm32wba6/src/bin/usb_hs_serial.rs4
-rw-r--r--examples/stm32wl/Cargo.toml2
-rw-r--r--examples/stm32wl/src/bin/adc.rs8
-rw-r--r--examples/stm32wl/src/bin/blinky.rs2
-rw-r--r--examples/stm32wl/src/bin/button.rs2
-rw-r--r--examples/stm32wl/src/bin/button_exti.rs11
-rw-r--r--examples/stm32wl/src/bin/flash.rs2
-rw-r--r--examples/stm32wl/src/bin/random.rs2
-rw-r--r--examples/stm32wl/src/bin/rtc.rs4
-rw-r--r--examples/stm32wl/src/bin/uart_async.rs2
-rw-r--r--examples/stm32wle5/.cargo/config.toml9
-rw-r--r--examples/stm32wle5/Cargo.toml38
-rw-r--r--examples/stm32wle5/README.md52
-rw-r--r--examples/stm32wle5/build.rs5
-rw-r--r--examples/stm32wle5/src/bin/adc.rs67
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs58
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs64
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs77
-rw-r--r--examples/stm32wle5/stm32wle5.code-workspace13
-rw-r--r--examples/wasm/Cargo.toml2
470 files changed, 8540 insertions, 1443 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index f5f89ecb5..ccaa24e3e 100644
--- a/examples/boot/application/nrf/Cargo.toml
+++ b/examples/boot/application/nrf/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-nrf-examples" 3name = "embassy-boot-nrf-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -9,9 +9,9 @@ publish = false
9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] }
11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] }
12embassy-nrf = { version = "0.8.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } 12embassy-nrf = { version = "0.9.0", path = "../../../../embassy-nrf", features = ["gpiote", ] }
13embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] } 13embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] }
14embassy-boot-nrf = { version = "0.9.0", path = "../../../../embassy-boot-nrf", features = [] } 14embassy-boot-nrf = { version = "0.10.0", path = "../../../../embassy-boot-nrf", features = [] }
15embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } 15embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
16 16
17defmt = { version = "1.0.1", optional = true } 17defmt = { version = "1.0.1", optional = true }
@@ -33,12 +33,14 @@ defmt = [
33 "embassy-boot-nrf/defmt", 33 "embassy-boot-nrf/defmt",
34 "embassy-sync/defmt", 34 "embassy-sync/defmt",
35] 35]
36nrf54 = ["embassy-nrf/time-driver-grtc"]
36 37
37[package.metadata.embassy] 38[package.metadata.embassy]
38build = [ 39build = [
39 { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" }, 40 { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" },
40 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" }, 41 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" },
41 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" }, 42 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" },
42 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" }, 43 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" },
43 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" } 44 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "embassy-nrf/time-driver-rtc1", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" },
45 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf54l15-app-s", "nrf54", "skip-include"], artifact-dir = "out/examples/boot/nrf54l15" }
44] 46]
diff --git a/examples/boot/application/nrf/README.md b/examples/boot/application/nrf/README.md
index 9d6d20336..c92ccb358 100644
--- a/examples/boot/application/nrf/README.md
+++ b/examples/boot/application/nrf/README.md
@@ -22,7 +22,7 @@ cp memory-bl.x ../../bootloader/nrf/memory.x
22# Flash bootloader 22# Flash bootloader
23cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --release --chip nRF52840_xxAA 23cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --release --chip nRF52840_xxAA
24# Build 'b' 24# Build 'b'
25cargo build --release --bin b --features embassy-nrf/nrf52840 25cargo build --release --bin b --features embassy-nrf/nrf52840,time-driver-rtc1
26# Generate binary for 'b' 26# Generate binary for 'b'
27cargo objcopy --release --bin b --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi -- -O binary b.bin 27cargo objcopy --release --bin b --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi -- -O binary b.bin
28``` 28```
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs
index 2c1d1a7bb..035ffe214 100644
--- a/examples/boot/application/nrf/src/bin/a.rs
+++ b/examples/boot/application/nrf/src/bin/a.rs
@@ -23,10 +23,21 @@ static APP_B: &[u8] = include_bytes!("../../b.bin");
23async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default()); 24 let p = embassy_nrf::init(Default::default());
25 25
26 #[cfg(not(feature = "nrf54"))]
26 let mut button = Input::new(p.P0_11, Pull::Up); 27 let mut button = Input::new(p.P0_11, Pull::Up);
28 #[cfg(not(feature = "nrf54"))]
27 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); 29 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
30 #[cfg(not(feature = "nrf54"))]
28 let mut led_reverted = Output::new(p.P0_14, Level::High, OutputDrive::Standard); 31 let mut led_reverted = Output::new(p.P0_14, Level::High, OutputDrive::Standard);
29 32
33 // nRF54 DK
34 #[cfg(feature = "nrf54")]
35 let mut button = Input::new(p.P1_13, Pull::Up);
36 #[cfg(feature = "nrf54")]
37 let mut led = Output::new(p.P1_14, Level::Low, OutputDrive::Standard);
38 #[cfg(feature = "nrf54")]
39 let mut led_reverted = Output::new(p.P2_09, Level::High, OutputDrive::Standard);
40
30 //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); 41 //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard);
31 //let mut button = Input::new(p.P1_02, Pull::Up); 42 //let mut button = Input::new(p.P1_02, Pull::Up);
32 43
@@ -40,8 +51,12 @@ async fn main(_spawner: Spawner) {
40 // the watchdog will cause the device to reset as per its configured timeout in the bootloader. 51 // the watchdog will cause the device to reset as per its configured timeout in the bootloader.
41 // This helps is avoid a situation where new firmware might be bad and block our executor. 52 // This helps is avoid a situation where new firmware might be bad and block our executor.
42 // If firmware is bad in this way then the bootloader will revert to any previous version. 53 // If firmware is bad in this way then the bootloader will revert to any previous version.
43 let wdt_config = wdt::Config::try_new(&p.WDT).unwrap(); 54 #[cfg(feature = "nrf54")]
44 let (_wdt, [_wdt_handle]) = match Watchdog::try_new(p.WDT, wdt_config) { 55 let wdt = p.WDT0;
56 #[cfg(not(feature = "nrf54"))]
57 let wdt = p.WDT;
58 let wdt_config = wdt::Config::try_new(&wdt).unwrap();
59 let (_wdt, [_wdt_handle]) = match Watchdog::try_new(wdt, wdt_config) {
45 Ok(x) => x, 60 Ok(x) => x,
46 Err(_) => { 61 Err(_) => {
47 // Watchdog already active with the wrong number of handles, waiting for it to timeout... 62 // Watchdog already active with the wrong number of handles, waiting for it to timeout...
@@ -51,11 +66,15 @@ async fn main(_spawner: Spawner) {
51 } 66 }
52 }; 67 };
53 68
69 // RRAMC for nRF54
70 #[cfg(feature = "nrf54")]
71 let nvmc = Nvmc::new(p.RRAMC);
72 #[cfg(not(feature = "nrf54"))]
54 let nvmc = Nvmc::new(p.NVMC); 73 let nvmc = Nvmc::new(p.NVMC);
55 let nvmc = Mutex::new(BlockingAsync::new(nvmc)); 74 let nvmc = Mutex::new(BlockingAsync::new(nvmc));
56 75
57 let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc); 76 let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc);
58 let mut magic = [0; 4]; 77 let mut magic = [0; 16];
59 let mut updater = FirmwareUpdater::new(config, &mut magic); 78 let mut updater = FirmwareUpdater::new(config, &mut magic);
60 let state = updater.get_state().await.unwrap(); 79 let state = updater.get_state().await.unwrap();
61 if state == State::Revert { 80 if state == State::Revert {
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs
index de97b6a22..6718df5a1 100644
--- a/examples/boot/application/nrf/src/bin/b.rs
+++ b/examples/boot/application/nrf/src/bin/b.rs
@@ -10,11 +10,15 @@ use panic_reset as _;
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 #[cfg(not(feature = "nrf54"))]
13 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); 14 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
14 // let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); 15 // let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard);
15 16
16 // nRF91 DK 17 // nRF91 DK
17 // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard); 18 // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard);
19 // nrf54l15 dk
20 #[cfg(feature = "nrf54")]
21 let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard);
18 22
19 loop { 23 loop {
20 led.set_high(); 24 led.set_high();
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml
index d86386b00..292d1abec 100644
--- a/examples/boot/application/rp/Cargo.toml
+++ b/examples/boot/application/rp/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-rp-examples" 3name = "embassy-boot-rp-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -9,8 +9,8 @@ publish = false
9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] }
12embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } 12embassy-rp = { version = "0.9.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] }
13embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] } 13embassy-boot-rp = { version = "0.9.0", path = "../../../../embassy-boot-rp", features = [] }
14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
15 15
16defmt = "1.0.1" 16defmt = "1.0.1"
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml
index cd5f422fc..2dc75d939 100644
--- a/examples/boot/application/stm32f3/Cargo.toml
+++ b/examples/boot/application/stm32f3/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32f3-examples" 3name = "embassy-boot-stm32f3-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs
index b608b2e01..da3cbf1e6 100644
--- a/examples/boot/application/stm32f3/src/bin/a.rs
+++ b/examples/boot/application/stm32f3/src/bin/a.rs
@@ -6,12 +6,18 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use panic_reset as _; 14use panic_reset as _;
14 15
16bind_interrupts!(
17 pub struct Irqs{
18 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
19});
20
15#[cfg(feature = "skip-include")] 21#[cfg(feature = "skip-include")]
16static APP_B: &[u8] = &[0, 1, 2, 3]; 22static APP_B: &[u8] = &[0, 1, 2, 3];
17#[cfg(not(feature = "skip-include"))] 23#[cfg(not(feature = "skip-include"))]
@@ -23,7 +29,7 @@ async fn main(_spawner: Spawner) {
23 let flash = Flash::new_blocking(p.FLASH); 29 let flash = Flash::new_blocking(p.FLASH);
24 let flash = Mutex::new(BlockingAsync::new(flash)); 30 let flash = Mutex::new(BlockingAsync::new(flash));
25 31
26 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 32 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
27 33
28 let mut led = Output::new(p.PA5, Level::Low, Speed::Low); 34 let mut led = Output::new(p.PA5, Level::Low, Speed::Low);
29 led.set_high(); 35 led.set_high();
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml
index c3921a166..5c372fb19 100644
--- a/examples/boot/application/stm32f7/Cargo.toml
+++ b/examples/boot/application/stm32f7/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32f7-examples" 3name = "embassy-boot-stm32f7-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs
index 172b4c235..62f1da269 100644
--- a/examples/boot/application/stm32f7/src/bin/a.rs
+++ b/examples/boot/application/stm32f7/src/bin/a.rs
@@ -7,9 +7,10 @@ use core::cell::RefCell;
7use defmt_rtt::*; 7use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pull, Speed};
13use embassy_stm32::{bind_interrupts, interrupt};
13use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
14use embedded_storage::nor_flash::NorFlash; 15use embedded_storage::nor_flash::NorFlash;
15use panic_reset as _; 16use panic_reset as _;
@@ -19,13 +20,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
19#[cfg(not(feature = "skip-include"))] 20#[cfg(not(feature = "skip-include"))]
20static APP_B: &[u8] = include_bytes!("../../b.bin"); 21static APP_B: &[u8] = include_bytes!("../../b.bin");
21 22
23bind_interrupts!(
24 pub struct Irqs{
25 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
26});
27
22#[embassy_executor::main] 28#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 29async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(Default::default()); 30 let p = embassy_stm32::init(Default::default());
25 let flash = Flash::new_blocking(p.FLASH); 31 let flash = Flash::new_blocking(p.FLASH);
26 let flash = Mutex::new(RefCell::new(flash)); 32 let flash = Mutex::new(RefCell::new(flash));
27 33
28 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 34 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
29 35
30 let mut led = Output::new(p.PB7, Level::Low, Speed::Low); 36 let mut led = Output::new(p.PB7, Level::Low, Speed::Low);
31 led.set_high(); 37 led.set_high();
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml
index ca186d4d9..641a2ba96 100644
--- a/examples/boot/application/stm32h7/Cargo.toml
+++ b/examples/boot/application/stm32h7/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32h7-examples" 3name = "embassy-boot-stm32h7-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs
index c1b1a267a..226971e02 100644
--- a/examples/boot/application/stm32h7/src/bin/a.rs
+++ b/examples/boot/application/stm32h7/src/bin/a.rs
@@ -7,13 +7,19 @@ use core::cell::RefCell;
7use defmt_rtt::*; 7use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pull, Speed};
13use embassy_stm32::{bind_interrupts, interrupt};
13use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
14use embedded_storage::nor_flash::NorFlash; 15use embedded_storage::nor_flash::NorFlash;
15use panic_reset as _; 16use panic_reset as _;
16 17
18bind_interrupts!(
19 pub struct Irqs{
20 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
21});
22
17#[cfg(feature = "skip-include")] 23#[cfg(feature = "skip-include")]
18static APP_B: &[u8] = &[0, 1, 2, 3]; 24static APP_B: &[u8] = &[0, 1, 2, 3];
19#[cfg(not(feature = "skip-include"))] 25#[cfg(not(feature = "skip-include"))]
@@ -25,7 +31,7 @@ async fn main(_spawner: Spawner) {
25 let flash = Flash::new_blocking(p.FLASH); 31 let flash = Flash::new_blocking(p.FLASH);
26 let flash = Mutex::new(RefCell::new(flash)); 32 let flash = Mutex::new(RefCell::new(flash));
27 33
28 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 34 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
29 35
30 let mut led = Output::new(p.PB14, Level::Low, Speed::Low); 36 let mut led = Output::new(p.PB14, Level::Low, Speed::Low);
31 led.set_high(); 37 led.set_high();
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml
index be08956f1..4a168be15 100644
--- a/examples/boot/application/stm32l0/Cargo.toml
+++ b/examples/boot/application/stm32l0/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32l0-examples" 3name = "embassy-boot-stm32l0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs
index dcc10e5c6..0aa723eaa 100644
--- a/examples/boot/application/stm32l0/src/bin/a.rs
+++ b/examples/boot/application/stm32l0/src/bin/a.rs
@@ -6,13 +6,19 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use embassy_time::Timer; 14use embassy_time::Timer;
14use panic_reset as _; 15use panic_reset as _;
15 16
17bind_interrupts!(
18 pub struct Irqs{
19 EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>;
20});
21
16#[cfg(feature = "skip-include")] 22#[cfg(feature = "skip-include")]
17static APP_B: &[u8] = &[0, 1, 2, 3]; 23static APP_B: &[u8] = &[0, 1, 2, 3];
18#[cfg(not(feature = "skip-include"))] 24#[cfg(not(feature = "skip-include"))]
@@ -24,7 +30,7 @@ async fn main(_spawner: Spawner) {
24 let flash = Flash::new_blocking(p.FLASH); 30 let flash = Flash::new_blocking(p.FLASH);
25 let flash = Mutex::new(BlockingAsync::new(flash)); 31 let flash = Mutex::new(BlockingAsync::new(flash));
26 32
27 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 33 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
28 34
29 let mut led = Output::new(p.PB5, Level::Low, Speed::Low); 35 let mut led = Output::new(p.PB5, Level::Low, Speed::Low);
30 36
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml
index 207eed733..af2cb3881 100644
--- a/examples/boot/application/stm32l1/Cargo.toml
+++ b/examples/boot/application/stm32l1/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32l1-examples" 3name = "embassy-boot-stm32l1-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs
index dcc10e5c6..7ad7046fb 100644
--- a/examples/boot/application/stm32l1/src/bin/a.rs
+++ b/examples/boot/application/stm32l1/src/bin/a.rs
@@ -6,9 +6,10 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use embassy_time::Timer; 14use embassy_time::Timer;
14use panic_reset as _; 15use panic_reset as _;
@@ -18,13 +19,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
18#[cfg(not(feature = "skip-include"))] 19#[cfg(not(feature = "skip-include"))]
19static APP_B: &[u8] = include_bytes!("../../b.bin"); 20static APP_B: &[u8] = include_bytes!("../../b.bin");
20 21
22bind_interrupts!(
23 pub struct Irqs{
24 EXTI2 => exti::InterruptHandler<interrupt::typelevel::EXTI2>;
25});
26
21#[embassy_executor::main] 27#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
23 let p = embassy_stm32::init(Default::default()); 29 let p = embassy_stm32::init(Default::default());
24 let flash = Flash::new_blocking(p.FLASH); 30 let flash = Flash::new_blocking(p.FLASH);
25 let flash = Mutex::new(BlockingAsync::new(flash)); 31 let flash = Mutex::new(BlockingAsync::new(flash));
26 32
27 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 33 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
28 34
29 let mut led = Output::new(p.PB5, Level::Low, Speed::Low); 35 let mut led = Output::new(p.PB5, Level::Low, Speed::Low);
30 36
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml
index 22b9642d8..032e934aa 100644
--- a/examples/boot/application/stm32l4/Cargo.toml
+++ b/examples/boot/application/stm32l4/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32l4-examples" 3name = "embassy-boot-stm32l4-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs
index 7f8015c04..4edd338c5 100644
--- a/examples/boot/application/stm32l4/src/bin/a.rs
+++ b/examples/boot/application/stm32l4/src/bin/a.rs
@@ -6,9 +6,10 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use panic_reset as _; 14use panic_reset as _;
14 15
@@ -17,13 +18,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
17#[cfg(not(feature = "skip-include"))] 18#[cfg(not(feature = "skip-include"))]
18static APP_B: &[u8] = include_bytes!("../../b.bin"); 19static APP_B: &[u8] = include_bytes!("../../b.bin");
19 20
21bind_interrupts!(
22 pub struct Irqs{
23 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
24});
25
20#[embassy_executor::main] 26#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
22 let p = embassy_stm32::init(Default::default()); 28 let p = embassy_stm32::init(Default::default());
23 let flash = Flash::new_blocking(p.FLASH); 29 let flash = Flash::new_blocking(p.FLASH);
24 let flash = Mutex::new(BlockingAsync::new(flash)); 30 let flash = Mutex::new(BlockingAsync::new(flash));
25 31
26 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 32 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
27 33
28 let mut led = Output::new(p.PB14, Level::Low, Speed::Low); 34 let mut led = Output::new(p.PB14, Level::Low, Speed::Low);
29 led.set_high(); 35 led.set_high();
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml
index e2be4f470..ea4c26681 100644
--- a/examples/boot/application/stm32wb-dfu/Cargo.toml
+++ b/examples/boot/application/stm32wb-dfu/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32wb-dfu-examples" 3name = "embassy-boot-stm32wb-dfu-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs
index 5e7b71f5a..1ae28bf3a 100644
--- a/examples/boot/application/stm32wb-dfu/src/main.rs
+++ b/examples/boot/application/stm32wb-dfu/src/main.rs
@@ -13,9 +13,9 @@ use embassy_stm32::usb::{self, Driver};
13use embassy_stm32::{bind_interrupts, peripherals}; 13use embassy_stm32::{bind_interrupts, peripherals};
14use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
15use embassy_time::Duration; 15use embassy_time::Duration;
16use embassy_usb::{msos, Builder}; 16use embassy_usb::{Builder, msos};
17use embassy_usb_dfu::consts::DfuAttributes; 17use embassy_usb_dfu::consts::DfuAttributes;
18use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; 18use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu};
19use panic_reset as _; 19use panic_reset as _;
20 20
21bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml
index 6f4213b2c..d6f7dc3b6 100644
--- a/examples/boot/application/stm32wba-dfu/Cargo.toml
+++ b/examples/boot/application/stm32wba-dfu/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32wba-dfu-examples" 3name = "embassy-boot-stm32wba-dfu-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32wba-dfu/src/main.rs b/examples/boot/application/stm32wba-dfu/src/main.rs
index bf17a7150..8adb2e7c0 100644
--- a/examples/boot/application/stm32wba-dfu/src/main.rs
+++ b/examples/boot/application/stm32wba-dfu/src/main.rs
@@ -12,9 +12,9 @@ use embassy_stm32::usb::{self, Driver};
12use embassy_stm32::{bind_interrupts, peripherals}; 12use embassy_stm32::{bind_interrupts, peripherals};
13use embassy_sync::blocking_mutex::Mutex; 13use embassy_sync::blocking_mutex::Mutex;
14use embassy_time::Duration; 14use embassy_time::Duration;
15use embassy_usb::{msos, Builder}; 15use embassy_usb::{Builder, msos};
16use embassy_usb_dfu::consts::DfuAttributes; 16use embassy_usb_dfu::consts::DfuAttributes;
17use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; 17use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu};
18use panic_reset as _; 18use panic_reset as _;
19 19
20bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml
index 8d1446ba9..c7fa811c9 100644
--- a/examples/boot/application/stm32wl/Cargo.toml
+++ b/examples/boot/application/stm32wl/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-boot-stm32wl-examples" 3name = "embassy-boot-stm32wl-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs
index e4526927f..58063eb50 100644
--- a/examples/boot/application/stm32wl/src/bin/a.rs
+++ b/examples/boot/application/stm32wl/src/bin/a.rs
@@ -8,10 +8,10 @@ use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_embedded_hal::adapter::BlockingAsync; 9use embassy_embedded_hal::adapter::BlockingAsync;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::exti::ExtiInput; 11use embassy_stm32::exti::{self, ExtiInput};
12use embassy_stm32::flash::{Flash, WRITE_SIZE}; 12use embassy_stm32::flash::{Flash, WRITE_SIZE};
13use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 13use embassy_stm32::gpio::{Level, Output, Pull, Speed};
14use embassy_stm32::SharedData; 14use embassy_stm32::{SharedData, bind_interrupts, interrupt};
15use embassy_sync::mutex::Mutex; 15use embassy_sync::mutex::Mutex;
16use panic_reset as _; 16use panic_reset as _;
17 17
@@ -20,6 +20,11 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
20#[cfg(not(feature = "skip-include"))] 20#[cfg(not(feature = "skip-include"))]
21static APP_B: &[u8] = include_bytes!("../../b.bin"); 21static APP_B: &[u8] = include_bytes!("../../b.bin");
22 22
23bind_interrupts!(
24 pub struct Irqs{
25 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
26});
27
23#[unsafe(link_section = ".shared_data")] 28#[unsafe(link_section = ".shared_data")]
24static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 29static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
25 30
@@ -29,7 +34,7 @@ async fn main(_spawner: Spawner) {
29 let flash = Flash::new_blocking(p.FLASH); 34 let flash = Flash::new_blocking(p.FLASH);
30 let flash = Mutex::new(BlockingAsync::new(flash)); 35 let flash = Mutex::new(BlockingAsync::new(flash));
31 36
32 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 37 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
33 38
34 let mut led = Output::new(p.PB9, Level::Low, Speed::Low); 39 let mut led = Output::new(p.PB9, Level::Low, Speed::Low);
35 led.set_high(); 40 led.set_high();
diff --git a/examples/boot/application/stm32wl/src/bin/b.rs b/examples/boot/application/stm32wl/src/bin/b.rs
index 6016a9555..952e94a58 100644
--- a/examples/boot/application/stm32wl/src/bin/b.rs
+++ b/examples/boot/application/stm32wl/src/bin/b.rs
@@ -6,8 +6,8 @@ use core::mem::MaybeUninit;
6#[cfg(feature = "defmt")] 6#[cfg(feature = "defmt")]
7use defmt_rtt::*; 7use defmt_rtt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::SharedData; 9use embassy_stm32::SharedData;
10use embassy_stm32::gpio::{Level, Output, Speed};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use panic_reset as _; 12use panic_reset as _;
13 13
diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml
index 72b7114d4..59fc6e4ed 100644
--- a/examples/boot/bootloader/nrf/Cargo.toml
+++ b/examples/boot/bootloader/nrf/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "nrf-bootloader-example" 3name = "nrf-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Bootloader for nRF chips" 5description = "Bootloader for nRF chips"
@@ -27,6 +27,7 @@ defmt = [
27softdevice = [ 27softdevice = [
28 "embassy-boot-nrf/softdevice", 28 "embassy-boot-nrf/softdevice",
29] 29]
30nrf54 = []
30 31
31[profile.dev] 32[profile.dev]
32debug = 2 33debug = 2
@@ -65,5 +66,6 @@ build = [
65 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] }, 66 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] },
66 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] }, 67 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] },
67 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] }, 68 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] },
68 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] } 69 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] },
70 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf54l15-app-s", "nrf54"] }
69] 71]
diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs
index b849a0df3..9ba57e81b 100644
--- a/examples/boot/bootloader/nrf/src/main.rs
+++ b/examples/boot/bootloader/nrf/src/main.rs
@@ -28,7 +28,10 @@ fn main() -> ! {
28 wdt_config.action_during_sleep = SleepConfig::RUN; 28 wdt_config.action_during_sleep = SleepConfig::RUN;
29 wdt_config.action_during_debug_halt = HaltConfig::PAUSE; 29 wdt_config.action_during_debug_halt = HaltConfig::PAUSE;
30 30
31 #[cfg(not(feature = "nrf54"))]
31 let flash = WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, wdt_config); 32 let flash = WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, wdt_config);
33 #[cfg(feature = "nrf54")]
34 let flash = WatchdogFlash::start(Nvmc::new(p.RRAMC), p.WDT0, wdt_config);
32 let flash = Mutex::new(RefCell::new(flash)); 35 let flash = Mutex::new(RefCell::new(flash));
33 36
34 let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash); 37 let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash);
@@ -38,8 +41,8 @@ fn main() -> ! {
38 unsafe { bl.load(active_offset) } 41 unsafe { bl.load(active_offset) }
39} 42}
40 43
41#[no_mangle] 44#[unsafe(no_mangle)]
42#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 45#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
43unsafe extern "C" fn HardFault() { 46unsafe extern "C" fn HardFault() {
44 cortex_m::peripheral::SCB::sys_reset(); 47 cortex_m::peripheral::SCB::sys_reset();
45} 48}
@@ -47,7 +50,7 @@ unsafe extern "C" fn HardFault() {
47#[exception] 50#[exception]
48unsafe fn DefaultHandler(_: i16) -> ! { 51unsafe fn DefaultHandler(_: i16) -> ! {
49 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 52 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
50 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 53 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
51 54
52 panic!("DefaultHandler #{:?}", irqn); 55 panic!("DefaultHandler #{:?}", irqn);
53} 56}
diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml
index 93a1c4edf..188bcab36 100644
--- a/examples/boot/bootloader/rp/Cargo.toml
+++ b/examples/boot/bootloader/rp/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "rp-bootloader-example" 3name = "rp-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example bootloader for RP2040 chips" 5description = "Example bootloader for RP2040 chips"
diff --git a/examples/boot/bootloader/rp/src/main.rs b/examples/boot/bootloader/rp/src/main.rs
index 25b1657b8..7ebefd374 100644
--- a/examples/boot/bootloader/rp/src/main.rs
+++ b/examples/boot/bootloader/rp/src/main.rs
@@ -34,8 +34,8 @@ fn main() -> ! {
34 unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) } 34 unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) }
35} 35}
36 36
37#[no_mangle] 37#[unsafe(no_mangle)]
38#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 38#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
39unsafe extern "C" fn HardFault() { 39unsafe extern "C" fn HardFault() {
40 cortex_m::peripheral::SCB::sys_reset(); 40 cortex_m::peripheral::SCB::sys_reset();
41} 41}
@@ -43,7 +43,7 @@ unsafe extern "C" fn HardFault() {
43#[exception] 43#[exception]
44unsafe fn DefaultHandler(_: i16) -> ! { 44unsafe fn DefaultHandler(_: i16) -> ! {
45 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 45 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
46 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 46 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
47 47
48 panic!("DefaultHandler #{:?}", irqn); 48 panic!("DefaultHandler #{:?}", irqn);
49} 49}
diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
index 95ca20a59..cf68921dc 100644
--- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
+++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "stm32-bootloader-dual-bank-flash-example" 3name = "stm32-bootloader-dual-bank-flash-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example bootloader for dual-bank flash STM32 chips" 5description = "Example bootloader for dual-bank flash STM32 chips"
diff --git a/examples/boot/bootloader/stm32-dual-bank/src/main.rs b/examples/boot/bootloader/stm32-dual-bank/src/main.rs
index 4d2e82d26..f0063fb5c 100644
--- a/examples/boot/bootloader/stm32-dual-bank/src/main.rs
+++ b/examples/boot/bootloader/stm32-dual-bank/src/main.rs
@@ -7,7 +7,7 @@ use cortex_m_rt::{entry, exception};
7#[cfg(feature = "defmt")] 7#[cfg(feature = "defmt")]
8use defmt_rtt as _; 8use defmt_rtt as _;
9use embassy_boot_stm32::*; 9use embassy_boot_stm32::*;
10use embassy_stm32::flash::{Flash, BANK1_REGION}; 10use embassy_stm32::flash::{BANK1_REGION, Flash};
11use embassy_sync::blocking_mutex::Mutex; 11use embassy_sync::blocking_mutex::Mutex;
12 12
13#[entry] 13#[entry]
@@ -33,8 +33,8 @@ fn main() -> ! {
33 unsafe { bl.load(BANK1_REGION.base + active_offset) } 33 unsafe { bl.load(BANK1_REGION.base + active_offset) }
34} 34}
35 35
36#[no_mangle] 36#[unsafe(no_mangle)]
37#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 37#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
38unsafe extern "C" fn HardFault() { 38unsafe extern "C" fn HardFault() {
39 cortex_m::peripheral::SCB::sys_reset(); 39 cortex_m::peripheral::SCB::sys_reset();
40} 40}
@@ -42,7 +42,7 @@ unsafe extern "C" fn HardFault() {
42#[exception] 42#[exception]
43unsafe fn DefaultHandler(_: i16) -> ! { 43unsafe fn DefaultHandler(_: i16) -> ! {
44 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 44 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
45 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 45 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
46 46
47 panic!("DefaultHandler #{:?}", irqn); 47 panic!("DefaultHandler #{:?}", irqn);
48} 48}
diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml
index 526637f37..e457310b9 100644
--- a/examples/boot/bootloader/stm32/Cargo.toml
+++ b/examples/boot/bootloader/stm32/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "stm32-bootloader-example" 3name = "stm32-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example bootloader for STM32 chips" 5description = "Example bootloader for STM32 chips"
diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs
index 99a7a6a6b..383ad912d 100644
--- a/examples/boot/bootloader/stm32/src/main.rs
+++ b/examples/boot/bootloader/stm32/src/main.rs
@@ -7,7 +7,7 @@ use cortex_m_rt::{entry, exception};
7#[cfg(feature = "defmt")] 7#[cfg(feature = "defmt")]
8use defmt_rtt as _; 8use defmt_rtt as _;
9use embassy_boot_stm32::*; 9use embassy_boot_stm32::*;
10use embassy_stm32::flash::{Flash, BANK1_REGION}; 10use embassy_stm32::flash::{BANK1_REGION, Flash};
11use embassy_sync::blocking_mutex::Mutex; 11use embassy_sync::blocking_mutex::Mutex;
12 12
13#[entry] 13#[entry]
@@ -32,8 +32,8 @@ fn main() -> ! {
32 unsafe { bl.load(BANK1_REGION.base + active_offset) } 32 unsafe { bl.load(BANK1_REGION.base + active_offset) }
33} 33}
34 34
35#[no_mangle] 35#[unsafe(no_mangle)]
36#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 36#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
37unsafe extern "C" fn HardFault() { 37unsafe extern "C" fn HardFault() {
38 cortex_m::peripheral::SCB::sys_reset(); 38 cortex_m::peripheral::SCB::sys_reset();
39} 39}
@@ -41,7 +41,7 @@ unsafe extern "C" fn HardFault() {
41#[exception] 41#[exception]
42unsafe fn DefaultHandler(_: i16) -> ! { 42unsafe fn DefaultHandler(_: i16) -> ! {
43 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 43 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
44 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 44 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
45 45
46 panic!("DefaultHandler #{:?}", irqn); 46 panic!("DefaultHandler #{:?}", irqn);
47} 47}
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
index ef10aeabf..75b7081df 100644
--- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
+++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "stm32wb-dfu-bootloader-example" 3name = "stm32wb-dfu-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example USB DFUbootloader for the STM32WB series of chips" 5description = "Example USB DFUbootloader for the STM32WB series of chips"
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
index 107f243fd..9ee82846d 100644
--- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs
+++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
@@ -7,14 +7,14 @@ use cortex_m_rt::{entry, exception};
7#[cfg(feature = "defmt")] 7#[cfg(feature = "defmt")]
8use defmt_rtt as _; 8use defmt_rtt as _;
9use embassy_boot_stm32::*; 9use embassy_boot_stm32::*;
10use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; 10use embassy_stm32::flash::{BANK1_REGION, Flash, WRITE_SIZE};
11use embassy_stm32::rcc::WPAN_DEFAULT; 11use embassy_stm32::rcc::WPAN_DEFAULT;
12use embassy_stm32::usb::Driver; 12use embassy_stm32::usb::Driver;
13use embassy_stm32::{bind_interrupts, peripherals, usb}; 13use embassy_stm32::{bind_interrupts, peripherals, usb};
14use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
15use embassy_usb::{msos, Builder}; 15use embassy_usb::{Builder, msos};
16use embassy_usb_dfu::consts::DfuAttributes; 16use embassy_usb_dfu::consts::DfuAttributes;
17use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; 17use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu};
18 18
19bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
20 USB_LP => usb::InterruptHandler<peripherals::USB>; 20 USB_LP => usb::InterruptHandler<peripherals::USB>;
@@ -109,8 +109,8 @@ fn main() -> ! {
109 unsafe { bl.load(BANK1_REGION.base + active_offset) } 109 unsafe { bl.load(BANK1_REGION.base + active_offset) }
110} 110}
111 111
112#[no_mangle] 112#[unsafe(no_mangle)]
113#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 113#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
114unsafe extern "C" fn HardFault() { 114unsafe extern "C" fn HardFault() {
115 cortex_m::peripheral::SCB::sys_reset(); 115 cortex_m::peripheral::SCB::sys_reset();
116} 116}
@@ -118,7 +118,7 @@ unsafe extern "C" fn HardFault() {
118#[exception] 118#[exception]
119unsafe fn DefaultHandler(_: i16) -> ! { 119unsafe fn DefaultHandler(_: i16) -> ! {
120 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 120 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
121 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 121 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
122 122
123 panic!("DefaultHandler #{:?}", irqn); 123 panic!("DefaultHandler #{:?}", irqn);
124} 124}
diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml
index 16de7684e..eee2b2f71 100644
--- a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml
+++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "stm32wba6-dfu-bootloader-example" 3name = "stm32wba6-dfu-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example USB DFUbootloader for the STM32WBA series of chips" 5description = "Example USB DFUbootloader for the STM32WBA series of chips"
diff --git a/examples/boot/bootloader/stm32wba-dfu/src/main.rs b/examples/boot/bootloader/stm32wba-dfu/src/main.rs
index 75d8d4199..b33a75d95 100644
--- a/examples/boot/bootloader/stm32wba-dfu/src/main.rs
+++ b/examples/boot/bootloader/stm32wba-dfu/src/main.rs
@@ -7,13 +7,13 @@ use cortex_m_rt::{entry, exception};
7#[cfg(feature = "defmt")] 7#[cfg(feature = "defmt")]
8use defmt_rtt as _; 8use defmt_rtt as _;
9use embassy_boot_stm32::*; 9use embassy_boot_stm32::*;
10use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE}; 10use embassy_stm32::flash::{BANK1_REGION, Flash, WRITE_SIZE};
11use embassy_stm32::usb::Driver; 11use embassy_stm32::usb::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 12use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
13use embassy_sync::blocking_mutex::Mutex; 13use embassy_sync::blocking_mutex::Mutex;
14use embassy_usb::{msos, Builder}; 14use embassy_usb::{Builder, msos};
15use embassy_usb_dfu::consts::DfuAttributes; 15use embassy_usb_dfu::consts::DfuAttributes;
16use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; 16use embassy_usb_dfu::{Control, ResetImmediate, usb_dfu};
17 17
18bind_interrupts!(struct Irqs { 18bind_interrupts!(struct Irqs {
19 USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>; 19 USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
@@ -138,8 +138,8 @@ fn main() -> ! {
138 unsafe { bl.load(BANK1_REGION.base + active_offset) } 138 unsafe { bl.load(BANK1_REGION.base + active_offset) }
139} 139}
140 140
141#[no_mangle] 141#[unsafe(no_mangle)]
142#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 142#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
143unsafe extern "C" fn HardFault() { 143unsafe extern "C" fn HardFault() {
144 cortex_m::peripheral::SCB::sys_reset(); 144 cortex_m::peripheral::SCB::sys_reset();
145} 145}
@@ -147,7 +147,7 @@ unsafe extern "C" fn HardFault() {
147#[exception] 147#[exception]
148unsafe fn DefaultHandler(_: i16) -> ! { 148unsafe fn DefaultHandler(_: i16) -> ! {
149 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 149 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
150 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 150 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
151 151
152 panic!("DefaultHandler #{:?}", irqn); 152 panic!("DefaultHandler #{:?}", irqn);
153} 153}
diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml
index 579748595..94903b3f8 100644
--- a/examples/lpc55s69/Cargo.toml
+++ b/examples/lpc55s69/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nxp-lpc55s69-examples" 3name = "embassy-nxp-lpc55s69-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/lpc55s69/src/bin/pwm.rs b/examples/lpc55s69/src/bin/pwm.rs
new file mode 100644
index 000000000..8a9894b94
--- /dev/null
+++ b/examples/lpc55s69/src/bin/pwm.rs
@@ -0,0 +1,18 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nxp::pwm::{Config, Pwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_halt as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nxp::init(Default::default());
13 let pwm = Pwm::new_output(p.SCT0_OUT1, p.PIO0_18, Config::new(1_000_000_000, 2_000_000_000));
14 loop {
15 info!("Counter: {}", pwm.counter());
16 Timer::after_millis(50).await;
17 }
18}
diff --git a/examples/lpc55s69/src/bin/usart_async.rs b/examples/lpc55s69/src/bin/usart_async.rs
index b06abd477..a9815b920 100644
--- a/examples/lpc55s69/src/bin/usart_async.rs
+++ b/examples/lpc55s69/src/bin/usart_async.rs
@@ -38,8 +38,8 @@ async fn main(spawner: Spawner) {
38 p.PIO0_27, 38 p.PIO0_27,
39 p.PIO1_24, 39 p.PIO1_24,
40 Irqs, 40 Irqs,
41 p.DMA_CH11, 41 p.DMA0_CH11,
42 p.DMA_CH10, 42 p.DMA0_CH10,
43 Config::default(), 43 Config::default(),
44 ); 44 );
45 let led = Output::new(p.PIO1_6, Level::Low); 45 let led = Output::new(p.PIO1_6, Level::Low);
diff --git a/examples/mcxa/.cargo/config.toml b/examples/mcxa/.cargo/config.toml
new file mode 100644
index 000000000..aedc55b06
--- /dev/null
+++ b/examples/mcxa/.cargo/config.toml
@@ -0,0 +1,17 @@
1[target.thumbv8m.main-none-eabihf]
2runner = 'probe-rs run --chip MCXA276 --preverify --verify --protocol swd --speed 12000'
3
4rustflags = [
5 "-C", "linker=flip-link",
6 "-C", "link-arg=-Tlink.x",
7 "-C", "link-arg=-Tdefmt.x",
8 # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
9 # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
10 "-C", "link-arg=--nmagic",
11]
12
13[build]
14target = "thumbv8m.main-none-eabihf" # Cortex-M33
15
16[env]
17DEFMT_LOG = "trace"
diff --git a/examples/mcxa/.gitignore b/examples/mcxa/.gitignore
new file mode 100644
index 000000000..2f7896d1d
--- /dev/null
+++ b/examples/mcxa/.gitignore
@@ -0,0 +1 @@
target/
diff --git a/examples/mcxa/Cargo.toml b/examples/mcxa/Cargo.toml
new file mode 100644
index 000000000..347659f5b
--- /dev/null
+++ b/examples/mcxa/Cargo.toml
@@ -0,0 +1,35 @@
1[package]
2name = "embassy-mcxa-examples"
3version = "0.1.0"
4edition = "2021"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
10cortex-m-rt = { version = "0.7", features = ["set-sp", "set-vtor"] }
11crc = "3.4.0"
12critical-section = "1.2.0"
13defmt = "1.0"
14defmt-rtt = "1.0"
15embassy-embedded-hal = "0.5.0"
16embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false }
17embassy-mcxa = { path = "../../embassy-mcxa", features = ["defmt", "unstable-pac", "time"] }
18embassy-sync = "0.7.2"
19embassy-time = "0.5.0"
20embassy-time-driver = "0.2.1"
21embedded-io-async = "0.6.1"
22heapless = "0.9.2"
23panic-probe = { version = "1.0", features = ["print-defmt"] }
24rand_core = "0.9"
25static_cell = "2.1.1"
26tmp108 = "0.4.0"
27
28[profile.release]
29lto = true # better optimizations
30debug = 2 # enough information for defmt/rtt locations
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/mcxa" }
35]
diff --git a/examples/mcxa/build.rs b/examples/mcxa/build.rs
new file mode 100644
index 000000000..f076bba9f
--- /dev/null
+++ b/examples/mcxa/build.rs
@@ -0,0 +1,20 @@
1use std::env;
2use std::fs::File;
3use std::io::Write;
4use std::path::PathBuf;
5
6fn main() {
7 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
8
9 // Generate memory.x - put "FLASH" at start of RAM, RAM after "FLASH"
10 // cortex-m-rt expects FLASH for code, RAM for data/bss/stack
11 // Both are in RAM, but separated to satisfy cortex-m-rt's expectations
12 // MCXA256 has 128KB RAM total
13 File::create(out.join("memory.x"))
14 .unwrap()
15 .write_all(include_bytes!("memory.x"))
16 .unwrap();
17
18 println!("cargo:rustc-link-search={}", out.display());
19 println!("cargo:rerun-if-changed=memory.x");
20}
diff --git a/examples/mcxa/memory.x b/examples/mcxa/memory.x
new file mode 100644
index 000000000..315ced58a
--- /dev/null
+++ b/examples/mcxa/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 1M
4 RAM : ORIGIN = 0x20000000, LENGTH = 128K
5}
diff --git a/examples/mcxa/src/bin/adc_interrupt.rs b/examples/mcxa/src/bin/adc_interrupt.rs
new file mode 100644
index 000000000..d2cda631c
--- /dev/null
+++ b/examples/mcxa/src/bin/adc_interrupt.rs
@@ -0,0 +1,65 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::{Duration, Ticker};
6use hal::adc::{Adc, InterruptHandler, LpadcConfig, TriggerPriorityPolicy};
7use hal::bind_interrupts;
8use hal::clocks::PoweredClock;
9use hal::clocks::config::Div8;
10use hal::clocks::periph_helpers::{AdcClockSel, Div4};
11use hal::config::Config;
12use hal::pac::adc1::cfg::{Pwrsel, Refsel};
13use hal::pac::adc1::cmdl1::Mode;
14use hal::pac::adc1::ctrl::CalAvgs;
15use hal::peripherals::ADC1;
16use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 ADC1 => InterruptHandler<ADC1>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let mut config = Config::default();
25 config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1);
26
27 let p = hal::init(config);
28
29 defmt::info!("ADC interrupt Example");
30
31 let adc_config = LpadcConfig {
32 enable_in_doze_mode: true,
33 conversion_average_mode: CalAvgs::Average128,
34 enable_analog_preliminary: true,
35 power_up_delay: 0x80,
36 reference_voltage_source: Refsel::Option3,
37 power_level_mode: Pwrsel::Lowest,
38 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed,
39 enable_conv_pause: false,
40 conv_pause_delay: 0,
41 power: PoweredClock::NormalEnabledDeepSleepDisabled,
42 source: AdcClockSel::FroLfDiv,
43 div: Div4::no_div(),
44 };
45 let mut adc = Adc::new_async(p.ADC1, p.P1_10, Irqs, adc_config).unwrap();
46
47 adc.do_offset_calibration();
48 adc.do_auto_calibration();
49 adc.set_resolution(Mode::Data16Bits);
50
51 defmt::info!("ADC configuration done...");
52 let mut ticker = Ticker::every(Duration::from_millis(100));
53
54 loop {
55 ticker.next().await;
56 match adc.read().await {
57 Ok(value) => {
58 defmt::info!("ADC value: {}", value);
59 }
60 Err(e) => {
61 defmt::error!("ADC read error: {:?}", e);
62 }
63 }
64 }
65}
diff --git a/examples/mcxa/src/bin/adc_polling.rs b/examples/mcxa/src/bin/adc_polling.rs
new file mode 100644
index 000000000..5c4d5524c
--- /dev/null
+++ b/examples/mcxa/src/bin/adc_polling.rs
@@ -0,0 +1,78 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::adc::{ConvCommandConfig, ConvTriggerConfig};
6use embassy_time::{Duration, Ticker};
7use hal::adc::{Adc, LpadcConfig, TriggerPriorityPolicy};
8use hal::clocks::PoweredClock;
9use hal::clocks::config::Div8;
10use hal::clocks::periph_helpers::{AdcClockSel, Div4};
11use hal::config::Config;
12use hal::pac::adc1::cfg::{Pwrsel, Refsel};
13use hal::pac::adc1::cmdl1::Mode;
14use hal::pac::adc1::ctrl::CalAvgs;
15use hal::pac::adc1::tctrl::Tcmd;
16use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
17
18const G_LPADC_RESULT_SHIFT: u32 = 0;
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) {
22 let mut config = Config::default();
23 config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1);
24
25 let p = hal::init(config);
26
27 defmt::info!("=== ADC polling Example ===");
28
29 let adc_config = LpadcConfig {
30 enable_in_doze_mode: true,
31 conversion_average_mode: CalAvgs::Average128,
32 enable_analog_preliminary: true,
33 power_up_delay: 0x80,
34 reference_voltage_source: Refsel::Option3,
35 power_level_mode: Pwrsel::Lowest,
36 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed,
37 enable_conv_pause: false,
38 conv_pause_delay: 0,
39 power: PoweredClock::NormalEnabledDeepSleepDisabled,
40 source: AdcClockSel::FroLfDiv,
41 div: Div4::no_div(),
42 };
43 let adc = Adc::new_blocking(p.ADC1, p.P1_10, adc_config).unwrap();
44
45 adc.do_offset_calibration();
46 adc.do_auto_calibration();
47
48 let conv_command_config = ConvCommandConfig {
49 conversion_resolution_mode: Mode::Data16Bits,
50 ..ConvCommandConfig::default()
51 };
52 adc.set_conv_command_config(1, &conv_command_config).unwrap();
53
54 let conv_trigger_config = ConvTriggerConfig {
55 target_command_id: Tcmd::ExecuteCmd1,
56 enable_hardware_trigger: false,
57 ..Default::default()
58 };
59 adc.set_conv_trigger_config(0, &conv_trigger_config).unwrap();
60
61 defmt::info!("=== ADC configuration done... ===");
62 let mut tick = Ticker::every(Duration::from_millis(100));
63
64 loop {
65 tick.next().await;
66 adc.do_software_trigger(1).unwrap();
67 let result = loop {
68 match adc.get_conv_result() {
69 Ok(res) => break res,
70 Err(_) => {
71 // Conversion not ready, continue polling
72 }
73 }
74 };
75 let value = result.conv_value >> G_LPADC_RESULT_SHIFT;
76 defmt::info!("ADC value: {=u16}", value);
77 }
78}
diff --git a/examples/mcxa/src/bin/blinky.rs b/examples/mcxa/src/bin/blinky.rs
new file mode 100644
index 000000000..dd08ec0d9
--- /dev/null
+++ b/examples/mcxa/src/bin/blinky.rs
@@ -0,0 +1,36 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::gpio::{DriveStrength, Level, Output, SlewRate};
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = hal::init(hal::config::Config::default());
12
13 defmt::info!("Blink example");
14
15 let mut red = Output::new(p.P3_18, Level::High, DriveStrength::Normal, SlewRate::Fast);
16 let mut green = Output::new(p.P3_19, Level::High, DriveStrength::Normal, SlewRate::Fast);
17 let mut blue = Output::new(p.P3_21, Level::High, DriveStrength::Normal, SlewRate::Fast);
18
19 loop {
20 defmt::info!("Toggle LEDs");
21
22 red.toggle();
23 Timer::after_millis(250).await;
24
25 red.toggle();
26 green.toggle();
27 Timer::after_millis(250).await;
28
29 green.toggle();
30 blue.toggle();
31 Timer::after_millis(250).await;
32 blue.toggle();
33
34 Timer::after_millis(250).await;
35 }
36}
diff --git a/examples/mcxa/src/bin/button.rs b/examples/mcxa/src/bin/button.rs
new file mode 100644
index 000000000..943edbb15
--- /dev/null
+++ b/examples/mcxa/src/bin/button.rs
@@ -0,0 +1,23 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::gpio::{Input, Pull};
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = hal::init(hal::config::Config::default());
12
13 defmt::info!("Button example");
14
15 // This button is labeled "WAKEUP" on the FRDM-MCXA276
16 // The board already has a 10K pullup
17 let monitor = Input::new(p.P1_7, Pull::Disabled);
18
19 loop {
20 defmt::info!("Pin level is {:?}", monitor.get_level());
21 Timer::after_millis(1000).await;
22 }
23}
diff --git a/examples/mcxa/src/bin/button_async.rs b/examples/mcxa/src/bin/button_async.rs
new file mode 100644
index 000000000..6cc7b62cd
--- /dev/null
+++ b/examples/mcxa/src/bin/button_async.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::gpio::{Input, Pull};
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = hal::init(hal::config::Config::default());
12
13 defmt::info!("GPIO interrupt example");
14
15 // This button is labeled "WAKEUP" on the FRDM-MCXA276
16 // The board already has a 10K pullup
17 let mut pin = Input::new(p.P1_7, Pull::Disabled);
18
19 let mut press_count = 0u32;
20
21 loop {
22 pin.wait_for_falling_edge().await;
23
24 press_count += 1;
25
26 defmt::info!("Button pressed! Count: {}", press_count);
27 Timer::after_millis(50).await;
28 }
29}
diff --git a/examples/mcxa/src/bin/clkout.rs b/examples/mcxa/src/bin/clkout.rs
new file mode 100644
index 000000000..1e52912d3
--- /dev/null
+++ b/examples/mcxa/src/bin/clkout.rs
@@ -0,0 +1,68 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4};
6use embassy_mcxa::clocks::PoweredClock;
7use embassy_mcxa::gpio::{DriveStrength, Level, Output, SlewRate};
8use embassy_time::Timer;
9use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
10
11/// Demonstrate CLKOUT, using Pin P4.2
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = hal::init(hal::config::Config::default());
15 let mut pin = p.P4_2;
16 let mut clkout = p.CLKOUT;
17
18 loop {
19 defmt::info!("Set Low...");
20 let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow);
21 Timer::after_millis(500).await;
22
23 defmt::info!("Set High...");
24 output.set_high();
25 Timer::after_millis(400).await;
26
27 defmt::info!("Set Low...");
28 output.set_low();
29 Timer::after_millis(500).await;
30
31 defmt::info!("16k...");
32 // Run Clock Out with the 16K clock
33 let _clock_out = ClockOut::new(
34 clkout.reborrow(),
35 pin.reborrow(),
36 Config {
37 sel: ClockOutSel::Clk16K,
38 div: Div4::no_div(),
39 level: PoweredClock::NormalEnabledDeepSleepDisabled,
40 },
41 )
42 .unwrap();
43
44 Timer::after_millis(3000).await;
45
46 defmt::info!("Set Low...");
47 drop(_clock_out);
48
49 let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow);
50 Timer::after_millis(500).await;
51
52 // Run Clock Out with the 12M clock, divided by 3
53 defmt::info!("4M...");
54 let _clock_out = ClockOut::new(
55 clkout.reborrow(),
56 pin.reborrow(),
57 Config {
58 sel: ClockOutSel::Fro12M,
59 div: const { Div4::from_divisor(3).unwrap() },
60 level: PoweredClock::NormalEnabledDeepSleepDisabled,
61 },
62 )
63 .unwrap();
64
65 // Let it run for 3 seconds...
66 Timer::after_millis(3000).await;
67 }
68}
diff --git a/examples/mcxa/src/bin/crc.rs b/examples/mcxa/src/bin/crc.rs
new file mode 100644
index 000000000..0125e625c
--- /dev/null
+++ b/examples/mcxa/src/bin/crc.rs
@@ -0,0 +1,154 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use hal::config::Config;
6use hal::crc::Crc;
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9const CCITT_FALSE: crc::Algorithm<u16> = crc::Algorithm {
10 width: 16,
11 poly: 0x1021,
12 init: 0xffff,
13 refin: false,
14 refout: false,
15 xorout: 0,
16 check: 0x29b1,
17 residue: 0x0000,
18};
19
20const POSIX: crc::Algorithm<u32> = crc::Algorithm {
21 width: 32,
22 poly: 0x04c1_1db7,
23 init: 0,
24 refin: false,
25 refout: false,
26 xorout: 0xffff_ffff,
27 check: 0x765e_7680,
28 residue: 0x0000,
29};
30
31#[embassy_executor::main]
32async fn main(_spawner: Spawner) {
33 let config = Config::default();
34 let mut p = hal::init(config);
35
36 defmt::info!("CRC example");
37
38 let buf_u8 = [0x00u8, 0x11, 0x22, 0x33];
39 let buf_u16 = [0x0000u16, 0x1111, 0x2222, 0x3333];
40 let buf_u32 = [0x0000_0000u32, 0x1111_1111, 0x2222_2222, 0x3333_3333];
41
42 // CCITT False
43
44 let sw_crc = crc::Crc::<u16>::new(&CCITT_FALSE);
45 let mut digest = sw_crc.digest();
46 digest.update(&buf_u8);
47 let sw_sum = digest.finalize();
48
49 let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow());
50 crc.feed(&buf_u8);
51 let sum = crc.finalize();
52 assert_eq!(sum, sw_sum);
53
54 let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow());
55 crc.feed(&buf_u16);
56 let sum = crc.finalize();
57 assert_eq!(sum, 0xa467);
58
59 let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow());
60 crc.feed(&buf_u32);
61 let sum = crc.finalize();
62 assert_eq!(sum, 0xe5c7);
63
64 // Maxim
65
66 let sw_crc = crc::Crc::<u16>::new(&crc::CRC_16_MAXIM_DOW);
67 let mut digest = sw_crc.digest();
68 digest.update(&buf_u8);
69 let sw_sum = digest.finalize();
70
71 let mut crc = Crc::new_maxim(p.CRC0.reborrow());
72 crc.feed(&buf_u8);
73 let sum = crc.finalize();
74 assert_eq!(sum, sw_sum);
75
76 let mut crc = Crc::new_maxim(p.CRC0.reborrow());
77 crc.feed(&buf_u16);
78 let sum = crc.finalize();
79 assert_eq!(sum, 0x2afe);
80
81 let mut crc = Crc::new_maxim(p.CRC0.reborrow());
82 crc.feed(&buf_u32);
83 let sum = crc.finalize();
84 assert_eq!(sum, 0x17d7);
85
86 // Kermit
87
88 let sw_crc = crc::Crc::<u16>::new(&crc::CRC_16_KERMIT);
89 let mut digest = sw_crc.digest();
90 digest.update(&buf_u8);
91 let sw_sum = digest.finalize();
92
93 let mut crc = Crc::new_kermit(p.CRC0.reborrow());
94 crc.feed(&buf_u8);
95 let sum = crc.finalize();
96 assert_eq!(sum, sw_sum);
97
98 let mut crc = Crc::new_kermit(p.CRC0.reborrow());
99 crc.feed(&buf_u16);
100 let sum = crc.finalize();
101 assert_eq!(sum, 0x66eb);
102
103 let mut crc = Crc::new_kermit(p.CRC0.reborrow());
104 crc.feed(&buf_u32);
105 let sum = crc.finalize();
106 assert_eq!(sum, 0x75ea);
107
108 // ISO HDLC
109
110 let sw_crc = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
111 let mut digest = sw_crc.digest();
112 digest.update(&buf_u8);
113 let sw_sum = digest.finalize();
114
115 let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow());
116 crc.feed(&buf_u8);
117 let sum = crc.finalize();
118 assert_eq!(sum, sw_sum);
119
120 let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow());
121 crc.feed(&buf_u16);
122 let sum = crc.finalize();
123 assert_eq!(sum, 0x8a61_4178);
124
125 let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow());
126 crc.feed(&buf_u32);
127 let sum = crc.finalize();
128 assert_eq!(sum, 0xfab5_d04e);
129
130 // POSIX
131
132 let sw_crc = crc::Crc::<u32>::new(&POSIX);
133 let mut digest = sw_crc.digest();
134 digest.update(&buf_u8);
135 let sw_sum = digest.finalize();
136
137 let mut crc = Crc::new_posix(p.CRC0.reborrow());
138 crc.feed(&buf_u8);
139 let sum = crc.finalize();
140
141 assert_eq!(sum, sw_sum);
142
143 let mut crc = Crc::new_posix(p.CRC0.reborrow());
144 crc.feed(&buf_u16);
145 let sum = crc.finalize();
146 assert_eq!(sum, 0x6d76_4f58);
147
148 let mut crc = Crc::new_posix(p.CRC0.reborrow());
149 crc.feed(&buf_u32);
150 let sum = crc.finalize();
151 assert_eq!(sum, 0x2a5b_cb90);
152
153 defmt::info!("CRC successful");
154}
diff --git a/examples/mcxa/src/bin/dma_mem_to_mem.rs b/examples/mcxa/src/bin/dma_mem_to_mem.rs
new file mode 100644
index 000000000..b38baccb5
--- /dev/null
+++ b/examples/mcxa/src/bin/dma_mem_to_mem.rs
@@ -0,0 +1,118 @@
1//! DMA memory-to-memory transfer example for MCXA276.
2//!
3//! This example demonstrates using DMA to copy data between memory buffers
4//! using the Embassy-style async API with type-safe transfers.
5//!
6//! # Embassy-style features demonstrated:
7//! - `TransferOptions` for configuration
8//! - Type-safe `mem_to_mem<u32>()` method with async `.await`
9//! - `Transfer` Future that can be `.await`ed
10//! - `Word` trait for automatic transfer width detection
11//! - `memset()` method for filling memory with a pattern
12
13#![no_std]
14#![no_main]
15
16use embassy_executor::Spawner;
17use embassy_mcxa::clocks::config::Div8;
18use embassy_mcxa::dma::{DmaChannel, TransferOptions};
19use static_cell::ConstStaticCell;
20use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
21
22const BUFFER_LENGTH: usize = 4;
23
24// Buffers in RAM (static mut is automatically placed in .bss/.data)
25static SRC_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([1, 2, 3, 4]);
26static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
27static MEMSET_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
28
29#[embassy_executor::main]
30async fn main(_spawner: Spawner) {
31 // Small delay to allow probe-rs to attach after reset
32 for _ in 0..100_000 {
33 cortex_m::asm::nop();
34 }
35
36 let mut cfg = hal::config::Config::default();
37 cfg.clock_cfg.sirc.fro_12m_enabled = true;
38 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
39 let p = hal::init(cfg);
40
41 defmt::info!("DMA memory-to-memory example starting...");
42
43 defmt::info!("EDMA memory to memory example begin.");
44
45 let src = SRC_BUFFER.take();
46 let dst = DEST_BUFFER.take();
47 let mst = MEMSET_BUFFER.take();
48
49 defmt::info!("Source Buffer: {=[?]}", src.as_slice());
50 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
51 defmt::info!("Configuring DMA with Embassy-style API...");
52
53 // Create DMA channel
54 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
55
56 // Configure transfer options (Embassy-style)
57 // TransferOptions defaults to: complete_transfer_interrupt = true
58 let options = TransferOptions::default();
59
60 // =========================================================================
61 // Part 1: Embassy-style async API demonstration (mem_to_mem)
62 // =========================================================================
63 //
64 // Use the new type-safe `mem_to_mem<u32>()` method:
65 // - Automatically determines transfer width from buffer element type (u32)
66 // - Returns a `Transfer` future that can be `.await`ed
67 // - Uses TransferOptions for consistent configuration
68 //
69 // Using async `.await` - the executor can run other tasks while waiting!
70
71 // Perform type-safe memory-to-memory transfer using Embassy-style async API
72 // Using async `.await` - the executor can run other tasks while waiting!
73 let transfer = dma_ch0.mem_to_mem(src, dst, options).unwrap();
74 transfer.await.unwrap();
75
76 defmt::info!("DMA mem-to-mem transfer complete!");
77 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
78
79 // Verify data
80 if src != dst {
81 defmt::error!("FAIL: mem_to_mem mismatch!");
82 } else {
83 defmt::info!("PASS: mem_to_mem verified.");
84 }
85
86 // =========================================================================
87 // Part 2: memset() demonstration
88 // =========================================================================
89 //
90 // The `memset()` method fills a buffer with a pattern value:
91 // - Fixed source address (pattern is read repeatedly)
92 // - Incrementing destination address
93 // - Uses the same Transfer future pattern
94
95 defmt::info!("--- Demonstrating memset() feature ---");
96
97 defmt::info!("Memset Buffer (before): {=[?]}", mst.as_slice());
98
99 // Fill buffer with a pattern value using DMA memset
100 let pattern: u32 = 0xDEADBEEF;
101 defmt::info!("Filling with pattern 0xDEADBEEF...");
102
103 // Using blocking_wait() for demonstration - also shows non-async usage
104 let transfer = dma_ch0.memset(&pattern, mst, options);
105 transfer.blocking_wait();
106
107 defmt::info!("DMA memset complete!");
108 defmt::info!("Memset Buffer (after): {=[?]}", mst.as_slice());
109
110 // Verify memset result
111 if !mst.iter().all(|&v| v == pattern) {
112 defmt::error!("FAIL: memset mismatch!");
113 } else {
114 defmt::info!("PASS: memset verified.");
115 }
116
117 defmt::info!("=== All DMA tests complete ===");
118}
diff --git a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs
new file mode 100644
index 000000000..30ce20c96
--- /dev/null
+++ b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs
@@ -0,0 +1,130 @@
1//! DMA Scatter-Gather Builder example for MCXA276.
2//!
3//! This example demonstrates using the new `ScatterGatherBuilder` API for
4//! chaining multiple DMA transfers with a type-safe builder pattern.
5//!
6//! # Features demonstrated:
7//! - `ScatterGatherBuilder::new()` for creating a builder
8//! - `add_transfer()` for adding memory-to-memory segments
9//! - `build()` to start the chained transfer
10//! - Automatic TCD linking and ESG bit management
11//!
12//! # Comparison with manual scatter-gather:
13//! The manual approach (see `dma_scatter_gather.rs`) requires:
14//! - Manual TCD pool allocation and alignment
15//! - Manual CSR/ESG/INTMAJOR bit manipulation
16//! - Manual dlast_sga address calculations
17//!
18//! The builder approach handles all of this automatically!
19
20#![no_std]
21#![no_main]
22
23use embassy_executor::Spawner;
24use embassy_mcxa::clocks::config::Div8;
25use embassy_mcxa::dma::{DmaChannel, ScatterGatherBuilder};
26use static_cell::ConstStaticCell;
27use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
28
29// Source buffers (multiple segments)
30static SRC1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x11111111, 0x22222222, 0x33333333, 0x44444444]);
31static SRC2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD]);
32static SRC3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210]);
33
34// Destination buffers (one per segment)
35static DST1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
36static DST2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
37static DST3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
38
39#[embassy_executor::main]
40async fn main(_spawner: Spawner) {
41 // Small delay to allow probe-rs to attach after reset
42 for _ in 0..100_000 {
43 cortex_m::asm::nop();
44 }
45
46 let mut cfg = hal::config::Config::default();
47 cfg.clock_cfg.sirc.fro_12m_enabled = true;
48 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
49 let p = hal::init(cfg);
50
51 defmt::info!("DMA Scatter-Gather Builder example starting...");
52
53 defmt::info!("DMA Scatter-Gather Builder Example");
54 defmt::info!("===================================");
55 let src1 = SRC1.take();
56 let src2 = SRC2.take();
57 let src3 = SRC3.take();
58 let dst1 = DST1.take();
59 let dst2 = DST2.take();
60 let dst3 = DST3.take();
61
62 // Show source buffers
63 defmt::info!("Source buffers:");
64 defmt::info!(" SRC1: {=[?]}", src1.as_slice());
65 defmt::info!(" SRC2: {=[?]}", src2.as_slice());
66 defmt::info!(" SRC3: {=[?]}", src3.as_slice());
67
68 defmt::info!("Destination buffers (before):");
69 defmt::info!(" DST1: {=[?]}", dst1.as_slice());
70 defmt::info!(" DST2: {=[?]}", dst2.as_slice());
71 defmt::info!(" DST3: {=[?]}", dst3.as_slice());
72
73 // Create DMA channel
74 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
75
76 defmt::info!("Building scatter-gather chain with builder API...");
77
78 // =========================================================================
79 // ScatterGatherBuilder API demonstration
80 // =========================================================================
81 //
82 // The builder pattern makes scatter-gather transfers much easier:
83 // 1. Create a builder
84 // 2. Add transfer segments with add_transfer()
85 // 3. Call build() to start the entire chain
86 // No manual TCD manipulation required!
87
88 let mut builder = ScatterGatherBuilder::<u32>::new();
89
90 // Add three transfer segments - the builder handles TCD linking automatically
91 builder.add_transfer(src1, dst1);
92 builder.add_transfer(src2, dst2);
93 builder.add_transfer(src3, dst3);
94
95 defmt::info!("Added 3 transfer segments to chain.");
96 defmt::info!("Starting scatter-gather transfer with .await...");
97
98 // Build and execute the scatter-gather chain
99 // The build() method:
100 // - Links all TCDs together with ESG bit
101 // - Sets INTMAJOR on all TCDs
102 // - Loads the first TCD into hardware
103 // - Returns a Transfer future
104 let transfer = builder.build(&dma_ch0).expect("Failed to build scatter-gather");
105 transfer.blocking_wait();
106
107 defmt::info!("Scatter-gather transfer complete!");
108
109 // Show results
110 defmt::info!("Destination buffers (after):");
111 defmt::info!(" DST1: {=[?]}", dst1.as_slice());
112 defmt::info!(" DST2: {=[?]}", dst2.as_slice());
113 defmt::info!(" DST3: {=[?]}", dst3.as_slice());
114
115 let comps = [(src1, dst1), (src2, dst2), (src3, dst3)];
116
117 // Verify all three segments
118 let mut all_ok = true;
119 for (src, dst) in comps {
120 all_ok &= src == dst;
121 }
122
123 if all_ok {
124 defmt::info!("PASS: All segments verified!");
125 } else {
126 defmt::error!("FAIL: Mismatch detected!");
127 }
128
129 defmt::info!("=== Scatter-Gather Builder example complete ===");
130}
diff --git a/examples/mcxa/src/bin/dma_wrap_transfer.rs b/examples/mcxa/src/bin/dma_wrap_transfer.rs
new file mode 100644
index 000000000..acfd29f08
--- /dev/null
+++ b/examples/mcxa/src/bin/dma_wrap_transfer.rs
@@ -0,0 +1,184 @@
1//! DMA wrap transfer example for MCXA276.
2//!
3//! This example demonstrates using DMA with modulo addressing to wrap around
4//! a source buffer, effectively repeating the source data in the destination.
5//!
6//! # Embassy-style features demonstrated:
7//! - `DmaChannel::is_done()` and `clear_done()` helper methods
8//! - No need to pass register block around
9
10#![no_std]
11#![no_main]
12
13use core::fmt::Write as _;
14
15use embassy_executor::Spawner;
16use embassy_mcxa::clocks::config::Div8;
17use embassy_mcxa::dma::DmaChannel;
18use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx};
19use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
20
21// Source buffer: 4 words (16 bytes), aligned to 16 bytes for modulo
22#[repr(align(16))]
23struct AlignedSrc([u32; 4]);
24
25static mut SRC: AlignedSrc = AlignedSrc([0; 4]);
26static mut DST: [u32; 8] = [0; 8];
27
28/// Helper to print a buffer to UART
29fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) {
30 write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok();
31}
32
33#[embassy_executor::main]
34async fn main(_spawner: Spawner) {
35 // Small delay to allow probe-rs to attach after reset
36 for _ in 0..100_000 {
37 cortex_m::asm::nop();
38 }
39
40 let mut cfg = hal::config::Config::default();
41 cfg.clock_cfg.sirc.fro_12m_enabled = true;
42 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
43 let p = hal::init(cfg);
44
45 defmt::info!("DMA wrap transfer example starting...");
46
47 let config = Config {
48 baudrate_bps: 115_200,
49 ..Default::default()
50 };
51
52 let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap();
53 let (mut tx, _rx) = lpuart.split();
54
55 tx.blocking_write(b"EDMA wrap transfer example begin.\r\n\r\n").unwrap();
56
57 // Initialize buffers
58 unsafe {
59 SRC.0 = [1, 2, 3, 4];
60 DST = [0; 8];
61 }
62
63 tx.blocking_write(b"Source Buffer: ").unwrap();
64 print_buffer(&mut tx, unsafe { core::ptr::addr_of!(SRC.0) } as *const u32, 4);
65 tx.blocking_write(b"\r\n").unwrap();
66
67 tx.blocking_write(b"Destination Buffer (before): ").unwrap();
68 print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8);
69 tx.blocking_write(b"\r\n").unwrap();
70
71 tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n")
72 .unwrap();
73
74 // Create DMA channel using Embassy-style API
75 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
76
77 // Configure wrap transfer using direct TCD access:
78 // SRC is 16 bytes (4 * u32). We want to transfer 32 bytes (8 * u32).
79 // SRC modulo is 16 bytes (2^4 = 16) - wraps source address.
80 // DST modulo is 0 (disabled).
81 // This causes the source address to wrap around after 16 bytes,
82 // effectively repeating the source data.
83 unsafe {
84 let t = dma_ch0.tcd();
85
86 // Reset channel state
87 t.ch_csr().write(|w| {
88 w.erq()
89 .disable()
90 .earq()
91 .disable()
92 .eei()
93 .no_error()
94 .ebw()
95 .disable()
96 .done()
97 .clear_bit_by_one()
98 });
99 t.ch_es().write(|w| w.bits(0));
100 t.ch_int().write(|w| w.int().clear_bit_by_one());
101
102 // Source/destination addresses
103 t.tcd_saddr()
104 .write(|w| w.saddr().bits(core::ptr::addr_of!(SRC.0) as u32));
105 t.tcd_daddr()
106 .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DST) as u32));
107
108 // Offsets: both increment by 4 bytes
109 t.tcd_soff().write(|w| w.soff().bits(4));
110 t.tcd_doff().write(|w| w.doff().bits(4));
111
112 // Attributes: 32-bit transfers (size = 2)
113 // SMOD = 4 (2^4 = 16 byte modulo for source), DMOD = 0 (disabled)
114 t.tcd_attr().write(|w| {
115 w.ssize()
116 .bits(2)
117 .dsize()
118 .bits(2)
119 .smod()
120 .bits(4) // Source modulo: 2^4 = 16 bytes
121 .dmod()
122 .bits(0) // Dest modulo: disabled
123 });
124
125 // Transfer 32 bytes total in one minor loop
126 let nbytes = 32u32;
127 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
128
129 // Source wraps via modulo, no adjustment needed
130 t.tcd_slast_sda().write(|w| w.slast_sda().bits(0));
131 // Reset dest address after major loop
132 t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32));
133
134 // Major loop count = 1
135 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
136 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
137
138 // Enable interrupt on major loop completion
139 t.tcd_csr().write(|w| w.intmajor().set_bit());
140
141 cortex_m::asm::dsb();
142
143 tx.blocking_write(b"Triggering transfer...\r\n").unwrap();
144 dma_ch0.trigger_start();
145 }
146
147 // Wait for completion using channel helper method
148 while !dma_ch0.is_done() {
149 cortex_m::asm::nop();
150 }
151 unsafe {
152 dma_ch0.clear_done();
153 }
154
155 tx.blocking_write(b"\r\nEDMA wrap transfer example finish.\r\n\r\n")
156 .unwrap();
157 tx.blocking_write(b"Destination Buffer (after): ").unwrap();
158 print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8);
159 tx.blocking_write(b"\r\n\r\n").unwrap();
160
161 // Verify: DST should be [1, 2, 3, 4, 1, 2, 3, 4]
162 let expected = [1u32, 2, 3, 4, 1, 2, 3, 4];
163 let mut mismatch = false;
164 unsafe {
165 for i in 0..8 {
166 if DST[i] != expected[i] {
167 mismatch = true;
168 break;
169 }
170 }
171 }
172
173 if mismatch {
174 tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap();
175 defmt::error!("FAIL: Mismatch detected!");
176 } else {
177 tx.blocking_write(b"PASS: Data verified.\r\n").unwrap();
178 defmt::info!("PASS: Data verified.");
179 }
180
181 loop {
182 cortex_m::asm::wfe();
183 }
184}
diff --git a/examples/mcxa/src/bin/hello.rs b/examples/mcxa/src/bin/hello.rs
new file mode 100644
index 000000000..e371d9413
--- /dev/null
+++ b/examples/mcxa/src/bin/hello.rs
@@ -0,0 +1,119 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::clocks::config::Div8;
6use hal::lpuart::{Blocking, Config, Lpuart};
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9/// Simple helper to write a byte as hex to UART
10fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) {
11 const HEX_DIGITS: &[u8] = b"0123456789ABCDEF";
12 let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]);
13 let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]);
14}
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut cfg = hal::config::Config::default();
19 cfg.clock_cfg.sirc.fro_12m_enabled = true;
20 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
21 let p = hal::init(cfg);
22
23 defmt::info!("boot");
24
25 // Create UART configuration
26 let config = Config {
27 baudrate_bps: 115_200,
28 ..Default::default()
29 };
30
31 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
32 let mut uart = Lpuart::new_blocking(
33 p.LPUART2, // Peripheral
34 p.P2_2, // TX pin
35 p.P2_3, // RX pin
36 config,
37 )
38 .unwrap();
39
40 // Print welcome message before any async delays to guarantee early console output
41 uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n");
42 uart.write_str_blocking("Available commands:\r\n");
43 uart.write_str_blocking(" help - Show this help\r\n");
44 uart.write_str_blocking(" echo <text> - Echo back the text\r\n");
45 uart.write_str_blocking(" hex <byte> - Display byte in hex (0-255)\r\n");
46 uart.write_str_blocking("Type a command: ");
47
48 let mut buffer = [0u8; 64];
49 let mut buf_idx = 0;
50
51 loop {
52 // Read a byte from UART
53 let byte = uart.read_byte_blocking();
54
55 // Echo the character back
56 if byte == b'\r' || byte == b'\n' {
57 // Enter pressed - process command
58 uart.write_str_blocking("\r\n");
59
60 if buf_idx > 0 {
61 let command = &buffer[0..buf_idx];
62
63 if command == b"help" {
64 uart.write_str_blocking("Available commands:\r\n");
65 uart.write_str_blocking(" help - Show this help\r\n");
66 uart.write_str_blocking(" echo <text> - Echo back the text\r\n");
67 uart.write_str_blocking(" hex <byte> - Display byte in hex (0-255)\r\n");
68 } else if command.starts_with(b"echo ") && command.len() > 5 {
69 uart.write_str_blocking("Echo: ");
70 uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or(""));
71 uart.write_str_blocking("\r\n");
72 } else if command.starts_with(b"hex ") && command.len() > 4 {
73 // Parse the byte value
74 let num_str = &command[4..];
75 if let Ok(num) = parse_u8(num_str) {
76 uart.write_str_blocking("Hex: 0x");
77 write_hex_byte(&mut uart, num);
78 uart.write_str_blocking("\r\n");
79 } else {
80 uart.write_str_blocking("Invalid number for hex command\r\n");
81 }
82 } else if !command.is_empty() {
83 uart.write_str_blocking("Unknown command: ");
84 uart.write_str_blocking(core::str::from_utf8(command).unwrap_or(""));
85 uart.write_str_blocking("\r\n");
86 }
87 }
88
89 // Reset buffer and prompt
90 buf_idx = 0;
91 uart.write_str_blocking("Type a command: ");
92 } else if byte == 8 || byte == 127 {
93 // Backspace
94 if buf_idx > 0 {
95 buf_idx -= 1;
96 uart.write_str_blocking("\x08 \x08"); // Erase character
97 }
98 } else if buf_idx < buffer.len() - 1 {
99 // Regular character
100 buffer[buf_idx] = byte;
101 buf_idx += 1;
102 let _ = uart.write_byte(byte);
103 }
104 }
105}
106
107/// Simple parser for u8 from ASCII bytes
108fn parse_u8(bytes: &[u8]) -> Result<u8, ()> {
109 let mut result = 0u8;
110 for &b in bytes {
111 if b.is_ascii_digit() {
112 result = result.checked_mul(10).ok_or(())?;
113 result = result.checked_add(b - b'0').ok_or(())?;
114 } else {
115 return Err(());
116 }
117 }
118 Ok(result)
119}
diff --git a/examples/mcxa/src/bin/i2c-async.rs b/examples/mcxa/src/bin/i2c-async.rs
new file mode 100644
index 000000000..edcfd5f22
--- /dev/null
+++ b/examples/mcxa/src/bin/i2c-async.rs
@@ -0,0 +1,39 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::bind_interrupts;
7use hal::clocks::config::Div8;
8use hal::config::Config;
9use hal::i2c::InterruptHandler;
10use hal::i2c::controller::{self, I2c, Speed};
11use hal::peripherals::LPI2C3;
12use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
13
14bind_interrupts!(
15 struct Irqs {
16 LPI2C3 => InterruptHandler<LPI2C3>;
17 }
18);
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) {
22 let mut config = Config::default();
23 config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1);
24
25 let p = hal::init(config);
26
27 defmt::info!("I2C example");
28
29 let mut config = controller::Config::default();
30 config.speed = Speed::Standard;
31 let mut i2c = I2c::new_async(p.LPI2C3, p.P3_27, p.P3_28, Irqs, config).unwrap();
32 let mut buf = [0u8; 2];
33
34 loop {
35 i2c.async_write_read(0x48, &[0x00], &mut buf).await.unwrap();
36 defmt::info!("Buffer: {:02x}", buf);
37 Timer::after_secs(1).await;
38 }
39}
diff --git a/examples/mcxa/src/bin/i2c-blocking.rs b/examples/mcxa/src/bin/i2c-blocking.rs
new file mode 100644
index 000000000..0f6c8cbae
--- /dev/null
+++ b/examples/mcxa/src/bin/i2c-blocking.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::clocks::config::Div8;
7use hal::config::Config;
8use hal::i2c::controller::{self, I2c, Speed};
9use tmp108::Tmp108;
10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let mut config = Config::default();
15 config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1);
16
17 let p = hal::init(config);
18
19 defmt::info!("I2C example");
20
21 let mut config = controller::Config::default();
22 config.speed = Speed::Standard;
23 let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap();
24 let mut tmp = Tmp108::new_with_a0_gnd(i2c);
25
26 loop {
27 let temperature = tmp.temperature().unwrap();
28 defmt::info!("Temperature: {}C", temperature);
29 Timer::after_secs(1).await;
30 }
31}
diff --git a/examples/mcxa/src/bin/i2c-scan-blocking.rs b/examples/mcxa/src/bin/i2c-scan-blocking.rs
new file mode 100644
index 000000000..bd706d712
--- /dev/null
+++ b/examples/mcxa/src/bin/i2c-scan-blocking.rs
@@ -0,0 +1,40 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::gpio::{Input, Pull};
6use embassy_time::Timer;
7use hal::clocks::config::Div8;
8use hal::config::Config;
9use hal::i2c::controller::{self, I2c, Speed};
10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let mut config = Config::default();
15 config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1);
16
17 let p = hal::init(config);
18
19 defmt::info!("I2C example");
20
21 let mut config = controller::Config::default();
22 config.speed = Speed::Standard;
23
24 // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and
25 // defaults to SWO on the debug peripheral. Explicitly make it a high-z
26 // input.
27 let _pin = Input::new(p.P0_2, Pull::Disabled);
28 let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap();
29
30 for addr in 0x01..=0x7f {
31 let result = i2c.blocking_write(addr, &[]);
32 if result.is_ok() {
33 defmt::info!("Device found at addr {:02x}", addr);
34 }
35 }
36
37 loop {
38 Timer::after_secs(10).await;
39 }
40}
diff --git a/examples/mcxa/src/bin/lpuart_buffered.rs b/examples/mcxa/src/bin/lpuart_buffered.rs
new file mode 100644
index 000000000..47b56b7c7
--- /dev/null
+++ b/examples/mcxa/src/bin/lpuart_buffered.rs
@@ -0,0 +1,62 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::clocks::config::Div8;
6use embassy_mcxa::lpuart::Config;
7use embassy_mcxa::lpuart::buffered::BufferedLpuart;
8use embassy_mcxa::{bind_interrupts, lpuart};
9use embedded_io_async::Write;
10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
11
12// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver
13bind_interrupts!(struct Irqs {
14 LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>;
15});
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 let mut cfg = hal::config::Config::default();
20 cfg.clock_cfg.sirc.fro_12m_enabled = true;
21 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
22 let p = hal::init(cfg);
23
24 // Configure NVIC for LPUART2
25 hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3);
26
27 // UART configuration (enable both TX and RX)
28 let config = Config {
29 baudrate_bps: 115_200,
30 rx_fifo_watermark: 0,
31 tx_fifo_watermark: 0,
32 ..Default::default()
33 };
34
35 let mut tx_buf = [0u8; 256];
36 let mut rx_buf = [0u8; 256];
37
38 // Create a buffered LPUART2 instance with both TX and RX
39 let mut uart = BufferedLpuart::new(
40 p.LPUART2,
41 p.P2_2, // TX pin
42 p.P2_3, // RX pin
43 Irqs,
44 &mut tx_buf,
45 &mut rx_buf,
46 config,
47 )
48 .unwrap();
49
50 // Split into TX and RX parts
51 let (tx, rx) = uart.split_ref();
52
53 tx.write(b"Hello buffered LPUART.\r\n").await.unwrap();
54 tx.write(b"Type characters to echo them back.\r\n").await.unwrap();
55
56 // Echo loop
57 let mut buf = [0u8; 4];
58 loop {
59 let used = rx.read(&mut buf).await.unwrap();
60 tx.write_all(&buf[..used]).await.unwrap();
61 }
62}
diff --git a/examples/mcxa/src/bin/lpuart_dma.rs b/examples/mcxa/src/bin/lpuart_dma.rs
new file mode 100644
index 000000000..cc86f6a40
--- /dev/null
+++ b/examples/mcxa/src/bin/lpuart_dma.rs
@@ -0,0 +1,68 @@
1//! LPUART DMA example for MCXA276.
2//!
3//! This example demonstrates using DMA for UART TX and RX operations.
4//! It sends a message using DMA, then waits for 16 characters to be received
5//! via DMA and echoes them back.
6//!
7//! The DMA request sources are automatically derived from the LPUART instance type.
8//! DMA clock/reset/init is handled automatically by the HAL.
9
10#![no_std]
11#![no_main]
12
13use embassy_executor::Spawner;
14use embassy_mcxa::clocks::config::Div8;
15use embassy_mcxa::lpuart::{Config, LpuartDma};
16use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 let mut cfg = hal::config::Config::default();
21 cfg.clock_cfg.sirc.fro_12m_enabled = true;
22 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
23 let p = hal::init(cfg);
24
25 defmt::info!("LPUART DMA example starting...");
26
27 // Create UART configuration
28 let config = Config {
29 baudrate_bps: 115_200,
30 ..Default::default()
31 };
32
33 // Create UART instance with DMA channels
34 let mut lpuart = LpuartDma::new(
35 p.LPUART2, // Instance
36 p.P2_2, // TX pin
37 p.P2_3, // RX pin
38 p.DMA_CH0, // TX DMA channel
39 p.DMA_CH1, // RX DMA channel
40 config,
41 )
42 .unwrap();
43
44 // Send a message using DMA (DMA request source is automatically derived from LPUART2)
45 let tx_msg = b"Hello from LPUART2 DMA TX!\r\n";
46 lpuart.write_dma(tx_msg).await.unwrap();
47
48 defmt::info!("TX DMA complete");
49
50 // Send prompt
51 let prompt = b"Type 16 characters to echo via DMA:\r\n";
52 lpuart.write_dma(prompt).await.unwrap();
53
54 // Receive 16 characters using DMA
55 let mut rx_buf = [0u8; 16];
56 lpuart.read_dma(&mut rx_buf).await.unwrap();
57
58 defmt::info!("RX DMA complete");
59
60 // Echo back the received data
61 let echo_prefix = b"\r\nReceived: ";
62 lpuart.write_dma(echo_prefix).await.unwrap();
63 lpuart.write_dma(&rx_buf).await.unwrap();
64 let done_msg = b"\r\nDone!\r\n";
65 lpuart.write_dma(done_msg).await.unwrap();
66
67 defmt::info!("Example complete");
68}
diff --git a/examples/mcxa/src/bin/lpuart_polling.rs b/examples/mcxa/src/bin/lpuart_polling.rs
new file mode 100644
index 000000000..b80668834
--- /dev/null
+++ b/examples/mcxa/src/bin/lpuart_polling.rs
@@ -0,0 +1,47 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::clocks::config::Div8;
6use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
7
8use crate::hal::lpuart::{Config, Lpuart};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let mut cfg = hal::config::Config::default();
13 cfg.clock_cfg.sirc.fro_12m_enabled = true;
14 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
15 let p = hal::init(cfg);
16
17 defmt::info!("boot");
18
19 // Create UART configuration
20 let config = Config {
21 baudrate_bps: 115_200,
22 ..Default::default()
23 };
24
25 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
26 let lpuart = Lpuart::new_blocking(
27 p.LPUART2, // Peripheral
28 p.P2_2, // TX pin
29 p.P2_3, // RX pin
30 config,
31 )
32 .unwrap();
33
34 // Split into separate TX and RX parts
35 let (mut tx, mut rx) = lpuart.split();
36
37 // Write hello messages
38 tx.blocking_write(b"Hello world.\r\n").unwrap();
39 tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap();
40
41 // Echo loop
42 loop {
43 let mut buf = [0u8; 1];
44 rx.blocking_read(&mut buf).unwrap();
45 tx.blocking_write(&buf).unwrap();
46 }
47}
diff --git a/examples/mcxa/src/bin/lpuart_ring_buffer.rs b/examples/mcxa/src/bin/lpuart_ring_buffer.rs
new file mode 100644
index 000000000..be7fd4534
--- /dev/null
+++ b/examples/mcxa/src/bin/lpuart_ring_buffer.rs
@@ -0,0 +1,115 @@
1//! LPUART Ring Buffer DMA example for MCXA276.
2//!
3//! This example demonstrates using the high-level `LpuartRxDma::setup_ring_buffer()`
4//! API for continuous circular DMA reception from a UART peripheral.
5//!
6//! # Features demonstrated:
7//! - `LpuartRxDma::setup_ring_buffer()` for continuous peripheral-to-memory DMA
8//! - `RingBuffer` for async reading of received data
9//! - Handling of potential overrun conditions
10//! - Half-transfer and complete-transfer interrupts for timely wakeups
11//!
12//! # How it works:
13//! 1. Create an `LpuartRxDma` driver with a DMA channel
14//! 2. Call `setup_ring_buffer()` which handles all low-level DMA configuration
15//! 3. Application asynchronously reads data as it arrives via `ring_buf.read()`
16//! 4. Both half-transfer and complete-transfer interrupts wake the reader
17
18#![no_std]
19#![no_main]
20
21use embassy_executor::Spawner;
22use embassy_mcxa::clocks::config::Div8;
23use embassy_mcxa::lpuart::{Config, LpuartDma, LpuartTxDma};
24use static_cell::ConstStaticCell;
25use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
26
27// Ring buffer for RX - power of 2 is ideal for modulo efficiency
28static RX_RING_BUFFER: ConstStaticCell<[u8; 64]> = ConstStaticCell::new([0; 64]);
29
30/// Helper to write a byte as hex to UART
31fn write_hex<T: embassy_mcxa::lpuart::Instance, C: embassy_mcxa::dma::Channel>(
32 tx: &mut LpuartTxDma<'_, T, C>,
33 byte: u8,
34) {
35 const HEX: &[u8; 16] = b"0123456789ABCDEF";
36 let buf = [HEX[(byte >> 4) as usize], HEX[(byte & 0x0F) as usize]];
37 tx.blocking_write(&buf).ok();
38}
39
40#[embassy_executor::main]
41async fn main(_spawner: Spawner) {
42 // Small delay to allow probe-rs to attach after reset
43 for _ in 0..100_000 {
44 cortex_m::asm::nop();
45 }
46
47 let mut cfg = hal::config::Config::default();
48 cfg.clock_cfg.sirc.fro_12m_enabled = true;
49 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
50 let p = hal::init(cfg);
51
52 defmt::info!("LPUART Ring Buffer DMA example starting...");
53
54 // Create UART configuration
55 let config = Config {
56 baudrate_bps: 115_200,
57 ..Default::default()
58 };
59
60 // Create LPUART with DMA support for both TX and RX, then split
61 // This is the proper Embassy pattern - create once, split into TX and RX
62 let lpuart = LpuartDma::new(p.LPUART2, p.P2_2, p.P2_3, p.DMA_CH1, p.DMA_CH0, config).unwrap();
63 let (mut tx, rx) = lpuart.split();
64
65 tx.blocking_write(b"LPUART Ring Buffer DMA Example\r\n").unwrap();
66 tx.blocking_write(b"==============================\r\n\r\n").unwrap();
67
68 tx.blocking_write(b"Setting up circular DMA for UART RX...\r\n")
69 .unwrap();
70
71 let buf = RX_RING_BUFFER.take();
72 // Set up the ring buffer with circular DMA
73 let mut ring_buf = rx.into_ring_dma_rx(buf);
74
75 tx.blocking_write(b"Ring buffer ready! Type characters to see them echoed.\r\n")
76 .unwrap();
77 tx.blocking_write(b"The DMA continuously receives in the background.\r\n\r\n")
78 .unwrap();
79
80 // Main loop: read from ring buffer and echo back
81 let mut read_buf = [0u8; 16];
82 let mut total_received: usize = 0;
83
84 loop {
85 // Async read - waits until data is available
86 match ring_buf.read(&mut read_buf).await {
87 Ok(n) if n > 0 => {
88 total_received += n;
89
90 // Echo back what we received
91 tx.blocking_write(b"RX[").unwrap();
92 for (i, &byte) in read_buf.iter().enumerate().take(n) {
93 write_hex(&mut tx, byte);
94 if i < n - 1 {
95 tx.blocking_write(b" ").unwrap();
96 }
97 }
98 tx.blocking_write(b"]: ").unwrap();
99 tx.blocking_write(&read_buf[..n]).unwrap();
100 tx.blocking_write(b"\r\n").unwrap();
101
102 defmt::info!("Received {} bytes, total: {}", n, total_received);
103 }
104 Ok(_) => {
105 // No data, shouldn't happen with async read
106 }
107 Err(_) => {
108 // Overrun detected
109 tx.blocking_write(b"ERROR: Ring buffer overrun!\r\n").unwrap();
110 defmt::error!("Ring buffer overrun!");
111 ring_buf.clear();
112 }
113 }
114 }
115}
diff --git a/examples/mcxa/src/bin/raw_dma_channel_link.rs b/examples/mcxa/src/bin/raw_dma_channel_link.rs
new file mode 100644
index 000000000..74785e4f3
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_channel_link.rs
@@ -0,0 +1,278 @@
1//! DMA channel linking example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates DMA channel linking (minor and major loop linking):
8//! - Channel 0: Transfers SRC_BUFFER to DEST_BUFFER0, with:
9//! - Minor Link to Channel 1 (triggers CH1 after each minor loop)
10//! - Major Link to Channel 2 (triggers CH2 after major loop completes)
11//! - Channel 1: Transfers SRC_BUFFER to DEST_BUFFER1 (triggered by CH0 minor link)
12//! - Channel 2: Transfers SRC_BUFFER to DEST_BUFFER2 (triggered by CH0 major link)
13//!
14//! # Embassy-style features demonstrated:
15//! - `DmaChannel::new()` for channel creation
16//! - `DmaChannel::is_done()` and `clear_done()` helper methods
17//! - Channel linking with `set_minor_link()` and `set_major_link()`
18
19#![no_std]
20#![no_main]
21
22use embassy_executor::Spawner;
23use embassy_mcxa::clocks::config::Div8;
24use embassy_mcxa::dma::DmaChannel;
25use embassy_mcxa::pac;
26use static_cell::ConstStaticCell;
27use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
28
29// Buffers
30static SRC_BUFFER: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([1, 2, 3, 4]);
31static DEST_BUFFER0: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
32static DEST_BUFFER1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
33static DEST_BUFFER2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]);
34
35#[embassy_executor::main]
36async fn main(_spawner: Spawner) {
37 // Small delay to allow probe-rs to attach after reset
38 for _ in 0..100_000 {
39 cortex_m::asm::nop();
40 }
41
42 let mut cfg = hal::config::Config::default();
43 cfg.clock_cfg.sirc.fro_12m_enabled = true;
44 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
45 let p = hal::init(cfg);
46
47 defmt::info!("DMA channel link example starting...");
48
49 // DMA is initialized during hal::init() - no need to call ensure_init()
50
51 let pac_periphs = unsafe { pac::Peripherals::steal() };
52 let dma0 = &pac_periphs.dma0;
53 let edma = unsafe { &*pac::Edma0Tcd0::ptr() };
54
55 // Clear any residual state
56 for i in 0..3 {
57 let t = edma.tcd(i);
58 t.ch_csr().write(|w| w.erq().disable().done().clear_bit_by_one());
59 t.ch_int().write(|w| w.int().clear_bit_by_one());
60 t.ch_es().write(|w| w.err().clear_bit_by_one());
61 t.ch_mux().write(|w| unsafe { w.bits(0) });
62 }
63
64 // Clear Global Halt/Error state
65 dma0.mp_csr().modify(|_, w| {
66 w.halt()
67 .normal_operation()
68 .hae()
69 .normal_operation()
70 .ecx()
71 .normal_operation()
72 .cx()
73 .normal_operation()
74 });
75
76 defmt::info!("EDMA channel link example begin.");
77
78 // Initialize buffers
79 let src = SRC_BUFFER.take();
80 let dst0 = DEST_BUFFER0.take();
81 let dst1 = DEST_BUFFER1.take();
82 let dst2 = DEST_BUFFER2.take();
83
84 defmt::info!("Source Buffer: {=[?]}", src.as_slice());
85 defmt::info!("DEST0 (before): {=[?]}", dst0.as_slice());
86 defmt::info!("DEST1 (before): {=[?]}", dst1.as_slice());
87 defmt::info!("DEST2 (before): {=[?]}", dst2.as_slice());
88
89 defmt::info!("Configuring DMA channels with Embassy-style API...");
90
91 let ch0 = DmaChannel::new(p.DMA_CH0);
92 let ch1 = DmaChannel::new(p.DMA_CH1);
93 let ch2 = DmaChannel::new(p.DMA_CH2);
94
95 // Configure channels using direct TCD access (advanced feature demo)
96 // This example demonstrates channel linking which requires direct TCD manipulation
97
98 // Helper to configure TCD for memory-to-memory transfer
99 // Parameters: channel, src, dst, width, nbytes (minor loop), count (major loop), interrupt
100 #[allow(clippy::too_many_arguments)]
101 unsafe fn configure_tcd(
102 edma: &embassy_mcxa::pac::edma_0_tcd0::RegisterBlock,
103 ch: usize,
104 src: u32,
105 dst: u32,
106 width: u8,
107 nbytes: u32,
108 count: u16,
109 enable_int: bool,
110 ) {
111 let t = edma.tcd(ch);
112
113 // Reset channel state
114 t.ch_csr().write(|w| {
115 w.erq()
116 .disable()
117 .earq()
118 .disable()
119 .eei()
120 .no_error()
121 .ebw()
122 .disable()
123 .done()
124 .clear_bit_by_one()
125 });
126 t.ch_es().write(|w| w.bits(0));
127 t.ch_int().write(|w| w.int().clear_bit_by_one());
128
129 // Source/destination addresses
130 t.tcd_saddr().write(|w| w.saddr().bits(src));
131 t.tcd_daddr().write(|w| w.daddr().bits(dst));
132
133 // Offsets: increment by width
134 t.tcd_soff().write(|w| w.soff().bits(width as u16));
135 t.tcd_doff().write(|w| w.doff().bits(width as u16));
136
137 // Attributes: size = log2(width)
138 let size = match width {
139 1 => 0,
140 2 => 1,
141 4 => 2,
142 _ => 0,
143 };
144 t.tcd_attr().write(|w| w.ssize().bits(size).dsize().bits(size));
145
146 // Number of bytes per minor loop
147 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
148
149 // Major loop: reset source address after major loop
150 let total_bytes = nbytes * count as u32;
151 t.tcd_slast_sda()
152 .write(|w| w.slast_sda().bits(-(total_bytes as i32) as u32));
153 t.tcd_dlast_sga()
154 .write(|w| w.dlast_sga().bits(-(total_bytes as i32) as u32));
155
156 // Major loop count
157 t.tcd_biter_elinkno().write(|w| w.biter().bits(count));
158 t.tcd_citer_elinkno().write(|w| w.citer().bits(count));
159
160 // Control/status: enable interrupt if requested
161 if enable_int {
162 t.tcd_csr().write(|w| w.intmajor().set_bit());
163 } else {
164 t.tcd_csr().write(|w| w.intmajor().clear_bit());
165 }
166
167 cortex_m::asm::dsb();
168 }
169
170 unsafe {
171 // Channel 0: Transfer 16 bytes total (8 bytes per minor loop, 2 major iterations)
172 // Minor Link -> Channel 1
173 // Major Link -> Channel 2
174 configure_tcd(
175 edma,
176 0,
177 src.as_ptr() as u32,
178 dst0.as_mut_ptr() as u32,
179 4, // src width
180 8, // nbytes (minor loop = 2 words)
181 2, // count (major loop = 2 iterations)
182 false, // no interrupt
183 );
184 ch0.set_minor_link(1); // Link to CH1 after each minor loop
185 ch0.set_major_link(2); // Link to CH2 after major loop
186
187 // Channel 1: Transfer 16 bytes (triggered by CH0 minor link)
188 configure_tcd(
189 edma,
190 1,
191 src.as_ptr() as u32,
192 dst1.as_mut_ptr() as u32,
193 4,
194 16, // full buffer in one minor loop
195 1, // 1 major iteration
196 false,
197 );
198
199 // Channel 2: Transfer 16 bytes (triggered by CH0 major link)
200 configure_tcd(
201 edma,
202 2,
203 src.as_ptr() as u32,
204 dst2.as_mut_ptr() as u32,
205 4,
206 16, // full buffer in one minor loop
207 1, // 1 major iteration
208 true, // enable interrupt
209 );
210 }
211
212 defmt::info!("Triggering Channel 0 (1st minor loop)...");
213
214 // Trigger first minor loop of CH0
215 unsafe {
216 ch0.trigger_start();
217 }
218
219 // Wait for CH1 to complete (triggered by CH0 minor link)
220 while !ch1.is_done() {
221 cortex_m::asm::nop();
222 }
223 unsafe {
224 ch1.clear_done();
225 }
226
227 defmt::info!("CH1 done (via minor link).");
228 defmt::info!("Triggering Channel 0 (2nd minor loop)...");
229
230 // Trigger second minor loop of CH0
231 unsafe {
232 ch0.trigger_start();
233 }
234
235 // Wait for CH0 major loop to complete
236 while !ch0.is_done() {
237 cortex_m::asm::nop();
238 }
239 unsafe {
240 ch0.clear_done();
241 }
242
243 defmt::info!("CH0 major loop done.");
244
245 // Wait for CH2 to complete (triggered by CH0 major link)
246 // Using is_done() instead of AtomicBool - the standard interrupt handler
247 // clears the interrupt flag and wakes wakers, but DONE bit remains set
248 while !ch2.is_done() {
249 cortex_m::asm::nop();
250 }
251 unsafe {
252 ch2.clear_done();
253 }
254
255 defmt::info!("CH2 done (via major link).");
256
257 defmt::info!("EDMA channel link example finish.");
258
259 defmt::info!("DEST0 (after): {=[?]}", dst0.as_slice());
260 defmt::info!("DEST1 (after): {=[?]}", dst1.as_slice());
261 defmt::info!("DEST2 (after): {=[?]}", dst2.as_slice());
262
263 // Verify all buffers match source
264 let mut success = true;
265 for sli in [dst0, dst1, dst2] {
266 success &= sli == src;
267 }
268
269 if success {
270 defmt::info!("PASS: Data verified.");
271 } else {
272 defmt::error!("FAIL: Mismatch detected!");
273 }
274
275 loop {
276 cortex_m::asm::wfe();
277 }
278}
diff --git a/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs b/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs
new file mode 100644
index 000000000..a383b6cf4
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_interleave_transfer.rs
@@ -0,0 +1,141 @@
1//! DMA interleaved transfer example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates using DMA with custom source/destination offsets
8//! to interleave data during transfer.
9//!
10//! # Embassy-style features demonstrated:
11//! - `TransferOptions::default()` for configuration (used internally)
12//! - DMA channel with `DmaChannel::new()`
13
14#![no_std]
15#![no_main]
16
17use embassy_executor::Spawner;
18use embassy_mcxa::clocks::config::Div8;
19use embassy_mcxa::dma::DmaChannel;
20use static_cell::ConstStaticCell;
21use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
22
23const BUFFER_LENGTH: usize = 16;
24const HALF_BUFF_LENGTH: usize = BUFFER_LENGTH / 2;
25
26// Buffers in RAM
27static SRC_BUFFER: ConstStaticCell<[u32; HALF_BUFF_LENGTH]> = ConstStaticCell::new([0; HALF_BUFF_LENGTH]);
28static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
29
30#[embassy_executor::main]
31async fn main(_spawner: Spawner) {
32 // Small delay to allow probe-rs to attach after reset
33 for _ in 0..100_000 {
34 cortex_m::asm::nop();
35 }
36
37 let mut cfg = hal::config::Config::default();
38 cfg.clock_cfg.sirc.fro_12m_enabled = true;
39 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
40 let p = hal::init(cfg);
41
42 defmt::info!("DMA interleave transfer example starting...");
43
44 defmt::info!("EDMA interleave transfer example begin.");
45
46 // Initialize buffers
47 let src = SRC_BUFFER.take();
48 *src = [1, 2, 3, 4, 5, 6, 7, 8];
49 let dst = DEST_BUFFER.take();
50
51 defmt::info!("Source Buffer: {=[?]}", src.as_slice());
52 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
53
54 defmt::info!("Configuring DMA with Embassy-style API...");
55
56 // Create DMA channel using Embassy-style API
57 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
58
59 // Configure interleaved transfer using direct TCD access:
60 // - src_offset = 4: advance source by 4 bytes after each read
61 // - dst_offset = 8: advance dest by 8 bytes after each write
62 // This spreads source data across every other word in destination
63 unsafe {
64 let t = dma_ch0.tcd();
65
66 // Reset channel state
67 t.ch_csr().write(|w| {
68 w.erq()
69 .disable()
70 .earq()
71 .disable()
72 .eei()
73 .no_error()
74 .ebw()
75 .disable()
76 .done()
77 .clear_bit_by_one()
78 });
79 t.ch_es().write(|w| w.bits(0));
80 t.ch_int().write(|w| w.int().clear_bit_by_one());
81
82 // Source/destination addresses
83 t.tcd_saddr().write(|w| w.saddr().bits(src.as_ptr() as u32));
84 t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32));
85
86 // Custom offsets for interleaving
87 t.tcd_soff().write(|w| w.soff().bits(4)); // src: +4 bytes per read
88 t.tcd_doff().write(|w| w.doff().bits(8)); // dst: +8 bytes per write
89
90 // Attributes: 32-bit transfers (size = 2)
91 t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2));
92
93 // Transfer entire source buffer in one minor loop
94 let nbytes = (HALF_BUFF_LENGTH * 4) as u32;
95 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
96
97 // Reset source address after major loop
98 t.tcd_slast_sda().write(|w| w.slast_sda().bits(-(nbytes as i32) as u32));
99 // Destination uses 2x offset, so adjust accordingly
100 let dst_total = (HALF_BUFF_LENGTH * 8) as u32;
101 t.tcd_dlast_sga()
102 .write(|w| w.dlast_sga().bits(-(dst_total as i32) as u32));
103
104 // Major loop count = 1
105 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
106 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
107
108 // Enable interrupt on major loop completion
109 t.tcd_csr().write(|w| w.intmajor().set_bit());
110
111 cortex_m::asm::dsb();
112
113 defmt::info!("Triggering transfer...");
114 dma_ch0.trigger_start();
115 }
116
117 // Wait for completion using channel helper method
118 while !dma_ch0.is_done() {
119 cortex_m::asm::nop();
120 }
121 unsafe {
122 dma_ch0.clear_done();
123 }
124
125 defmt::info!("EDMA interleave transfer example finish.");
126 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
127
128 // Verify: Even indices should match SRC_BUFFER[i/2], odd indices should be 0
129 let mut mismatch = false;
130 let diter = dst.chunks_exact(2);
131 let siter = src.iter();
132 for (ch, src) in diter.zip(siter) {
133 mismatch |= !matches!(ch, [a, 0] if a == src);
134 }
135
136 if mismatch {
137 defmt::error!("FAIL: Mismatch detected!");
138 } else {
139 defmt::info!("PASS: Data verified.");
140 }
141}
diff --git a/examples/mcxa/src/bin/raw_dma_memset.rs b/examples/mcxa/src/bin/raw_dma_memset.rs
new file mode 100644
index 000000000..7b3c06ffa
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_memset.rs
@@ -0,0 +1,129 @@
1//! DMA memset example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates using DMA to fill a buffer with a repeated pattern.
8//! The source address stays fixed while the destination increments.
9//!
10//! # Embassy-style features demonstrated:
11//! - `DmaChannel::is_done()` and `clear_done()` helper methods
12//! - No need to pass register block around
13
14#![no_std]
15#![no_main]
16
17use embassy_executor::Spawner;
18use embassy_mcxa::clocks::config::Div8;
19use embassy_mcxa::dma::DmaChannel;
20use static_cell::ConstStaticCell;
21use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
22
23const BUFFER_LENGTH: usize = 4;
24
25// Buffers in RAM
26static PATTERN: u32 = 0xDEADBEEF;
27static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
28
29#[embassy_executor::main]
30async fn main(_spawner: Spawner) {
31 // Small delay to allow probe-rs to attach after reset
32 for _ in 0..100_000 {
33 cortex_m::asm::nop();
34 }
35
36 let mut cfg = hal::config::Config::default();
37 cfg.clock_cfg.sirc.fro_12m_enabled = true;
38 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
39 let p = hal::init(cfg);
40
41 defmt::info!("DMA memset example starting...");
42 defmt::info!("EDMA memset example begin.");
43
44 // Initialize buffers
45 let pat = &PATTERN;
46 let dst = DEST_BUFFER.take();
47 defmt::info!("Pattern Value: {=u32}", pat);
48 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
49 defmt::info!("Configuring DMA with Embassy-style API...");
50
51 // Create DMA channel using Embassy-style API
52 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
53
54 // Configure memset transfer using direct TCD access:
55 // Source stays fixed (soff = 0, reads same pattern repeatedly)
56 // Destination increments (doff = 4)
57 unsafe {
58 let t = dma_ch0.tcd();
59
60 // Reset channel state
61 t.ch_csr().write(|w| {
62 w.erq()
63 .disable()
64 .earq()
65 .disable()
66 .eei()
67 .no_error()
68 .ebw()
69 .disable()
70 .done()
71 .clear_bit_by_one()
72 });
73 t.ch_es().write(|w| w.bits(0));
74 t.ch_int().write(|w| w.int().clear_bit_by_one());
75
76 // Source address (pattern) - fixed
77 t.tcd_saddr().write(|w| w.saddr().bits(pat as *const _ as u32));
78 // Destination address - increments
79 t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32));
80
81 // Source offset = 0 (stays fixed), Dest offset = 4 (increments)
82 t.tcd_soff().write(|w| w.soff().bits(0));
83 t.tcd_doff().write(|w| w.doff().bits(4));
84
85 // Attributes: 32-bit transfers (size = 2)
86 t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2));
87
88 // Transfer entire buffer in one minor loop
89 let nbytes = (BUFFER_LENGTH * 4) as u32;
90 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
91
92 // Source doesn't need adjustment (stays fixed)
93 t.tcd_slast_sda().write(|w| w.slast_sda().bits(0));
94 // Reset dest address after major loop
95 t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32));
96
97 // Major loop count = 1
98 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
99 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
100
101 // Enable interrupt on major loop completion
102 t.tcd_csr().write(|w| w.intmajor().set_bit());
103
104 cortex_m::asm::dsb();
105
106 defmt::info!("Triggering transfer...");
107 dma_ch0.trigger_start();
108 }
109
110 // Wait for completion using channel helper method
111 while !dma_ch0.is_done() {
112 cortex_m::asm::nop();
113 }
114 unsafe {
115 dma_ch0.clear_done();
116 }
117
118 defmt::info!("EDMA memset example finish.");
119 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
120
121 // Verify: All elements should equal PATTERN
122 let mismatch = dst.iter().any(|i| *i != *pat);
123
124 if mismatch {
125 defmt::error!("FAIL: Mismatch detected!");
126 } else {
127 defmt::info!("PASS: Data verified.");
128 }
129}
diff --git a/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs b/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs
new file mode 100644
index 000000000..80df40449
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_ping_pong_transfer.rs
@@ -0,0 +1,244 @@
1//! DMA ping-pong/double-buffer transfer example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates two approaches for ping-pong/double-buffering:
8//!
9//! ## Approach 1: Scatter/Gather with linked TCDs (manual)
10//! - Two TCDs link to each other for alternating transfers
11//! - Uses custom handler that delegates to on_interrupt() then signals completion
12//! - Note: With ESG=1, DONE bit is cleared by hardware when next TCD loads,
13//! so we need an AtomicBool to track completion
14//!
15//! ## Approach 2: Half-transfer interrupt with wait_half() (NEW!)
16//! - Single continuous transfer over entire buffer
17//! - Uses half-transfer interrupt to know when first half is ready
18//! - Application can process first half while second half is being filled
19//!
20//! # Embassy-style features demonstrated:
21//! - `DmaChannel::new()` for channel creation
22//! - Scatter/gather with linked TCDs
23//! - Custom handler that delegates to HAL's `on_interrupt()` (best practice)
24//! - Standard `DmaCh1InterruptHandler` with `bind_interrupts!` macro
25//! - NEW: `wait_half()` for half-transfer interrupt handling
26
27#![no_std]
28#![no_main]
29
30use embassy_executor::Spawner;
31use embassy_mcxa::clocks::config::Div8;
32use embassy_mcxa::dma::{DmaChannel, Tcd, TransferOptions};
33use embassy_mcxa::pac;
34use static_cell::ConstStaticCell;
35use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
36
37// Source and destination buffers for Approach 1 (scatter/gather)
38static SRC: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([1, 2, 3, 4, 5, 6, 7, 8]);
39static DST: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0; 8]);
40
41// Source and destination buffers for Approach 2 (wait_half)
42static SRC2: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0xA1, 0xA2, 0xA3, 0xA4, 0xB1, 0xB2, 0xB3, 0xB4]);
43static DST2: ConstStaticCell<[u32; 8]> = ConstStaticCell::new([0; 8]);
44
45// TCD pool for scatter/gather - must be 32-byte aligned
46#[repr(C, align(32))]
47struct TcdPool([Tcd; 2]);
48
49static TCD_POOL: ConstStaticCell<TcdPool> = ConstStaticCell::new(TcdPool(
50 [Tcd {
51 saddr: 0,
52 soff: 0,
53 attr: 0,
54 nbytes: 0,
55 slast: 0,
56 daddr: 0,
57 doff: 0,
58 citer: 0,
59 dlast_sga: 0,
60 csr: 0,
61 biter: 0,
62 }; 2],
63));
64
65#[embassy_executor::main]
66async fn main(_spawner: Spawner) {
67 // Small delay to allow probe-rs to attach after reset
68 for _ in 0..100_000 {
69 cortex_m::asm::nop();
70 }
71
72 let mut cfg = hal::config::Config::default();
73 cfg.clock_cfg.sirc.fro_12m_enabled = true;
74 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
75 let p = hal::init(cfg);
76
77 defmt::info!("DMA ping-pong transfer example starting...");
78
79 defmt::info!("EDMA ping-pong transfer example begin.");
80
81 // Initialize buffers
82 let src = SRC.take();
83 let dst = DST.take();
84
85 defmt::info!("Source Buffer: {=[?]}", src.as_slice());
86 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
87
88 defmt::info!("Configuring ping-pong DMA with Embassy-style API...");
89
90 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
91
92 // Configure ping-pong transfer using direct TCD access:
93 // This sets up TCD0 and TCD1 in RAM, and loads TCD0 into the channel.
94 // TCD0 transfers first half (SRC[0..4] -> DST[0..4]), links to TCD1.
95 // TCD1 transfers second half (SRC[4..8] -> DST[4..8]), links to TCD0.
96 let tcds = &mut TCD_POOL.take().0;
97
98 let half_len = 4usize;
99 let half_bytes = (half_len * 4) as u32;
100
101 unsafe {
102 let tcd0_addr = &tcds[0] as *const _ as u32;
103 let tcd1_addr = &tcds[1] as *const _ as u32;
104
105 // TCD0: First half -> Links to TCD1
106 tcds[0] = Tcd {
107 saddr: src.as_ptr() as u32,
108 soff: 4,
109 attr: 0x0202, // 32-bit src/dst
110 nbytes: half_bytes,
111 slast: 0,
112 daddr: dst.as_mut_ptr() as u32,
113 doff: 4,
114 citer: 1,
115 dlast_sga: tcd1_addr as i32,
116 csr: 0x0012, // ESG | INTMAJOR
117 biter: 1,
118 };
119
120 // TCD1: Second half -> Links to TCD0
121 tcds[1] = Tcd {
122 saddr: src.as_ptr().add(half_len) as u32,
123 soff: 4,
124 attr: 0x0202,
125 nbytes: half_bytes,
126 slast: 0,
127 daddr: dst.as_mut_ptr().add(half_len) as u32,
128 doff: 4,
129 citer: 1,
130 dlast_sga: tcd0_addr as i32,
131 csr: 0x0012,
132 biter: 1,
133 };
134
135 // Load TCD0 into hardware registers
136 dma_ch0.load_tcd(&tcds[0]);
137 }
138
139 defmt::info!("Triggering first half transfer...");
140
141 // Trigger first transfer (first half: SRC[0..4] -> DST[0..4])
142 unsafe {
143 dma_ch0.trigger_start();
144 }
145
146 let tcd = dma_ch0.tcd();
147 // Wait for first half
148 loop {
149 if tcd.tcd_saddr().read().bits() != src.as_ptr() as u32 {
150 break;
151 }
152 }
153
154 defmt::info!("First half transferred.");
155 defmt::info!("Triggering second half transfer...");
156
157 // Trigger second transfer (second half: SRC[4..8] -> DST[4..8])
158 unsafe {
159 dma_ch0.trigger_start();
160 }
161
162 // Wait for second half
163 loop {
164 if tcd.tcd_saddr().read().bits() != unsafe { src.as_ptr().add(half_len) } as u32 {
165 break;
166 }
167 }
168
169 defmt::info!("Second half transferred.");
170
171 defmt::info!("EDMA ping-pong transfer example finish.");
172 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
173
174 // Verify: DST should match SRC
175 let mismatch = src != dst;
176
177 if mismatch {
178 defmt::error!("FAIL: Approach 1 mismatch detected!");
179 } else {
180 defmt::info!("PASS: Approach 1 data verified.");
181 }
182
183 // =========================================================================
184 // Approach 2: Half-Transfer Interrupt with wait_half() (NEW!)
185 // =========================================================================
186 //
187 // This approach uses a single continuous DMA transfer with half-transfer
188 // interrupt enabled. The wait_half() method allows you to be notified
189 // when the first half of the buffer is complete, so you can process it
190 // while the second half is still being filled.
191 //
192 // Benefits:
193 // - Simpler setup (no TCD pool needed)
194 // - True async/await support
195 // - Good for streaming data processing
196
197 defmt::info!("--- Approach 2: wait_half() demo ---");
198
199 // Enable DMA CH1 interrupt
200 unsafe {
201 cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH1);
202 }
203
204 // Initialize approach 2 buffers
205 let src2 = SRC2.take();
206 let dst2 = DST2.take();
207
208 defmt::info!("SRC2: {=[?]}", src2.as_slice());
209
210 let dma_ch1 = DmaChannel::new(p.DMA_CH1);
211
212 // Configure transfer with half-transfer interrupt enabled
213 let mut options = TransferOptions::default();
214 options.half_transfer_interrupt = true; // Enable half-transfer interrupt
215 options.complete_transfer_interrupt = true;
216
217 defmt::info!("Starting transfer with half_transfer_interrupt...");
218
219 // Create the transfer
220 let mut transfer = dma_ch1.mem_to_mem(src2, dst2, options).unwrap();
221
222 // Wait for half-transfer (first 4 elements)
223 defmt::info!("Waiting for first half...");
224 let _ok = transfer.wait_half().await.unwrap();
225
226 defmt::info!("Half-transfer complete!");
227
228 // Wait for complete transfer
229 defmt::info!("Waiting for second half...");
230 transfer.await.unwrap();
231
232 defmt::info!("Transfer complete! Full DST2: {=[?]}", dst2.as_slice());
233
234 // Verify approach 2
235 let mismatch2 = src2 != dst2;
236
237 if mismatch2 {
238 defmt::error!("FAIL: Approach 2 mismatch!");
239 } else {
240 defmt::info!("PASS: Approach 2 verified.");
241 }
242
243 defmt::info!("=== All ping-pong demos complete ===");
244}
diff --git a/examples/mcxa/src/bin/raw_dma_scatter_gather.rs b/examples/mcxa/src/bin/raw_dma_scatter_gather.rs
new file mode 100644
index 000000000..eb9960764
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_scatter_gather.rs
@@ -0,0 +1,165 @@
1//! DMA scatter-gather transfer example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates using DMA with scatter/gather to chain multiple
8//! transfer descriptors. The first TCD transfers the first half of the buffer,
9//! then automatically loads the second TCD to transfer the second half.
10//!
11//! # Embassy-style features demonstrated:
12//! - `DmaChannel::new()` for channel creation
13//! - Scatter/gather with chained TCDs
14//! - Custom handler that delegates to HAL's `on_interrupt()` (best practice)
15
16#![no_std]
17#![no_main]
18
19use embassy_executor::Spawner;
20use embassy_mcxa::clocks::config::Div8;
21use embassy_mcxa::dma::{DmaChannel, Tcd};
22use static_cell::ConstStaticCell;
23use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
24
25// Source and destination buffers
26static SRC: ConstStaticCell<[u32; 12]> = ConstStaticCell::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
27static DST: ConstStaticCell<[u32; 12]> = ConstStaticCell::new([0; 12]);
28
29// TCD pool for scatter/gather - must be 32-byte aligned
30#[repr(C, align(32))]
31struct TcdPool([Tcd; 2]);
32
33static TCD_POOL: ConstStaticCell<TcdPool> = ConstStaticCell::new(TcdPool(
34 [Tcd {
35 saddr: 0,
36 soff: 0,
37 attr: 0,
38 nbytes: 0,
39 slast: 0,
40 daddr: 0,
41 doff: 0,
42 citer: 0,
43 dlast_sga: 0,
44 csr: 0,
45 biter: 0,
46 }; 2],
47));
48
49#[embassy_executor::main]
50async fn main(_spawner: Spawner) {
51 // Small delay to allow probe-rs to attach after reset
52 for _ in 0..100_000 {
53 cortex_m::asm::nop();
54 }
55
56 let mut cfg = hal::config::Config::default();
57 cfg.clock_cfg.sirc.fro_12m_enabled = true;
58 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
59 let p = hal::init(cfg);
60
61 defmt::info!("DMA scatter-gather transfer example starting...");
62
63 defmt::info!("EDMA scatter-gather transfer example begin.");
64
65 // Initialize buffers
66 let src = SRC.take();
67 let dst = DST.take();
68
69 defmt::info!("Source Buffer: {=[?]}", src.as_slice());
70 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
71 defmt::info!("Configuring scatter-gather DMA with Embassy-style API...");
72
73 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
74 let src_ptr = src.as_ptr();
75 let dst_ptr = dst.as_mut_ptr();
76
77 // Configure scatter-gather transfer using direct TCD access:
78 // This sets up TCD0 and TCD1 in RAM, and loads TCD0 into the channel.
79 // TCD0 transfers first half (SRC[0..4] -> DST[0..4]), then loads TCD1.
80 // TCD1 transfers second half (SRC[4..12] -> DST[4..12]), last TCD.
81 unsafe {
82 let tcds = &mut TCD_POOL.take().0;
83
84 // In the first transfer, copy
85 tcds[0] = Tcd {
86 saddr: src_ptr as u32,
87 soff: 4,
88 attr: 0x0202, // 32-bit src/dst
89 nbytes: 4 * 4,
90 slast: 0,
91 daddr: dst_ptr as u32,
92 doff: 4,
93 citer: 1,
94 dlast_sga: tcds.as_ptr().add(1) as i32,
95 // ESG (scatter/gather) for non-last, INTMAJOR for all
96 csr: 0x0012,
97 biter: 1,
98 };
99
100 tcds[1] = Tcd {
101 saddr: src_ptr.add(4) as u32,
102 soff: 4,
103 attr: 0x0202, // 32-bit src/dst
104 nbytes: 8 * 4,
105 slast: 0,
106 daddr: dst_ptr.add(4) as u32,
107 doff: 4,
108 citer: 1,
109 dlast_sga: 0,
110 // ESG (scatter/gather) for non-last, INTMAJOR for all
111 csr: 0x0002,
112 biter: 1,
113 };
114
115 // Load TCD0 into hardware registers
116 dma_ch0.load_tcd(&tcds[0]);
117 }
118
119 defmt::info!("Triggering first half transfer...");
120
121 let tcd = dma_ch0.tcd();
122
123 // Trigger first transfer (first half: SRC[0..4] -> DST[0..4])
124 // TCD0 is currently loaded.
125 unsafe {
126 dma_ch0.trigger_start();
127 }
128
129 // Wait for first half
130 loop {
131 if tcd.tcd_saddr().read().bits() != src_ptr as u32 {
132 defmt::info!("saddr: {=u32}", tcd.tcd_saddr().read().bits());
133 defmt::info!("srptr: {=u32}", src_ptr as u32);
134 break;
135 }
136 }
137
138 defmt::info!("First half transferred.");
139 defmt::info!("Triggering second half transfer...");
140
141 // Trigger second transfer (second half: SRC[4..8] -> DST[4..8])
142 // TCD1 should have been loaded by the scatter/gather engine.
143 unsafe {
144 dma_ch0.trigger_start();
145 }
146
147 // Wait for second half
148 while !dma_ch0.is_done() {
149 cortex_m::asm::nop();
150 }
151
152 defmt::info!("Second half transferred.");
153
154 defmt::info!("EDMA scatter-gather transfer example finish.");
155 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
156
157 // Verify: DST should match SRC
158 let mismatch = src != dst;
159
160 if mismatch {
161 defmt::error!("FAIL: Mismatch detected!");
162 } else {
163 defmt::info!("PASS: Data verified.");
164 }
165}
diff --git a/examples/mcxa/src/bin/reset-reason.rs b/examples/mcxa/src/bin/reset-reason.rs
new file mode 100644
index 000000000..c244fbe04
--- /dev/null
+++ b/examples/mcxa/src/bin/reset-reason.rs
@@ -0,0 +1,15 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use hal::config::Config;
6use hal::reset_reason::reset_reason;
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let config = Config::default();
12 let _p = hal::init(config);
13
14 defmt::info!("Reset Reason: '{}'", reset_reason());
15}
diff --git a/examples/mcxa/src/bin/rtc_alarm.rs b/examples/mcxa/src/bin/rtc_alarm.rs
new file mode 100644
index 000000000..fe355888b
--- /dev/null
+++ b/examples/mcxa/src/bin/rtc_alarm.rs
@@ -0,0 +1,47 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::bind_interrupts;
6use hal::rtc::{InterruptHandler, Rtc, RtcDateTime};
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9bind_interrupts!(struct Irqs {
10 RTC => InterruptHandler<hal::rtc::Rtc0>;
11});
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = hal::init(hal::config::Config::default());
16
17 defmt::info!("=== RTC Alarm Example ===");
18
19 let rtc_config = hal::rtc::get_default_config();
20
21 let mut rtc = Rtc::new(p.RTC0, Irqs, rtc_config);
22
23 let now = RtcDateTime {
24 year: 2025,
25 month: 10,
26 day: 15,
27 hour: 14,
28 minute: 30,
29 second: 0,
30 };
31
32 rtc.stop();
33
34 defmt::info!("Time set to: 2025-10-15 14:30:00");
35 rtc.set_datetime(now);
36
37 let mut alarm = now;
38 alarm.second += 10;
39
40 defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)");
41 defmt::info!("RTC started, waiting for alarm...");
42
43 rtc.wait_for_alarm(alarm).await;
44 defmt::info!("*** ALARM TRIGGERED! ***");
45
46 defmt::info!("Example complete - Test PASSED!");
47}
diff --git a/examples/mcxa/src/bin/trng.rs b/examples/mcxa/src/bin/trng.rs
new file mode 100644
index 000000000..5f6e2408c
--- /dev/null
+++ b/examples/mcxa/src/bin/trng.rs
@@ -0,0 +1,106 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use hal::bind_interrupts;
6use hal::config::Config;
7use hal::trng::{self, InterruptHandler, Trng};
8use rand_core::RngCore;
9use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
10
11bind_interrupts!(
12 struct Irqs {
13 TRNG0 => InterruptHandler;
14 }
15);
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 let config = Config::default();
20 let mut p = hal::init(config);
21
22 defmt::info!("TRNG example");
23
24 let mut trng = Trng::new_blocking_128(p.TRNG0.reborrow());
25 let rand = trng.blocking_next_u32();
26 defmt::info!("128-bit {}", rand);
27
28 drop(trng);
29
30 let mut trng = Trng::new_blocking_256(p.TRNG0.reborrow());
31 let rand = trng.blocking_next_u32();
32 defmt::info!("256-bit {}", rand);
33
34 drop(trng);
35
36 let mut trng = Trng::new_blocking_512(p.TRNG0.reborrow());
37 let rand = trng.blocking_next_u32();
38 defmt::info!("512-bit {}", rand);
39
40 drop(trng);
41
42 let config = trng::Config::default();
43 let mut trng = Trng::new_blocking_with_custom_config(p.TRNG0.reborrow(), config);
44
45 defmt::info!("========== BLOCKING ==========");
46
47 defmt::info!("Generate 10 u32");
48 for _ in 0..10 {
49 let rand = trng.blocking_next_u32();
50 defmt::info!("{}", rand);
51 }
52
53 defmt::info!("Generate 10 u64");
54 for _ in 0..10 {
55 let rand = trng.blocking_next_u64();
56 defmt::info!("{}", rand);
57 }
58
59 let mut buf = [0_u8; 256];
60
61 defmt::info!("Generate 10 256-byte buffers");
62 for _ in 0..10 {
63 trng.blocking_fill_bytes(&mut buf);
64 defmt::info!("{:02x}", buf);
65 }
66
67 defmt::info!("RngCore");
68
69 for _ in 0..10 {
70 defmt::info!("u32: {}", trng.next_u32());
71 defmt::info!("u64: {}", trng.next_u64());
72 }
73
74 drop(trng);
75
76 defmt::info!("========== ASYNC ==========");
77
78 let mut trng = Trng::new_with_custom_config(p.TRNG0.reborrow(), Irqs, config);
79
80 defmt::info!("Generate 10 u32");
81 for _ in 0..10 {
82 let rand = trng.async_next_u32().await.unwrap();
83 defmt::info!("{}", rand);
84 }
85
86 defmt::info!("Generate 10 u64");
87 for _ in 0..10 {
88 let rand = trng.async_next_u64().await.unwrap();
89 defmt::info!("{}", rand);
90 }
91
92 let mut buf = [0_u8; 256];
93
94 defmt::info!("Generate 10 256-byte buffers");
95 for _ in 0..10 {
96 trng.async_fill_bytes(&mut buf).await.unwrap();
97 defmt::info!("{:02x}", buf);
98 }
99
100 defmt::info!("RngCore");
101
102 for _ in 0..10 {
103 defmt::info!("u32: {}", trng.next_u32());
104 defmt::info!("u64: {}", trng.next_u64());
105 }
106}
diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml
index 3038f5d4d..d784ce729 100644
--- a/examples/mimxrt1011/Cargo.toml
+++ b/examples/mimxrt1011/Cargo.toml
@@ -1,7 +1,7 @@
1[package] 1[package]
2name = "embassy-imxrt1011-examples" 2name = "embassy-imxrt1011-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2024"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
diff --git a/examples/mimxrt1011/src/lib.rs b/examples/mimxrt1011/src/lib.rs
index f0391ef57..36d3e2fb3 100644
--- a/examples/mimxrt1011/src/lib.rs
+++ b/examples/mimxrt1011/src/lib.rs
@@ -71,5 +71,5 @@ pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock =
71 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); 71 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30);
72 72
73#[unsafe(no_mangle)] 73#[unsafe(no_mangle)]
74#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] 74#[cfg_attr(all(target_arch = "arm", target_os = "none"), unsafe(link_section = ".fcb"))]
75pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; 75pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;
diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml
index 82a24490d..29a80db12 100644
--- a/examples/mimxrt1062-evk/Cargo.toml
+++ b/examples/mimxrt1062-evk/Cargo.toml
@@ -1,7 +1,7 @@
1[package] 1[package]
2name = "embassy-imxrt1062-evk-examples" 2name = "embassy-imxrt1062-evk-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2024"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
diff --git a/examples/mimxrt1062-evk/src/lib.rs b/examples/mimxrt1062-evk/src/lib.rs
index 3f99f9db3..e952b91ec 100644
--- a/examples/mimxrt1062-evk/src/lib.rs
+++ b/examples/mimxrt1062-evk/src/lib.rs
@@ -55,6 +55,6 @@ pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock =
55 .sector_size(4096) 55 .sector_size(4096)
56 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30); 56 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30);
57 57
58#[no_mangle] 58#[unsafe(no_mangle)]
59#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")] 59#[cfg_attr(all(target_arch = "arm", target_os = "none"), unsafe(link_section = ".fcb"))]
60pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK; 60pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;
diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml
index 3f7ad8485..ada112833 100644
--- a/examples/mimxrt6/Cargo.toml
+++ b/examples/mimxrt6/Cargo.toml
@@ -1,7 +1,7 @@
1[package] 1[package]
2name = "embassy-imxrt-examples" 2name = "embassy-imxrt-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2024"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
@@ -21,6 +21,8 @@ embedded-hal-async = "1.0.0"
21 21
22mimxrt600-fcb = "0.2.2" 22mimxrt600-fcb = "0.2.2"
23panic-probe = { version = "1.0.0", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24embedded-hal-bus = "0.3.0"
25is31fl3743b-driver = { version = "0.1.1", features = ["is_blocking"] }
24 26
25# cargo build/run 27# cargo build/run
26[profile.dev] 28[profile.dev]
diff --git a/examples/mimxrt6/src/bin/button.rs b/examples/mimxrt6/src/bin/button.rs
index efb7f14af..a9bdde98e 100644
--- a/examples/mimxrt6/src/bin/button.rs
+++ b/examples/mimxrt6/src/bin/button.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::select::{select, Either}; 6use embassy_futures::select::{Either, select};
7use embassy_imxrt::gpio; 7use embassy_imxrt::gpio;
8use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _}; 8use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _};
9 9
diff --git a/examples/mimxrt6/src/bin/dma.rs b/examples/mimxrt6/src/bin/dma.rs
new file mode 100644
index 000000000..b490efc6b
--- /dev/null
+++ b/examples/mimxrt6/src/bin/dma.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::info;
7use embassy_executor::Spawner;
8use embassy_imxrt::dma::copy;
9use {defmt_rtt as _, panic_probe as _};
10
11const BUFLEN: usize = 1024;
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_imxrt::init(Default::default());
16
17 info!("Test memory-to-memory DMA transfers");
18
19 let src = [0x55u8; BUFLEN];
20 let mut dst = [0u8; BUFLEN];
21
22 unsafe { copy(p.DMA0_CH0, &src, &mut dst) }.await;
23 assert!(dst == src);
24
25 info!("DMA copy succeeded");
26}
diff --git a/examples/mimxrt6/src/bin/spi-async.rs b/examples/mimxrt6/src/bin/spi-async.rs
new file mode 100644
index 000000000..aa56f7c42
--- /dev/null
+++ b/examples/mimxrt6/src/bin/spi-async.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_imxrt::bind_interrupts;
7use embassy_imxrt::flexcomm::spi::{InterruptHandler, Spi};
8use embassy_imxrt::peripherals::FLEXCOMM5;
9use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 FLEXCOMM5 => InterruptHandler<FLEXCOMM5>;
13});
14
15const BUFLEN: usize = 1024;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 let p = embassy_imxrt::init(Default::default());
20
21 info!("Initializing SPI");
22
23 let mut spi = Spi::new_async(p.FLEXCOMM5, p.PIO1_3, p.PIO1_5, p.PIO1_4, Irqs, Default::default());
24
25 let mut rxbuf = [0x55; BUFLEN];
26 let txbuf = [0xaa; BUFLEN];
27
28 for _ in 0..10 {
29 spi.async_transfer(&mut rxbuf, &txbuf).await.unwrap();
30 assert!(rxbuf.iter().all(|b| *b == 0xaa));
31 rxbuf.fill(0x55);
32 }
33
34 info!("SPI transfers succeeded");
35}
diff --git a/examples/mimxrt6/src/bin/spi.rs b/examples/mimxrt6/src/bin/spi.rs
new file mode 100644
index 000000000..4854432e8
--- /dev/null
+++ b/examples/mimxrt6/src/bin/spi.rs
@@ -0,0 +1,51 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_imxrt::flexcomm::spi::Spi;
7use embassy_imxrt::gpio;
8use embassy_time::{Delay, Timer};
9use embedded_hal_bus::spi::ExclusiveDevice;
10use is31fl3743b_driver::{CSy, Is31fl3743b, SWx};
11use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_imxrt::init(Default::default());
16
17 info!("Initializing SPI");
18
19 let cs = gpio::Output::new(
20 p.PIO1_6,
21 gpio::Level::Low,
22 gpio::DriveMode::PushPull,
23 gpio::DriveStrength::Normal,
24 gpio::SlewRate::Standard,
25 );
26
27 let spi = Spi::new_blocking(p.FLEXCOMM5, p.PIO1_3, p.PIO1_5, p.PIO1_4, Default::default());
28 let delay = Delay;
29
30 // One SPI device only on the SPI bus
31 let spi_dev = ExclusiveDevice::new(spi, cs, delay).unwrap();
32
33 // Instantiate IS31FL3743B device
34 let mut driver = Is31fl3743b::new(spi_dev).unwrap();
35
36 // Enable phase delay to help reduce power noise
37 let _ = driver.enable_phase_delay();
38 // Set global current, check method documentation for more info
39 let _ = driver.set_global_current(90);
40
41 let _ = driver.set_led_peak_current_bulk(SWx::SW1, CSy::CS1, &[100; 11 * 18]);
42
43 // Driver is fully set up, we can now start turning on LEDs!
44 // Create a white breathing effect
45 loop {
46 for brightness in (0..=255_u8).chain((0..=255).rev()) {
47 let _ = driver.set_led_brightness_bulk(SWx::SW1, CSy::CS1, &[brightness; 11 * 18]);
48 Timer::after_micros(1).await;
49 }
50 }
51}
diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml
index 21434106a..74301bc9c 100644
--- a/examples/mspm0c1104/Cargo.toml
+++ b/examples/mspm0c1104/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-mspm0-c1104-examples" 3name = "embassy-mspm0-c1104-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/mspm0c1104/src/bin/blinky.rs b/examples/mspm0c1104/src/bin/blinky.rs
index 0d974cc5e..345077b37 100644
--- a/examples/mspm0c1104/src/bin/blinky.rs
+++ b/examples/mspm0c1104/src/bin/blinky.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Level, Output};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0c1104/src/bin/button.rs b/examples/mspm0c1104/src/bin/button.rs
index 7face1618..557d997cd 100644
--- a/examples/mspm0c1104/src/bin/button.rs
+++ b/examples/mspm0c1104/src/bin/button.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Input, Level, Output, Pull};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _}; 8use {defmt_rtt as _, panic_halt as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml
index 616b82adb..8c230f038 100644
--- a/examples/mspm0g3507/Cargo.toml
+++ b/examples/mspm0g3507/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-mspm0-g3507-examples" 3name = "embassy-mspm0-g3507-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/mspm0g3507/src/bin/adc.rs b/examples/mspm0g3507/src/bin/adc.rs
index ceccc7c02..cf1abb471 100644
--- a/examples/mspm0g3507/src/bin/adc.rs
+++ b/examples/mspm0g3507/src/bin/adc.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::adc::{self, Adc, Vrsel}; 6use embassy_mspm0::adc::{self, Adc, Vrsel};
7use embassy_mspm0::{bind_interrupts, peripherals, Config}; 7use embassy_mspm0::{Config, bind_interrupts, peripherals};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0g3507/src/bin/blinky.rs b/examples/mspm0g3507/src/bin/blinky.rs
index 055a5cd81..47eaf1535 100644
--- a/examples/mspm0g3507/src/bin/blinky.rs
+++ b/examples/mspm0g3507/src/bin/blinky.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Level, Output};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0g3507/src/bin/button.rs b/examples/mspm0g3507/src/bin/button.rs
index cde1f2892..76f3a1aba 100644
--- a/examples/mspm0g3507/src/bin/button.rs
+++ b/examples/mspm0g3507/src/bin/button.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Input, Level, Output, Pull};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _}; 8use {defmt_rtt as _, panic_halt as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
diff --git a/examples/mspm0g3507/src/bin/i2c_target.rs b/examples/mspm0g3507/src/bin/i2c_target.rs
new file mode 100644
index 000000000..5dd718eaf
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/i2c_target.rs
@@ -0,0 +1,63 @@
1//! Example of using async I2C target
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0G3507 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::i2c::Config;
11use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus};
12use embassy_mspm0::peripherals::I2C1;
13use embassy_mspm0::{bind_interrupts, i2c};
14use {defmt_rtt as _, panic_halt as _};
15
16bind_interrupts!(struct Irqs {
17 I2C1 => i2c::InterruptHandler<I2C1>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let p = embassy_mspm0::init(Default::default());
23
24 let instance = p.I2C1;
25 let scl = p.PB2;
26 let sda = p.PB3;
27
28 let config = Config::default();
29 let mut target_config = TargetConfig::default();
30 target_config.target_addr = 0x48;
31 target_config.general_call = true;
32 let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap();
33
34 let mut read = [0u8; 8];
35 let data = [8u8; 2];
36 let data_wr = [9u8; 2];
37
38 loop {
39 match i2c.listen(&mut read).await {
40 Ok(Command::GeneralCall(_)) => info!("General call received"),
41 Ok(Command::Read) => {
42 info!("Read command received");
43 match i2c.respond_to_read(&data).await.unwrap() {
44 ReadStatus::Done => info!("Finished reading"),
45 ReadStatus::NeedMoreBytes => {
46 info!("Read needs more bytes - will reset");
47 i2c.reset().unwrap();
48 }
49 ReadStatus::LeftoverBytes(_) => {
50 info!("Leftover bytes received");
51 i2c.flush_tx_fifo();
52 }
53 }
54 }
55 Ok(Command::Write(_)) => info!("Write command received"),
56 Ok(Command::WriteRead(_)) => {
57 info!("Write-Read command received");
58 i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap();
59 }
60 Err(e) => info!("Got error {}", e),
61 }
62 }
63}
diff --git a/examples/mspm0g3507/src/bin/mathacl_ops.rs b/examples/mspm0g3507/src/bin/mathacl_ops.rs
new file mode 100644
index 000000000..25d74b29b
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/mathacl_ops.rs
@@ -0,0 +1,39 @@
1//! Example of using mathematical calculations performed by the MSPM0G3507 chip.
2//!
3//! It prints the result of basics trigonometric calculation.
4
5#![no_std]
6#![no_main]
7
8use core::f32::consts::PI;
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_mspm0::mathacl::{Mathacl, Precision};
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_halt as _};
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) -> ! {
18 info!("Hello world!");
19
20 let d = embassy_mspm0::init(Default::default());
21
22 let mut macl = Mathacl::new(d.MATHACL);
23
24 // value radians [-PI; PI]
25 let rads = PI * 0.5;
26 match macl.sin(rads, Precision::High) {
27 Ok(res) => info!("sin({}) = {}", rads, res),
28 Err(e) => error!("sin Error: {:?}", e),
29 }
30
31 match macl.cos(rads, Precision::Medium) {
32 Ok(res) => info!("cos({}) = {}", rads, res),
33 Err(e) => error!("cos Error: {:?}", e),
34 }
35
36 loop {
37 Timer::after_millis(500).await;
38 }
39}
diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml
index ae699d6f4..0f5e58343 100644
--- a/examples/mspm0g3519/Cargo.toml
+++ b/examples/mspm0g3519/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-mspm0-g3519-examples" 3name = "embassy-mspm0-g3519-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/mspm0g3519/src/bin/blinky.rs b/examples/mspm0g3519/src/bin/blinky.rs
index 055a5cd81..47eaf1535 100644
--- a/examples/mspm0g3519/src/bin/blinky.rs
+++ b/examples/mspm0g3519/src/bin/blinky.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Level, Output};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0g3519/src/bin/button.rs b/examples/mspm0g3519/src/bin/button.rs
index c81cc2918..21e7873d8 100644
--- a/examples/mspm0g3519/src/bin/button.rs
+++ b/examples/mspm0g3519/src/bin/button.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Input, Level, Output, Pull};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _}; 8use {defmt_rtt as _, panic_halt as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
diff --git a/examples/mspm0g5187/.cargo/config.toml b/examples/mspm0g5187/.cargo/config.toml
new file mode 100644
index 000000000..ea407b411
--- /dev/null
+++ b/examples/mspm0g5187/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace MSPM0G5187 with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --restore-unwritten --verify --chip MSPM0G5187 --protocol=swd"
4
5[build]
6target = "thumbv6m-none-eabi"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/mspm0g5187/Cargo.toml b/examples/mspm0g5187/Cargo.toml
new file mode 100644
index 000000000..3d64a127a
--- /dev/null
+++ b/examples/mspm0g5187/Cargo.toml
@@ -0,0 +1,27 @@
1[package]
2edition = "2024"
3name = "embassy-mspm0-g5187-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g5187pm", "defmt", "rt", "time-driver-any"] }
10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
13panic-halt = "1.0.0"
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15cortex-m-rt = { version = "0.7.0"}
16defmt = "1.0.1"
17defmt-rtt = "1.0.0"
18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
19panic-semihosting = "0.6.0"
20
21[profile.release]
22debug = 2
23
24[package.metadata.embassy]
25build = [
26 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g5187" }
27]
diff --git a/examples/mspm0g5187/README.md b/examples/mspm0g5187/README.md
new file mode 100644
index 000000000..12e7846fb
--- /dev/null
+++ b/examples/mspm0g5187/README.md
@@ -0,0 +1,27 @@
1# Examples for MSPM0G5187
2
3Run individual examples with
4```
5cargo run --bin <module-name>
6```
7for example
8```
9cargo run --bin blinky
10```
11
12## Checklist before running examples
13A large number of the examples are written for the [LP-MSPM0G5187](https://www.ti.com/tool/LP-MSPM0G5187) board.
14
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G5187 it should be `probe-rs run --chip MSPM0G5187`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3519 it should be `mspm0g3519pz`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21
22If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
23
24* Which example you are trying to run
25* Which chip and board you are using
26
27Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
diff --git a/examples/mspm0g5187/build.rs b/examples/mspm0g5187/build.rs
new file mode 100644
index 000000000..2d777c2d3
--- /dev/null
+++ b/examples/mspm0g5187/build.rs
@@ -0,0 +1,37 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
37}
diff --git a/examples/mspm0g5187/memory.x b/examples/mspm0g5187/memory.x
new file mode 100644
index 000000000..37e381fbd
--- /dev/null
+++ b/examples/mspm0g5187/memory.x
@@ -0,0 +1,6 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 128K
4 /* Select non-parity range of SRAM due to SRAM_ERR_01 errata in SLAZ758 */
5 RAM : ORIGIN = 0x20200000, LENGTH = 32K
6}
diff --git a/examples/mspm0g5187/src/bin/blinky.rs b/examples/mspm0g5187/src/bin/blinky.rs
new file mode 100644
index 000000000..47eaf1535
--- /dev/null
+++ b/examples/mspm0g5187/src/bin/blinky.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) -> ! {
13 info!("Hello world!");
14 let p = embassy_mspm0::init(Config::default());
15
16 let mut led1 = Output::new(p.PA0, Level::Low);
17 led1.set_inversion(true);
18
19 loop {
20 Timer::after_millis(400).await;
21
22 info!("Toggle");
23 led1.toggle();
24 }
25}
diff --git a/examples/mspm0g5187/src/bin/button.rs b/examples/mspm0g5187/src/bin/button.rs
new file mode 100644
index 000000000..2ed15e354
--- /dev/null
+++ b/examples/mspm0g5187/src/bin/button.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) -> ! {
12 info!("Hello world!");
13
14 let p = embassy_mspm0::init(Config::default());
15
16 let led1 = p.PA0;
17 let s2 = p.PA7;
18
19 let mut led1 = Output::new(led1, Level::Low);
20
21 let mut s2 = Input::new(s2, Pull::Up);
22
23 // led1 is active low
24 led1.set_high();
25
26 loop {
27 s2.wait_for_falling_edge().await;
28
29 info!("Switch 2 was pressed");
30
31 led1.toggle();
32 }
33}
diff --git a/examples/mspm0g5187/src/bin/wwdt.rs b/examples/mspm0g5187/src/bin/wwdt.rs
new file mode 100644
index 000000000..a5de781f3
--- /dev/null
+++ b/examples/mspm0g5187/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0G5187 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml
index 8100e11da..d5b5e9d3e 100644
--- a/examples/mspm0l1306/Cargo.toml
+++ b/examples/mspm0l1306/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-mspm0-l1306-examples" 3name = "embassy-mspm0-l1306-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/mspm0l1306/src/bin/adc.rs b/examples/mspm0l1306/src/bin/adc.rs
index 2806b98cc..235396b8a 100644
--- a/examples/mspm0l1306/src/bin/adc.rs
+++ b/examples/mspm0l1306/src/bin/adc.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::adc::{self, Adc, Vrsel}; 6use embassy_mspm0::adc::{self, Adc, Vrsel};
7use embassy_mspm0::{bind_interrupts, peripherals, Config}; 7use embassy_mspm0::{Config, bind_interrupts, peripherals};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0l1306/src/bin/blinky.rs b/examples/mspm0l1306/src/bin/blinky.rs
index 055a5cd81..47eaf1535 100644
--- a/examples/mspm0l1306/src/bin/blinky.rs
+++ b/examples/mspm0l1306/src/bin/blinky.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Level, Output};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0l1306/src/bin/button.rs b/examples/mspm0l1306/src/bin/button.rs
index d8c85947f..33e682272 100644
--- a/examples/mspm0l1306/src/bin/button.rs
+++ b/examples/mspm0l1306/src/bin/button.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Input, Level, Output, Pull};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _}; 8use {defmt_rtt as _, panic_halt as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
diff --git a/examples/mspm0l1306/src/bin/i2c_target.rs b/examples/mspm0l1306/src/bin/i2c_target.rs
new file mode 100644
index 000000000..4d147d08b
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c_target.rs
@@ -0,0 +1,63 @@
1//! Example of using async I2C target
2//!
3//! This uses the virtual COM port provided on the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::i2c::Config;
11use embassy_mspm0::i2c_target::{Command, Config as TargetConfig, I2cTarget, ReadStatus};
12use embassy_mspm0::peripherals::I2C0;
13use embassy_mspm0::{bind_interrupts, i2c};
14use {defmt_rtt as _, panic_halt as _};
15
16bind_interrupts!(struct Irqs {
17 I2C0 => i2c::InterruptHandler<I2C0>;
18});
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) -> ! {
22 let p = embassy_mspm0::init(Default::default());
23
24 let instance = p.I2C0;
25 let scl = p.PA1;
26 let sda = p.PA0;
27
28 let config = Config::default();
29 let mut target_config = TargetConfig::default();
30 target_config.target_addr = 0x48;
31 target_config.general_call = true;
32 let mut i2c = I2cTarget::new(instance, scl, sda, Irqs, config, target_config).unwrap();
33
34 let mut read = [0u8; 8];
35 let data = [8u8; 2];
36 let data_wr = [9u8; 2];
37
38 loop {
39 match i2c.listen(&mut read).await {
40 Ok(Command::GeneralCall(_)) => info!("General call received"),
41 Ok(Command::Read) => {
42 info!("Read command received");
43 match i2c.respond_to_read(&data).await.unwrap() {
44 ReadStatus::Done => info!("Finished reading"),
45 ReadStatus::NeedMoreBytes => {
46 info!("Read needs more bytes - will reset");
47 i2c.reset().unwrap();
48 }
49 ReadStatus::LeftoverBytes(_) => {
50 info!("Leftover bytes received");
51 i2c.flush_tx_fifo();
52 }
53 }
54 }
55 Ok(Command::Write(_)) => info!("Write command received"),
56 Ok(Command::WriteRead(_)) => {
57 info!("Write-Read command received");
58 i2c.respond_and_fill(&data_wr, 0xFE).await.unwrap();
59 }
60 Err(e) => info!("Got error {}", e),
61 }
62 }
63}
diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml
index 3add7b8e8..1d27ae64a 100644
--- a/examples/mspm0l2228/Cargo.toml
+++ b/examples/mspm0l2228/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-mspm0-l2228-examples" 3name = "embassy-mspm0-l2228-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/mspm0l2228/src/bin/blinky.rs b/examples/mspm0l2228/src/bin/blinky.rs
index 055a5cd81..47eaf1535 100644
--- a/examples/mspm0l2228/src/bin/blinky.rs
+++ b/examples/mspm0l2228/src/bin/blinky.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Level, Output};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Level, Output};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_halt as _}; 9use {defmt_rtt as _, panic_halt as _};
10 10
diff --git a/examples/mspm0l2228/src/bin/button.rs b/examples/mspm0l2228/src/bin/button.rs
index 47bfd274b..bad1cb138 100644
--- a/examples/mspm0l2228/src/bin/button.rs
+++ b/examples/mspm0l2228/src/bin/button.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_mspm0::gpio::{Input, Level, Output, Pull};
7use embassy_mspm0::Config; 6use embassy_mspm0::Config;
7use embassy_mspm0::gpio::{Input, Level, Output, Pull};
8use {defmt_rtt as _, panic_halt as _}; 8use {defmt_rtt as _, panic_halt as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
index d2d0ae093..3d6b5e60a 100644
--- a/examples/nrf-rtos-trace/Cargo.toml
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf-rtos-trace-examples" 3name = "embassy-nrf-rtos-trace-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -19,7 +19,7 @@ log = [
19embassy-sync = { version = "0.7.2", path = "../../embassy-sync" } 19embassy-sync = { version = "0.7.2", path = "../../embassy-sync" }
20embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } 20embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] }
21embassy-time = { version = "0.5.0", path = "../../embassy-time" } 21embassy-time = { version = "0.5.0", path = "../../embassy-time" }
22embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 22embassy-nrf = { version = "0.9.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"] }
25cortex-m-rt = "0.7.0" 25cortex-m-rt = "0.7.0"
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml
index 082d85e5b..e8375952b 100644
--- a/examples/nrf51/Cargo.toml
+++ b/examples/nrf51/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf51-examples" 3name = "embassy-nrf51-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } 11embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] }
12 12
13defmt = "1.0.1" 13defmt = "1.0.1"
14defmt-rtt = "1.0.0" 14defmt-rtt = "1.0.0"
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml
index 7835320e5..73d129f91 100644
--- a/examples/nrf52810/Cargo.toml
+++ b/examples/nrf52810/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf52810-examples" 3name = "embassy-nrf52810-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
14 14
15defmt = "1.0.1" 15defmt = "1.0.1"
16defmt-rtt = "1.0.0" 16defmt-rtt = "1.0.0"
diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml
index 67a624d6d..8066a1150 100644
--- a/examples/nrf52840-edf/Cargo.toml
+++ b/examples/nrf52840-edf/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf52840-edf-examples" 3name = "embassy-nrf52840-edf-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -9,7 +9,7 @@ publish = false
9# NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled 9# NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled
10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] }
11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 12embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
13 13
14defmt = "1.0.1" 14defmt = "1.0.1"
15defmt-rtt = "1.0.0" 15defmt-rtt = "1.0.0"
diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs
index d888e17d1..f7214790d 100644
--- a/examples/nrf52840-edf/src/bin/basic.rs
+++ b/examples/nrf52840-edf/src/bin/basic.rs
@@ -12,7 +12,7 @@
12#![no_std] 12#![no_std]
13#![no_main] 13#![no_main]
14 14
15use core::sync::atomic::{compiler_fence, Ordering}; 15use core::sync::atomic::{Ordering, compiler_fence};
16 16
17use defmt::unwrap; 17use defmt::unwrap;
18use embassy_executor::Spawner; 18use embassy_executor::Spawner;
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml
index d860626a1..13a7724fa 100644
--- a/examples/nrf52840-rtic/Cargo.toml
+++ b/examples/nrf52840-rtic/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf52840-rtic-examples" 3name = "embassy-nrf52840-rtic-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -12,7 +12,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] }
14embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } 14embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] }
15embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 15embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
16 16
17defmt = "1.0.1" 17defmt = "1.0.1"
18defmt-rtt = "1.0.0" 18defmt-rtt = "1.0.0"
diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs
index 2adac7e0a..671082117 100644
--- a/examples/nrf52840-rtic/src/bin/blinky.rs
+++ b/examples/nrf52840-rtic/src/bin/blinky.rs
@@ -7,7 +7,7 @@ use {defmt_rtt as _, panic_probe as _};
7mod app { 7mod app {
8 use defmt::info; 8 use defmt::info;
9 use embassy_nrf::gpio::{Level, Output, OutputDrive}; 9 use embassy_nrf::gpio::{Level, Output, OutputDrive};
10 use embassy_nrf::{peripherals, Peri}; 10 use embassy_nrf::{Peri, peripherals};
11 use embassy_time::Timer; 11 use embassy_time::Timer;
12 12
13 #[shared] 13 #[shared]
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 5b3e176c0..a57bd7b24 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf52840-examples" 3name = "embassy-nrf52840-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embedded-io = { version = "0.6.0", features = ["defmt-03"] } 16embedded-io = { version = "0.6.0", features = ["defmt-03"] }
@@ -28,7 +28,7 @@ cortex-m-rt = "0.7.0"
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29rand = { version = "0.9.0", default-features = false } 29rand = { version = "0.9.0", default-features = false }
30embedded-storage = "0.3.1" 30embedded-storage = "0.3.1"
31usbd-hid = "0.8.1" 31usbd-hid = "0.9.0"
32serde = { version = "1.0.136", default-features = false } 32serde = { version = "1.0.136", default-features = false }
33embedded-hal = { version = "1.0" } 33embedded-hal = { version = "1.0" }
34embedded-hal-async = { version = "1.0" } 34embedded-hal-async = { version = "1.0" }
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs
index 09050db68..de694eaa0 100644
--- a/examples/nrf52840/src/bin/channel_sender_receiver.rs
+++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::unwrap; 4use defmt::unwrap;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
7use embassy_nrf::Peri; 6use embassy_nrf::Peri;
7use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
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::Timer; 10use embassy_time::Timer;
diff --git a/examples/nrf52840/src/bin/egu.rs b/examples/nrf52840/src/bin/egu.rs
index 8bf712697..36eba8084 100644
--- a/examples/nrf52840/src/bin/egu.rs
+++ b/examples/nrf52840/src/bin/egu.rs
@@ -6,7 +6,7 @@
6 6
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::egu::{Egu, TriggerNumber}; 8use embassy_nrf::egu::{Egu, TriggerNumber};
9use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 9use embassy_nrf::gpio::{Level, OutputDrive, Pull};
10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity}; 10use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity};
11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2}; 11use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2};
12use embassy_nrf::ppi::Ppi; 12use embassy_nrf::ppi::Ppi;
@@ -17,12 +17,15 @@ use {defmt_rtt as _, panic_probe as _};
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
19 19
20 let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard);
21 let btn1 = Input::new(p.P0_11, Pull::Up);
22
23 let mut egu1 = Egu::new(p.EGU0); 20 let mut egu1 = Egu::new(p.EGU0);
24 let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle); 21 let led1 = OutputChannel::new(
25 let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi); 22 p.GPIOTE_CH0,
23 p.P0_13,
24 Level::High,
25 OutputDrive::Standard,
26 OutputChannelPolarity::Toggle,
27 );
28 let btn1 = InputChannel::new(p.GPIOTE_CH1, p.P0_11, Pull::Up, InputChannelPolarity::LoToHi);
26 29
27 let trigger0 = egu1.trigger(TriggerNumber::Trigger0); 30 let trigger0 = egu1.trigger(TriggerNumber::Trigger0);
28 let trigger1 = egu1.trigger(TriggerNumber::Trigger1); 31 let trigger1 = egu1.trigger(TriggerNumber::Trigger1);
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
index e59afd37f..5a988d89b 100644
--- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs
+++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket;
7use embassy_net::StackResources; 6use embassy_net::StackResources;
7use embassy_net::tcp::TcpSocket;
8use embassy_net_enc28j60::Enc28j60; 8use embassy_net_enc28j60::Enc28j60;
9use embassy_nrf::gpio::{Level, Output, OutputDrive}; 9use embassy_nrf::gpio::{Level, Output, OutputDrive};
10use embassy_nrf::rng::Rng; 10use embassy_nrf::rng::Rng;
diff --git a/examples/nrf52840/src/bin/gpiote_channel.rs b/examples/nrf52840/src/bin/gpiote_channel.rs
index dcfe7723a..e358779b2 100644
--- a/examples/nrf52840/src/bin/gpiote_channel.rs
+++ b/examples/nrf52840/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!"); 13 info!("Starting!");
14 14
15 let ch1 = InputChannel::new( 15 let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_11, Pull::Up), 17 let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_12, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_24, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_25, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf52840/src/bin/i2s_effect.rs b/examples/nrf52840/src/bin/i2s_effect.rs
index 9eadeb4e4..c31b78614 100644
--- a/examples/nrf52840/src/bin/i2s_effect.rs
+++ b/examples/nrf52840/src/bin/i2s_effect.rs
@@ -5,7 +5,7 @@ use core::f32::consts::PI;
5 5
6use defmt::{error, info}; 6use defmt::{error, info};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; 8use embassy_nrf::i2s::{self, Channels, Config, I2S, MasterClock, MultiBuffering, Sample as _, SampleWidth};
9use embassy_nrf::{bind_interrupts, peripherals}; 9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -102,11 +102,7 @@ impl SineOsc {
102 102
103#[inline] 103#[inline]
104fn abs(value: f32) -> f32 { 104fn abs(value: f32) -> f32 {
105 if value < 0.0 { 105 if value < 0.0 { -value } else { value }
106 -value
107 } else {
108 value
109 }
110} 106}
111 107
112#[inline] 108#[inline]
diff --git a/examples/nrf52840/src/bin/i2s_monitor.rs b/examples/nrf52840/src/bin/i2s_monitor.rs
index 799be351f..a54659101 100644
--- a/examples/nrf52840/src/bin/i2s_monitor.rs
+++ b/examples/nrf52840/src/bin/i2s_monitor.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::{debug, error, info}; 4use defmt::{debug, error, info};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; 6use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth};
7use embassy_nrf::pwm::{Prescaler, SimplePwm}; 7use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
8use embassy_nrf::{bind_interrupts, peripherals}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) {
34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); 34 I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
35 35
36 // Configure the PWM to use the pins corresponding to the RGB leds 36 // Configure the PWM to use the pins corresponding to the RGB leds
37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); 37 let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24, &Default::default());
38 pwm.set_prescaler(Prescaler::Div1); 38 pwm.set_prescaler(Prescaler::Div1);
39 pwm.set_max_duty(255); 39 pwm.set_max_duty(255);
40 40
@@ -47,9 +47,8 @@ async fn main(_spawner: Spawner) {
47 let rgb = rgb_from_rms(rms); 47 let rgb = rgb_from_rms(rms);
48 48
49 debug!("RMS: {}, RGB: {:?}", rms, rgb); 49 debug!("RMS: {}, RGB: {:?}", rms, rgb);
50 for i in 0..3 { 50 let duties = rgb.map(|byte| DutyCycle::normal(u16::from(byte)));
51 pwm.set_duty(i, rgb[i].into()); 51 pwm.set_all_duties([duties[0], duties[1], duties[2], DutyCycle::normal(0)]);
52 }
53 52
54 if let Err(err) = input_stream.receive().await { 53 if let Err(err) = input_stream.receive().await {
55 error!("{}", err); 54 error!("{}", err);
diff --git a/examples/nrf52840/src/bin/i2s_waveform.rs b/examples/nrf52840/src/bin/i2s_waveform.rs
index 137d82840..ce7a68d3a 100644
--- a/examples/nrf52840/src/bin/i2s_waveform.rs
+++ b/examples/nrf52840/src/bin/i2s_waveform.rs
@@ -5,7 +5,7 @@ use core::f32::consts::PI;
5 5
6use defmt::{error, info}; 6use defmt::{error, info};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; 8use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, I2S, MasterClock, Sample as _, SampleWidth};
9use embassy_nrf::{bind_interrupts, peripherals}; 9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -140,11 +140,7 @@ impl SineOsc {
140 140
141#[inline] 141#[inline]
142fn abs(value: f32) -> f32 { 142fn abs(value: f32) -> f32 {
143 if value < 0.0 { 143 if value < 0.0 { -value } else { value }
144 -value
145 } else {
146 value
147 }
148} 144}
149 145
150#[inline] 146#[inline]
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs
index 4d9b986d4..dc566adee 100644
--- a/examples/nrf52840/src/bin/multiprio.rs
+++ b/examples/nrf52840/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn EGU1_SWI1() { 115unsafe fn EGU1_SWI1() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn EGU0_SWI0() { 120unsafe fn EGU0_SWI0() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/nrf52840/src/bin/ppi.rs b/examples/nrf52840/src/bin/ppi.rs
index 129ad06e7..177f6a06d 100644
--- a/examples/nrf52840/src/bin/ppi.rs
+++ b/examples/nrf52840/src/bin/ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::info; 6use defmt::info;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 8use embassy_nrf::gpio::{Level, OutputDrive, Pull};
9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use gpiote::{OutputChannel, OutputChannelPolarity}; 11use gpiote::{OutputChannel, OutputChannelPolarity};
@@ -16,36 +16,24 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_nrf::init(Default::default()); 16 let p = embassy_nrf::init(Default::default());
17 info!("Starting!"); 17 info!("Starting!");
18 18
19 let button1 = InputChannel::new( 19 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
20 p.GPIOTE_CH0, 20 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
21 Input::new(p.P0_11, Pull::Up), 21 let button3 = InputChannel::new(p.GPIOTE_CH2, p.P0_24, Pull::Up, InputChannelPolarity::HiToLo);
22 InputChannelPolarity::HiToLo, 22 let button4 = InputChannel::new(p.GPIOTE_CH3, p.P0_25, Pull::Up, InputChannelPolarity::HiToLo);
23 );
24 let button2 = InputChannel::new(
25 p.GPIOTE_CH1,
26 Input::new(p.P0_12, Pull::Up),
27 InputChannelPolarity::HiToLo,
28 );
29 let button3 = InputChannel::new(
30 p.GPIOTE_CH2,
31 Input::new(p.P0_24, Pull::Up),
32 InputChannelPolarity::HiToLo,
33 );
34 let button4 = InputChannel::new(
35 p.GPIOTE_CH3,
36 Input::new(p.P0_25, Pull::Up),
37 InputChannelPolarity::HiToLo,
38 );
39 23
40 let led1 = OutputChannel::new( 24 let led1 = OutputChannel::new(
41 p.GPIOTE_CH4, 25 p.GPIOTE_CH4,
42 Output::new(p.P0_13, Level::Low, OutputDrive::Standard), 26 p.P0_13,
27 Level::Low,
28 OutputDrive::Standard,
43 OutputChannelPolarity::Toggle, 29 OutputChannelPolarity::Toggle,
44 ); 30 );
45 31
46 let led2 = OutputChannel::new( 32 let led2 = OutputChannel::new(
47 p.GPIOTE_CH5, 33 p.GPIOTE_CH5,
48 Output::new(p.P0_14, Level::Low, OutputDrive::Standard), 34 p.P0_14,
35 Level::Low,
36 OutputDrive::Standard,
49 OutputChannelPolarity::Toggle, 37 OutputChannelPolarity::Toggle,
50 ); 38 );
51 39
diff --git a/examples/nrf52840/src/bin/pwm.rs b/examples/nrf52840/src/bin/pwm.rs
index a5bb1347a..02f9b4191 100644
--- a/examples/nrf52840/src/bin/pwm.rs
+++ b/examples/nrf52840/src/bin/pwm.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -71,7 +71,7 @@ static DUTY: [u16; 1024] = [
71#[embassy_executor::main] 71#[embassy_executor::main]
72async fn main(_spawner: Spawner) { 72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default()); 73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); 74 let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1); 75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767); 76 pwm.set_max_duty(32767);
77 info!("pwm initialized!"); 77 info!("pwm initialized!");
@@ -79,10 +79,12 @@ async fn main(_spawner: Spawner) {
79 let mut i = 0; 79 let mut i = 0;
80 loop { 80 loop {
81 i += 1; 81 i += 1;
82 pwm.set_duty(0, DUTY[i % 1024]); 82 pwm.set_all_duties([
83 pwm.set_duty(1, DUTY[(i + 256) % 1024]); 83 DutyCycle::normal(DUTY[i % 1024]),
84 pwm.set_duty(2, DUTY[(i + 512) % 1024]); 84 DutyCycle::normal(DUTY[(i + 256) % 1024]),
85 pwm.set_duty(3, DUTY[(i + 768) % 1024]); 85 DutyCycle::normal(DUTY[(i + 512) % 1024]),
86 DutyCycle::normal(DUTY[(i + 768) % 1024]),
87 ]);
86 Timer::after_millis(3).await; 88 Timer::after_millis(3).await;
87 } 89 }
88} 90}
diff --git a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
index 60ea712b5..fff7decb2 100644
--- a/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf52840/src/bin/pwm_sequence_ppi.rs
@@ -5,7 +5,7 @@ use core::future::pending;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_nrf::gpio::{Input, Pull}; 8use embassy_nrf::gpio::Pull;
9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 9use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
10use embassy_nrf::ppi::Ppi; 10use embassy_nrf::ppi::Ppi;
11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer}; 11use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer};
@@ -30,17 +30,9 @@ async fn main(_spawner: Spawner) {
30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 30 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
31 // so its going to have to start running in order load the configuration 31 // so its going to have to start running in order load the configuration
32 32
33 let button1 = InputChannel::new( 33 let button1 = InputChannel::new(p.GPIOTE_CH0, p.P0_11, Pull::Up, InputChannelPolarity::HiToLo);
34 p.GPIOTE_CH0,
35 Input::new(p.P0_11, Pull::Up),
36 InputChannelPolarity::HiToLo,
37 );
38 34
39 let button2 = InputChannel::new( 35 let button2 = InputChannel::new(p.GPIOTE_CH1, p.P0_12, Pull::Up, InputChannelPolarity::HiToLo);
40 p.GPIOTE_CH1,
41 Input::new(p.P0_12, Pull::Up),
42 InputChannelPolarity::HiToLo,
43 );
44 36
45 // messing with the pwm tasks is ill advised 37 // messing with the pwm tasks is ill advised
46 // Times::Ininite and Times even are seq0, Times odd is seq1 38 // Times::Ininite and Times even are seq0, Times odd is seq1
diff --git a/examples/nrf52840/src/bin/pwm_servo.rs b/examples/nrf52840/src/bin/pwm_servo.rs
index d772d2f5d..93cb984e6 100644
--- a/examples/nrf52840/src/bin/pwm_servo.rs
+++ b/examples/nrf52840/src/bin/pwm_servo.rs
@@ -3,14 +3,14 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{Prescaler, SimplePwm}; 6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); 13 let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05, &Default::default());
14 // sg90 microervo requires 50hz or 20ms period 14 // sg90 microervo requires 50hz or 20ms period
15 // set_period can only set down to 125khz so we cant use it directly 15 // set_period can only set down to 125khz so we cant use it directly
16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top 16 // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top
@@ -24,23 +24,23 @@ async fn main(_spawner: Spawner) {
24 loop { 24 loop {
25 info!("45 deg"); 25 info!("45 deg");
26 // poor mans inverting, subtract our value from max_duty 26 // poor mans inverting, subtract our value from max_duty
27 pwm.set_duty(0, 2500 - 156); 27 pwm.set_duty(0, DutyCycle::normal(2500 - 156));
28 Timer::after_millis(5000).await; 28 Timer::after_millis(5000).await;
29 29
30 info!("90 deg"); 30 info!("90 deg");
31 pwm.set_duty(0, 2500 - 187); 31 pwm.set_duty(0, DutyCycle::normal(2500 - 187));
32 Timer::after_millis(5000).await; 32 Timer::after_millis(5000).await;
33 33
34 info!("135 deg"); 34 info!("135 deg");
35 pwm.set_duty(0, 2500 - 218); 35 pwm.set_duty(0, DutyCycle::normal(2500 - 218));
36 Timer::after_millis(5000).await; 36 Timer::after_millis(5000).await;
37 37
38 info!("180 deg"); 38 info!("180 deg");
39 pwm.set_duty(0, 2500 - 250); 39 pwm.set_duty(0, DutyCycle::normal(2500 - 250));
40 Timer::after_millis(5000).await; 40 Timer::after_millis(5000).await;
41 41
42 info!("0 deg"); 42 info!("0 deg");
43 pwm.set_duty(0, 2500 - 125); 43 pwm.set_duty(0, DutyCycle::normal(2500 - 125));
44 Timer::after_millis(5000).await; 44 Timer::after_millis(5000).await;
45 } 45 }
46} 46}
diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs
index b80954408..783be763d 100644
--- a/examples/nrf52840/src/bin/raw_spawn.rs
+++ b/examples/nrf52840/src/bin/raw_spawn.rs
@@ -5,8 +5,8 @@ use core::mem;
5 5
6use cortex_m_rt::entry; 6use cortex_m_rt::entry;
7use defmt::{info, unwrap}; 7use defmt::{info, unwrap};
8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 8use embassy_executor::Executor;
9use embassy_executor::raw::TaskStorage;
10use embassy_time::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 _};
@@ -48,5 +48,5 @@ fn main() -> ! {
48} 48}
49 49
50unsafe fn make_static<T>(t: &T) -> &'static T { 50unsafe fn make_static<T>(t: &T) -> &'static T {
51 mem::transmute(t) 51 unsafe { mem::transmute(t) }
52} 52}
diff --git a/examples/nrf52840/src/bin/rtc.rs b/examples/nrf52840/src/bin/rtc.rs
index 9d475df7f..56a0c25f4 100644
--- a/examples/nrf52840/src/bin/rtc.rs
+++ b/examples/nrf52840/src/bin/rtc.rs
@@ -7,8 +7,8 @@ use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_nrf::interrupt; 8use embassy_nrf::interrupt;
9use embassy_nrf::rtc::Rtc; 9use embassy_nrf::rtc::Rtc;
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
12use portable_atomic::AtomicU64; 12use portable_atomic::AtomicU64;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index a75b967b4..14a1004d7 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -3,11 +3,11 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket;
7use embassy_net::StackResources; 6use embassy_net::StackResources;
7use embassy_net::tcp::TcpSocket;
8use embassy_nrf::rng::Rng; 8use embassy_nrf::rng::Rng;
9use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
10use embassy_nrf::usb::Driver; 9use embassy_nrf::usb::Driver;
10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
11use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb}; 11use embassy_nrf::{bind_interrupts, pac, peripherals, rng, usb};
12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
index 5a9dc90a2..7b7303526 100644
--- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs
@@ -1,19 +1,21 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_futures::join::join; 8use embassy_futures::join::join;
9use embassy_futures::select::{select, Either}; 9use embassy_futures::select::{Either, select};
10use embassy_nrf::gpio::{Input, Pull}; 10use embassy_nrf::gpio::{Input, Pull};
11use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
12use embassy_nrf::usb::Driver; 11use embassy_nrf::usb::Driver;
12use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
13use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 13use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15use embassy_sync::signal::Signal; 15use embassy_sync::signal::Signal;
16use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 16use embassy_usb::class::hid::{
17 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
18};
17use embassy_usb::control::OutResponse; 19use embassy_usb::control::OutResponse;
18use embassy_usb::{Builder, Config, Handler}; 20use embassy_usb::{Builder, Config, Handler};
19use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 21use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
@@ -26,6 +28,8 @@ bind_interrupts!(struct Irqs {
26 28
27static SUSPENDED: AtomicBool = AtomicBool::new(false); 29static SUSPENDED: AtomicBool = AtomicBool::new(false);
28 30
31static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
32
29#[embassy_executor::main] 33#[embassy_executor::main]
30async fn main(_spawner: Spawner) { 34async fn main(_spawner: Spawner) {
31 let p = embassy_nrf::init(Default::default()); 35 let p = embassy_nrf::init(Default::default());
@@ -45,6 +49,10 @@ async fn main(_spawner: Spawner) {
45 config.max_power = 100; 49 config.max_power = 100;
46 config.max_packet_size_0 = 64; 50 config.max_packet_size_0 = 64;
47 config.supports_remote_wakeup = true; 51 config.supports_remote_wakeup = true;
52 config.composite_with_iads = false;
53 config.device_class = 0;
54 config.device_sub_class = 0;
55 config.device_protocol = 0;
48 56
49 // Create embassy-usb DeviceBuilder using the driver and config. 57 // Create embassy-usb DeviceBuilder using the driver and config.
50 // It needs some buffers for building the descriptors. 58 // It needs some buffers for building the descriptors.
@@ -74,6 +82,8 @@ async fn main(_spawner: Spawner) {
74 request_handler: None, 82 request_handler: None,
75 poll_ms: 60, 83 poll_ms: 60,
76 max_packet_size: 64, 84 max_packet_size: 64,
85 hid_subclass: HidSubclass::Boot,
86 hid_boot_protocol: HidBootProtocol::Keyboard,
77 }; 87 };
78 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); 88 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
79 89
@@ -106,6 +116,11 @@ async fn main(_spawner: Spawner) {
106 if SUSPENDED.load(Ordering::Acquire) { 116 if SUSPENDED.load(Ordering::Acquire) {
107 info!("Triggering remote wakeup"); 117 info!("Triggering remote wakeup");
108 remote_wakeup.signal(()); 118 remote_wakeup.signal(());
119 } else if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
120 match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
121 Ok(()) => {}
122 Err(e) => warn!("Failed to send boot report: {:?}", e),
123 };
109 } else { 124 } else {
110 let report = KeyboardReport { 125 let report = KeyboardReport {
111 keycodes: [4, 0, 0, 0, 0, 0], 126 keycodes: [4, 0, 0, 0, 0, 0],
@@ -121,16 +136,23 @@ async fn main(_spawner: Spawner) {
121 136
122 button.wait_for_high().await; 137 button.wait_for_high().await;
123 info!("RELEASED"); 138 info!("RELEASED");
124 let report = KeyboardReport { 139 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
125 keycodes: [0, 0, 0, 0, 0, 0], 140 match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
126 leds: 0, 141 Ok(()) => {}
127 modifier: 0, 142 Err(e) => warn!("Failed to send boot report: {:?}", e),
128 reserved: 0, 143 };
129 }; 144 } else {
130 match writer.write_serialize(&report).await { 145 let report = KeyboardReport {
131 Ok(()) => {} 146 keycodes: [0, 0, 0, 0, 0, 0],
132 Err(e) => warn!("Failed to send report: {:?}", e), 147 leds: 0,
133 }; 148 modifier: 0,
149 reserved: 0,
150 };
151 match writer.write_serialize(&report).await {
152 Ok(()) => {}
153 Err(e) => warn!("Failed to send report: {:?}", e),
154 };
155 }
134 } 156 }
135 }; 157 };
136 158
@@ -156,6 +178,18 @@ impl RequestHandler for MyRequestHandler {
156 OutResponse::Accepted 178 OutResponse::Accepted
157 } 179 }
158 180
181 fn get_protocol(&self) -> HidProtocolMode {
182 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
183 info!("The current HID protocol mode is: {}", protocol);
184 protocol
185 }
186
187 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
188 info!("Switching to HID protocol mode: {}", protocol);
189 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
190 OutResponse::Accepted
191 }
192
159 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 193 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
160 info!("Set idle rate for {:?} to {:?}", id, dur); 194 info!("Set idle rate for {:?} to {:?}", id, dur);
161 } 195 }
@@ -210,7 +244,9 @@ impl Handler for MyDeviceHandler {
210 244
211 fn suspended(&mut self, suspended: bool) { 245 fn suspended(&mut self, suspended: bool) {
212 if suspended { 246 if suspended {
213 info!("Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled)."); 247 info!(
248 "Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled)."
249 );
214 SUSPENDED.store(true, Ordering::Release); 250 SUSPENDED.store(true, Ordering::Release);
215 } else { 251 } else {
216 SUSPENDED.store(false, Ordering::Release); 252 SUSPENDED.store(false, Ordering::Release);
diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs
index 80cda70e3..6bee4546b 100644
--- a/examples/nrf52840/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs
@@ -1,14 +1,18 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
7use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
8use embassy_nrf::usb::Driver; 9use embassy_nrf::usb::Driver;
10use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
9use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 11use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
10use embassy_time::Timer; 12use embassy_time::Timer;
11use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
15};
12use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
13use embassy_usb::{Builder, Config}; 17use embassy_usb::{Builder, Config};
14use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 18use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
@@ -19,6 +23,8 @@ bind_interrupts!(struct Irqs {
19 CLOCK_POWER => usb::vbus_detect::InterruptHandler; 23 CLOCK_POWER => usb::vbus_detect::InterruptHandler;
20}); 24});
21 25
26static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
27
22#[embassy_executor::main] 28#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 29async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default()); 30 let p = embassy_nrf::init(Default::default());
@@ -37,6 +43,10 @@ async fn main(_spawner: Spawner) {
37 config.serial_number = Some("12345678"); 43 config.serial_number = Some("12345678");
38 config.max_power = 100; 44 config.max_power = 100;
39 config.max_packet_size_0 = 64; 45 config.max_packet_size_0 = 64;
46 config.composite_with_iads = false;
47 config.device_class = 0;
48 config.device_sub_class = 0;
49 config.device_protocol = 0;
40 50
41 // Create embassy-usb DeviceBuilder using the driver and config. 51 // Create embassy-usb DeviceBuilder using the driver and config.
42 // It needs some buffers for building the descriptors. 52 // It needs some buffers for building the descriptors.
@@ -63,6 +73,8 @@ async fn main(_spawner: Spawner) {
63 request_handler: Some(&mut request_handler), 73 request_handler: Some(&mut request_handler),
64 poll_ms: 60, 74 poll_ms: 60,
65 max_packet_size: 8, 75 max_packet_size: 8,
76 hid_subclass: HidSubclass::Boot,
77 hid_boot_protocol: HidBootProtocol::Mouse,
66 }; 78 };
67 79
68 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); 80 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config);
@@ -80,16 +92,26 @@ async fn main(_spawner: Spawner) {
80 Timer::after_millis(500).await; 92 Timer::after_millis(500).await;
81 93
82 y = -y; 94 y = -y;
83 let report = MouseReport { 95
84 buttons: 0, 96 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
85 x: 0, 97 let buttons = 0u8;
86 y, 98 let x = 0i8;
87 wheel: 0, 99 match writer.write(&[buttons, x as u8, y as u8]).await {
88 pan: 0, 100 Ok(()) => {}
89 }; 101 Err(e) => warn!("Failed to send boot report: {:?}", e),
90 match writer.write_serialize(&report).await { 102 }
91 Ok(()) => {} 103 } else {
92 Err(e) => warn!("Failed to send report: {:?}", e), 104 let report = MouseReport {
105 buttons: 0,
106 x: 0,
107 y,
108 wheel: 0,
109 pan: 0,
110 };
111 match writer.write_serialize(&report).await {
112 Ok(()) => {}
113 Err(e) => warn!("Failed to send report: {:?}", e),
114 }
93 } 115 }
94 } 116 }
95 }; 117 };
@@ -112,6 +134,18 @@ impl RequestHandler for MyRequestHandler {
112 OutResponse::Accepted 134 OutResponse::Accepted
113 } 135 }
114 136
137 fn get_protocol(&self) -> HidProtocolMode {
138 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
139 info!("The current HID protocol mode is: {}", protocol);
140 protocol
141 }
142
143 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
144 info!("Switching to HID protocol mode: {}", protocol);
145 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
146 OutResponse::Accepted
147 }
148
115 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 149 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
116 info!("Set idle rate for {:?} to {:?}", id, dur); 150 info!("Set idle rate for {:?} to {:?}", id, dur);
117 } 151 }
diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs
index e7c2d0854..469002bc7 100644
--- a/examples/nrf52840/src/bin/usb_serial.rs
+++ b/examples/nrf52840/src/bin/usb_serial.rs
@@ -4,8 +4,8 @@
4use defmt::{info, panic}; 4use defmt::{info, panic};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
8use embassy_nrf::usb::Driver; 7use embassy_nrf::usb::Driver;
8use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
9use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 9use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index b6a983854..67b2bccbb 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::{info, panic, unwrap}; 4use defmt::{info, panic, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
7use embassy_nrf::usb::Driver; 6use embassy_nrf::usb::Driver;
7use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
8use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 8use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 10use embassy_usb::driver::EndpointError;
diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs
index e30e08a01..cd4d5bca1 100644
--- a/examples/nrf52840/src/bin/usb_serial_winusb.rs
+++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs
@@ -4,8 +4,8 @@
4use defmt::{info, panic}; 4use defmt::{info, panic};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
8use embassy_nrf::usb::Driver; 7use embassy_nrf::usb::Driver;
8use embassy_nrf::usb::vbus_detect::{HardwareVbusDetect, VbusDetect};
9use embassy_nrf::{bind_interrupts, pac, peripherals, usb}; 9use embassy_nrf::{bind_interrupts, pac, peripherals, usb};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
index 1bc35746a..2f9c06b56 100644
--- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs
+++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::{info, unwrap, warn}; 4use defmt::{info, unwrap, warn};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket;
7use embassy_net::StackResources; 6use embassy_net::StackResources;
7use embassy_net::tcp::TcpSocket;
8use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; 8use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
9use embassy_nrf::rng::Rng; 9use embassy_nrf::rng::Rng;
10use embassy_nrf::spim::{self, Spim}; 10use embassy_nrf::spim::{self, Spim};
@@ -27,14 +27,12 @@ bind_interrupts!(struct Irqs {
27async fn wifi_task( 27async fn wifi_task(
28 runner: hosted::Runner< 28 runner: hosted::Runner<
29 'static, 29 'static,
30 ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, 30 hosted::SpiInterface<ExclusiveDevice<Spim<'static>, Output<'static>, Delay>, Input<'static>>,
31 Input<'static>,
32 Output<'static>, 31 Output<'static>,
33 >, 32 >,
34) -> ! { 33) -> ! {
35 runner.run().await 34 runner.run().await
36} 35}
37
38#[embassy_executor::task] 36#[embassy_executor::task]
39async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! { 37async fn net_task(mut runner: embassy_net::Runner<'static, hosted::NetDriver<'static>>) -> ! {
40 runner.run().await 38 runner.run().await
@@ -60,15 +58,11 @@ async fn main(spawner: Spawner) {
60 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); 58 let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config);
61 let spi = ExclusiveDevice::new(spi, cs, Delay); 59 let spi = ExclusiveDevice::new(spi, cs, Delay);
62 60
61 let iface = hosted::SpiInterface::new(spi, handshake, ready);
62
63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new(); 63 static ESP_STATE: StaticCell<embassy_net_esp_hosted::State> = StaticCell::new();
64 let (device, mut control, runner) = embassy_net_esp_hosted::new( 64 let (device, mut control, runner) =
65 ESP_STATE.init(embassy_net_esp_hosted::State::new()), 65 embassy_net_esp_hosted::new(ESP_STATE.init(embassy_net_esp_hosted::State::new()), iface, reset).await;
66 spi,
67 handshake,
68 ready,
69 reset,
70 )
71 .await;
72 66
73 spawner.spawn(unwrap!(wifi_task(runner))); 67 spawner.spawn(unwrap!(wifi_task(runner)));
74 68
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index 256fee08d..b8d5dbfb1 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf5340-examples" 3name = "embassy-nrf5340-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -10,7 +10,7 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embedded-io-async = { version = "0.6.1" } 16embedded-io-async = { version = "0.6.1" }
@@ -23,7 +23,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
23cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
24panic-probe = { version = "1.0.0", features = ["print-defmt"] } 24panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25embedded-storage = "0.3.1" 25embedded-storage = "0.3.1"
26usbd-hid = "0.8.1" 26usbd-hid = "0.9.0"
27serde = { version = "1.0.136", default-features = false } 27serde = { version = "1.0.136", default-features = false }
28 28
29[profile.release] 29[profile.release]
diff --git a/examples/nrf5340/src/bin/gpiote_channel.rs b/examples/nrf5340/src/bin/gpiote_channel.rs
index 23f6fca98..41ee732c3 100644
--- a/examples/nrf5340/src/bin/gpiote_channel.rs
+++ b/examples/nrf5340/src/bin/gpiote_channel.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull}; 6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -12,26 +12,10 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default()); 12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!"); 13 info!("Starting!");
14 14
15 let ch1 = InputChannel::new( 15 let mut ch1 = InputChannel::new(p.GPIOTE_CH0, p.P0_23, Pull::Up, InputChannelPolarity::HiToLo);
16 p.GPIOTE_CH0, 16 let mut ch2 = InputChannel::new(p.GPIOTE_CH1, p.P0_24, Pull::Up, InputChannelPolarity::LoToHi);
17 Input::new(p.P0_23, Pull::Up), 17 let mut ch3 = InputChannel::new(p.GPIOTE_CH2, p.P0_08, Pull::Up, InputChannelPolarity::Toggle);
18 InputChannelPolarity::HiToLo, 18 let mut ch4 = InputChannel::new(p.GPIOTE_CH3, p.P0_09, Pull::Up, InputChannelPolarity::Toggle);
19 );
20 let ch2 = InputChannel::new(
21 p.GPIOTE_CH1,
22 Input::new(p.P0_24, Pull::Up),
23 InputChannelPolarity::LoToHi,
24 );
25 let ch3 = InputChannel::new(
26 p.GPIOTE_CH2,
27 Input::new(p.P0_08, Pull::Up),
28 InputChannelPolarity::Toggle,
29 );
30 let ch4 = InputChannel::new(
31 p.GPIOTE_CH3,
32 Input::new(p.P0_09, Pull::Up),
33 InputChannelPolarity::Toggle,
34 );
35 19
36 let button1 = async { 20 let button1 = async {
37 loop { 21 loop {
diff --git a/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs b/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs
new file mode 100644
index 000000000..0b1fb852e
--- /dev/null
+++ b/examples/nrf5340/src/bin/nrf5340dk_internal_caps.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::config::{Config, HfclkSource, LfclkSource, LfxoCapacitance};
7use embassy_nrf::pac;
8use {defmt_rtt as _, panic_probe as _};
9
10fn print_xosc32mcaps() {
11 let value = pac::OSCILLATORS.xosc32mcaps().read();
12 info!("XOSC32MCAPS.ENABLE = {}", value.enable());
13 info!("XOSC32MCAPS.CAPVALUE = {}", value.capvalue());
14}
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 info!("Before init:");
19 print_xosc32mcaps();
20
21 let mut config = Config::default();
22 config.hfclk_source = HfclkSource::Internal;
23 config.lfclk_source = LfclkSource::ExternalXtal;
24 config.internal_capacitors.hfxo = None; // keep the value from the FICR
25 config.internal_capacitors.lfxo = Some(LfxoCapacitance::_7pF);
26 let _p = embassy_nrf::init(config);
27
28 info!("After init:");
29 print_xosc32mcaps();
30}
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index 9c24cdab4..353d1b46e 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -1,14 +1,20 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf54l15-examples" 3name = "embassy-nrf54l15-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
16
17rand = { version = "0.9.0", default-features = false }
12 18
13defmt = "1.0.1" 19defmt = "1.0.1"
14defmt-rtt = "1.0.0" 20defmt-rtt = "1.0.0"
@@ -18,6 +24,9 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
18cortex-m-rt = "0.7.0" 24cortex-m-rt = "0.7.0"
19 25
20embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
27portable-atomic = "1"
28
29static_cell = "2"
21 30
22[profile.release] 31[profile.release]
23debug = 2 32debug = 2
diff --git a/examples/nrf54l15/memory.x b/examples/nrf54l15/memory.x
index 1064c8a5c..332200828 100644
--- a/examples/nrf54l15/memory.x
+++ b/examples/nrf54l15/memory.x
@@ -1,5 +1,5 @@
1MEMORY 1MEMORY
2{ 2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 1536K 3 FLASH : ORIGIN = 0x00000000, LENGTH = 1524K
4 RAM : ORIGIN = 0x20000000, LENGTH = 256K 4 RAM : ORIGIN = 0x20000000, LENGTH = 256K
5} 5}
diff --git a/examples/nrf54l15/src/bin/buffered_uart.rs b/examples/nrf54l15/src/bin/buffered_uart.rs
new file mode 100644
index 000000000..41fa1ca4e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/buffered_uart.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::buffered_uarte::{self, BufferedUarte};
7use embassy_nrf::{bind_interrupts, peripherals, uarte};
8use embedded_io_async::Write;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SERIAL20 => buffered_uarte::InterruptHandler<peripherals::SERIAL20>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default());
18 let mut config = uarte::Config::default();
19 config.parity = uarte::Parity::EXCLUDED;
20 config.baudrate = uarte::Baudrate::BAUD115200;
21
22 let mut tx_buffer = [0u8; 4096];
23 let mut rx_buffer = [0u8; 4096];
24
25 let mut u = BufferedUarte::new(
26 p.SERIAL20,
27 p.P1_12,
28 p.P1_13,
29 Irqs,
30 config,
31 &mut rx_buffer,
32 &mut tx_buffer,
33 );
34
35 info!("uarte initialized!");
36
37 unwrap!(u.write_all(b"Hello!\r\n").await);
38 info!("wrote hello in uart!");
39
40 loop {
41 info!("reading...");
42 let buf = unwrap!(u.fill_buf().await);
43 info!("read done, got {}", buf);
44
45 // Read bytes have to be explicitly consumed, otherwise fill_buf() will return them again
46 let n = buf.len();
47 u.consume(n);
48 }
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_channel.rs b/examples/nrf54l15/src/bin/gpiote_channel.rs
new file mode 100644
index 000000000..cac8823f8
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_channel.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!");
14
15 let mut ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_13, Pull::Up, InputChannelPolarity::HiToLo);
16 let mut ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi);
17 let mut ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle);
18 let mut ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_04, Pull::Up, InputChannelPolarity::Toggle);
19
20 let button1 = async {
21 loop {
22 ch1.wait().await;
23 info!("Button 1 pressed")
24 }
25 };
26
27 let button2 = async {
28 loop {
29 ch2.wait().await;
30 info!("Button 2 released")
31 }
32 };
33
34 let button3 = async {
35 loop {
36 ch3.wait().await;
37 info!("Button 3 toggled")
38 }
39 };
40
41 let button4 = async {
42 loop {
43 ch4.wait().await;
44 info!("Button 4 toggled")
45 }
46 };
47
48 embassy_futures::join::join4(button1, button2, button3, button4).await;
49}
diff --git a/examples/nrf54l15/src/bin/gpiote_port.rs b/examples/nrf54l15/src/bin/gpiote_port.rs
new file mode 100644
index 000000000..620cb2435
--- /dev/null
+++ b/examples/nrf54l15/src/bin/gpiote_port.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task(pool_size = 4)]
10async fn button_task(n: usize, mut pin: Input<'static>) {
11 loop {
12 pin.wait_for_low().await;
13 info!("Button {:?} pressed!", n);
14 pin.wait_for_high().await;
15 info!("Button {:?} released!", n);
16 }
17}
18
19#[embassy_executor::main]
20async fn main(spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default());
22 info!("Starting!");
23
24 let btn1 = Input::new(p.P1_13, Pull::Up);
25 let btn2 = Input::new(p.P1_09, Pull::Up);
26 let btn3 = Input::new(p.P1_08, Pull::Up);
27 let btn4 = Input::new(p.P0_04, Pull::Up);
28
29 spawner.spawn(unwrap!(button_task(1, btn1)));
30 spawner.spawn(unwrap!(button_task(2, btn2)));
31 spawner.spawn(unwrap!(button_task(3, btn3)));
32 spawner.spawn(unwrap!(button_task(4, btn4)));
33}
diff --git a/examples/nrf54l15/src/bin/pwm.rs b/examples/nrf54l15/src/bin/pwm.rs
new file mode 100644
index 000000000..b438978f1
--- /dev/null
+++ b/examples/nrf54l15/src/bin/pwm.rs
@@ -0,0 +1,86 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::pwm::{DutyCycle, Prescaler, SimplePwm};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='')
11static DUTY: [u16; 1024] = [
12 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, 9526, 9613, 9700,
13 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, 10766, 10857, 10948, 11039, 11131, 11223,
14 11315, 11407, 11500, 11592, 11685, 11779, 11872, 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723,
15 12818, 12914, 13010, 13106, 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266,
16 14364, 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, 15730, 15828,
17 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, 16995, 17091, 17188, 17284, 17380,
18 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896,
19 18989, 19082, 19174, 19266, 19358, 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346,
20 20434, 20521, 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, 21701,
21 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, 22714, 22788, 22861, 22934,
22 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, 23631, 23698, 23763, 23828, 23892, 23956, 24019,
23 24081, 24143, 24204, 24264, 24324, 24383, 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933,
24 24983, 25034, 25083, 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655,
25 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, 26117, 26144, 26170,
26 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, 26397, 26413, 26427, 26441, 26454, 26466,
27 26477, 26487, 26496, 26505, 26512, 26519, 26525, 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537,
28 26534, 26530, 26525, 26519, 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381,
29 26364, 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, 26032, 26002,
30 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, 25575, 25535, 25493, 25451, 25407,
31 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611,
32 24555, 24499, 24441, 24383, 24324, 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631,
33 23564, 23497, 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, 22488,
34 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, 21456, 21373, 21290, 21206,
35 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, 20346, 20258, 20169, 20081, 19991, 19902, 19812,
36 19722, 19631, 19540, 19449, 19358, 19266, 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334,
37 18239, 18145, 18050, 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801,
38 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, 15437, 15339, 15242,
39 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, 14169, 14072, 13975, 13878, 13781, 13684,
40 13587, 13491, 13394, 13298, 13202, 13106, 13010, 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154,
41 12060, 11966, 11872, 11779, 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675,
42 10585, 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, 9184, 9099,
43 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, 7873, 7794, 7716, 7638, 7561,
44 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172,
45 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947,
46 4888, 4828, 4769, 4711, 4653, 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892,
47 3841, 3791, 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, 3005,
48 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, 2382, 2347, 2312, 2278,
49 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, 1867, 1838, 1810, 1781, 1754, 1726, 1699,
50 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252,
51 1232, 1212, 1192, 1173, 1154, 1135, 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903,
52 888, 874, 860, 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, 627,
53 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, 479, 473, 467, 461, 455,
54 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, 386, 383, 379, 376, 373, 370, 367, 364, 361,
55 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328,
56 327, 327, 327, 327, 327, 328, 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347,
57 349, 351, 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, 419, 424,
58 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, 534, 541, 549, 557, 565, 574,
59 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, 710, 721, 733, 744, 756, 768, 781, 793, 806, 819,
60 833, 846, 860, 874, 888, 903, 918, 933, 948, 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154,
61 1173, 1192, 1212, 1232, 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570,
62 1595, 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, 2080, 2112,
63 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, 2641, 2680, 2719, 2758, 2798,
64 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642,
65 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653,
66 4711, 4769, 4828, 4888, 4947, 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834,
67 5901, 5968, 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, 7180,
68 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111,
69];
70
71#[embassy_executor::main]
72async fn main(_spawner: Spawner) {
73 let p = embassy_nrf::init(Default::default());
74 let mut pwm = SimplePwm::new_2ch(p.PWM20, p.P1_10, p.P1_14, &Default::default());
75 pwm.set_prescaler(Prescaler::Div1);
76 pwm.set_max_duty(32767);
77 info!("pwm initialized!");
78
79 let mut i = 0;
80 loop {
81 i += 1;
82 pwm.set_duty(0, DutyCycle::normal(DUTY[i % 1024]));
83 pwm.set_duty(1, DutyCycle::normal(DUTY[(i + 512) % 1024]));
84 Timer::after_millis(3).await;
85 }
86}
diff --git a/examples/nrf54l15/src/bin/rng.rs b/examples/nrf54l15/src/bin/rng.rs
new file mode 100644
index 000000000..b2d7f906b
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rng.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::cracen::Cracen;
6use rand::Rng as _;
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_nrf::init(Default::default());
12 let mut rng = Cracen::new_blocking(p.CRACEN);
13
14 // Async API
15 let mut bytes = [0; 4];
16 rng.blocking_fill_bytes(&mut bytes);
17 defmt::info!("Some random bytes: {:?}", bytes);
18
19 // Sync API with `rand`
20 defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10));
21
22 let mut bytes = [0; 1024];
23 rng.blocking_fill_bytes(&mut bytes);
24 let zero_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_zeros());
25 let one_count: u32 = bytes.iter().fold(0, |acc, val| acc + val.count_ones());
26 defmt::info!("Chance of zero: {}%", zero_count * 100 / (bytes.len() as u32 * 8));
27 defmt::info!("Chance of one: {}%", one_count * 100 / (bytes.len() as u32 * 8));
28}
diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/rramc.rs
index f990604cd..f990604cd 100644
--- a/examples/nrf54l15/src/bin/nvmc.rs
+++ b/examples/nrf54l15/src/bin/rramc.rs
diff --git a/examples/nrf54l15/src/bin/rramc_buffered.rs b/examples/nrf54l15/src/bin/rramc_buffered.rs
new file mode 100644
index 000000000..06c9585ed
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rramc_buffered.rs
@@ -0,0 +1,59 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::rramc::{Buffered, PAGE_SIZE, Rramc};
7use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Hello RRAMC NVMC!");
14
15 // Buffer 8 word lines
16 let mut f: Rramc<'_, Buffered<128>> = Rramc::new_buffered(p.RRAMC);
17
18 const ADDR: u32 = 0x80000;
19 let mut buf = [0u8; 4];
20
21 info!("Reading...");
22 unwrap!(f.read(ADDR, &mut buf));
23 info!("Read: {=[u8]:x}", buf);
24
25 info!("Erasing...");
26 unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32));
27
28 info!("Reading...");
29 unwrap!(f.read(ADDR, &mut buf));
30 info!("Read: {=[u8]:x}", buf);
31
32 info!("Writing...");
33 // 16 B (128-bit) write minimum
34 let out: [u8; 256] = [
35 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa,
36 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa,
37 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb,
38 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb,
39 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc,
40 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc,
41 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd,
42 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd,
43 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa,
44 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa,
45 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb,
46 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb,
47 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc,
48 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc,
49 0xdd, 0xdd, 0xdd, 0xdd,
50 ];
51 unwrap!(f.write(ADDR, &out));
52
53 info!("Reading...");
54 // Can read arbitrary sizes
55 for addr in (ADDR..ADDR + 256).step_by(4) {
56 unwrap!(f.read(addr, &mut buf));
57 info!("Read: {=[u8]:x}", buf);
58 }
59}
diff --git a/examples/nrf54l15/src/bin/saadc.rs b/examples/nrf54l15/src/bin/saadc.rs
new file mode 100644
index 000000000..567177894
--- /dev/null
+++ b/examples/nrf54l15/src/bin/saadc.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
7use embassy_nrf::{bind_interrupts, saadc};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SAADC => saadc::InterruptHandler;
13});
14
15#[embassy_executor::main]
16async fn main(_p: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let config = Config::default();
19 let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow());
20 let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
21
22 loop {
23 let mut buf = [0; 1];
24 saadc.sample(&mut buf).await;
25 info!("sample: {=i16}", &buf[0]);
26 Timer::after_millis(100).await;
27 }
28}
diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs
new file mode 100644
index 000000000..3f5980647
--- /dev/null
+++ b/examples/nrf54l15/src/bin/spim.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::{bind_interrupts, peripherals, spim};
6use {defmt_rtt as _, panic_probe as _};
7
8bind_interrupts!(struct Irqs {
9 SERIAL00 => spim::InterruptHandler<peripherals::SERIAL00>;
10});
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default());
15 let mut config = spim::Config::default();
16 config.frequency = spim::Frequency::M32;
17 let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone());
18 let data = [
19 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
20 ];
21 let mut buf = [0u8; 16];
22
23 buf.fill(0);
24 spim.blocking_transfer(&mut buf, &data).unwrap();
25 assert_eq!(data, buf);
26
27 buf.fill(0);
28 spim.transfer(&mut buf, &data).await.unwrap();
29 assert_eq!(data, buf);
30}
diff --git a/examples/nrf54l15/src/bin/timer.rs b/examples/nrf54l15/src/bin/timer.rs
new file mode 100644
index 000000000..68acc91c1
--- /dev/null
+++ b/examples/nrf54l15/src/bin/timer.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_time::Timer;
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task]
10async fn run1() {
11 loop {
12 info!("BIG INFREQUENT TICK");
13 Timer::after_secs(10).await;
14 }
15}
16
17#[embassy_executor::task]
18async fn run2() {
19 loop {
20 info!("tick");
21 Timer::after_secs(1).await;
22 }
23}
24
25#[embassy_executor::main]
26async fn main(spawner: Spawner) {
27 let _p = embassy_nrf::init(Default::default());
28 spawner.spawn(unwrap!(run1()));
29 spawner.spawn(unwrap!(run2()));
30}
diff --git a/examples/nrf54l15/src/bin/twim.rs b/examples/nrf54l15/src/bin/twim.rs
new file mode 100644
index 000000000..53b85034e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twim.rs
@@ -0,0 +1,37 @@
1//! Example on how to read a 24C/24LC i2c eeprom.
2//!
3//! Connect SDA to P0.03, SCL to P0.04
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_nrf::twim::{self, Twim};
11use embassy_nrf::{bind_interrupts, peripherals};
12use static_cell::ConstStaticCell;
13use {defmt_rtt as _, panic_probe as _};
14
15const ADDRESS: u8 = 0x18;
16const WHOAMI: u8 = 0x0F;
17
18bind_interrupts!(struct Irqs {
19 SERIAL20 => twim::InterruptHandler<peripherals::SERIAL20>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default());
25 info!("Initializing TWI...");
26 let config = twim::Config::default();
27 static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
28 let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take());
29
30 info!("Reading...");
31
32 let mut data = [0u8; 1];
33 match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await {
34 Ok(()) => info!("Whoami: {}", data[0]),
35 Err(e) => error!("I2c Error: {:?}", e),
36 }
37}
diff --git a/examples/nrf54l15/src/bin/twis.rs b/examples/nrf54l15/src/bin/twis.rs
new file mode 100644
index 000000000..34c04aee3
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twis.rs
@@ -0,0 +1,47 @@
1//! TWIS example
2
3#![no_std]
4#![no_main]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_nrf::twis::{self, Command, Twis};
9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 SERIAL20 => twis::InterruptHandler<peripherals::SERIAL20>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default());
19
20 let mut config = twis::Config::default();
21 config.address0 = 0x55; // Set i2c address
22 let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config);
23
24 info!("Listening...");
25 loop {
26 let response = [1, 2, 3, 4, 5, 6, 7, 8];
27 // This buffer is used if the i2c master performs a Write or WriteRead
28 let mut buf = [0u8; 16];
29 match i2c.listen(&mut buf).await {
30 Ok(Command::Read) => {
31 info!("Got READ command. Respond with data:\n{:?}\n", response);
32 if let Err(e) = i2c.respond_to_read(&response).await {
33 error!("{:?}", e);
34 }
35 }
36 Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]),
37 Ok(Command::WriteRead(n)) => {
38 info!("Got WRITE/READ command with data:\n{:?}", buf[..n]);
39 info!("Respond with data:\n{:?}\n", response);
40 if let Err(e) = i2c.respond_to_read(&response).await {
41 error!("{:?}", e);
42 }
43 }
44 Err(e) => error!("{:?}", e),
45 }
46 }
47}
diff --git a/examples/nrf54l15/src/bin/uart.rs b/examples/nrf54l15/src/bin/uart.rs
new file mode 100644
index 000000000..cc6528a6f
--- /dev/null
+++ b/examples/nrf54l15/src/bin/uart.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::{bind_interrupts, peripherals, uarte};
7use {defmt_rtt as _, panic_probe as _};
8
9bind_interrupts!(struct Irqs {
10 SERIAL20 => uarte::InterruptHandler<peripherals::SERIAL20>;
11});
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16 let mut config = uarte::Config::default();
17 config.parity = uarte::Parity::EXCLUDED;
18 config.baudrate = uarte::Baudrate::BAUD115200;
19
20 let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config);
21
22 info!("uarte initialized!");
23
24 // Message must be in SRAM
25 let mut buf = [0; 8];
26 buf.copy_from_slice(b"Hello!\r\n");
27
28 unwrap!(uart.write(&buf).await);
29 info!("wrote hello in uart!");
30
31 loop {
32 info!("reading...");
33 unwrap!(uart.read(&mut buf).await);
34 info!("writing...");
35 unwrap!(uart.write(&buf).await);
36 }
37}
diff --git a/examples/nrf54lm20/.cargo/config.toml b/examples/nrf54lm20/.cargo/config.toml
new file mode 100644
index 000000000..0ffebed14
--- /dev/null
+++ b/examples/nrf54lm20/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# Note: it needs the latest git version of probe-rs
3runner = "probe-rs run --chip nrf54lm20a"
4
5[build]
6target = "thumbv8m.main-none-eabihf"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/nrf54lm20/Cargo.toml b/examples/nrf54lm20/Cargo.toml
new file mode 100644
index 000000000..e3bf22b25
--- /dev/null
+++ b/examples/nrf54lm20/Cargo.toml
@@ -0,0 +1,37 @@
1[package]
2edition = "2024"
3name = "embassy-nrf54lm20-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54lm20-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
16
17rand = { version = "0.9.0", default-features = false }
18
19defmt = "1.0.1"
20defmt-rtt = "1.0.0"
21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22
23cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
24cortex-m-rt = "0.7.0"
25
26embedded-storage = "0.3.1"
27portable-atomic = "1"
28
29static_cell = "2"
30
31[profile.release]
32debug = 2
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf54lm20" }
37]
diff --git a/examples/nrf54lm20/build.rs b/examples/nrf54lm20/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/nrf54lm20/build.rs
@@ -0,0 +1,35 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35}
diff --git a/examples/nrf54lm20/memory.x b/examples/nrf54lm20/memory.x
new file mode 100644
index 000000000..564f488ac
--- /dev/null
+++ b/examples/nrf54lm20/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x00000000, LENGTH = 2036K
4 RAM : ORIGIN = 0x20000000, LENGTH = 512K
5}
diff --git a/examples/nrf54lm20/src/bin/blinky.rs b/examples/nrf54lm20/src/bin/blinky.rs
new file mode 100644
index 000000000..962e9f5a6
--- /dev/null
+++ b/examples/nrf54lm20/src/bin/blinky.rs
@@ -0,0 +1,23 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 let mut led = Output::new(p.P1_22, Level::Low, OutputDrive::HighDrive);
14
15 loop {
16 info!("high!");
17 led.set_high();
18 Timer::after_millis(300).await;
19 info!("low!");
20 led.set_low();
21 Timer::after_millis(300).await;
22 }
23}
diff --git a/examples/nrf54lm20/src/bin/gpio.rs b/examples/nrf54lm20/src/bin/gpio.rs
new file mode 100644
index 000000000..4b6b4630d
--- /dev/null
+++ b/examples/nrf54lm20/src/bin/gpio.rs
@@ -0,0 +1,23 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 let btn = Input::new(p.P1_26, Pull::Up);
14
15 loop {
16 if btn.is_high() {
17 info!("high");
18 } else {
19 info!("low");
20 }
21 Timer::after_millis(100).await;
22 }
23}
diff --git a/examples/nrf54lm20/src/bin/gpiote_channel.rs b/examples/nrf54lm20/src/bin/gpiote_channel.rs
new file mode 100644
index 000000000..0f30f06c7
--- /dev/null
+++ b/examples/nrf54lm20/src/bin/gpiote_channel.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::Pull;
7use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Starting!");
14
15 let mut ch1 = InputChannel::new(p.GPIOTE20_CH0, p.P1_26, Pull::Up, InputChannelPolarity::HiToLo);
16 let mut ch2 = InputChannel::new(p.GPIOTE20_CH1, p.P1_09, Pull::Up, InputChannelPolarity::LoToHi);
17 let mut ch3 = InputChannel::new(p.GPIOTE20_CH2, p.P1_08, Pull::Up, InputChannelPolarity::Toggle);
18 let mut ch4 = InputChannel::new(p.GPIOTE30_CH0, p.P0_05, Pull::Up, InputChannelPolarity::Toggle);
19
20 let button1 = async {
21 loop {
22 ch1.wait().await;
23 info!("Button 1 pressed")
24 }
25 };
26
27 let button2 = async {
28 loop {
29 ch2.wait().await;
30 info!("Button 2 released")
31 }
32 };
33
34 let button3 = async {
35 loop {
36 ch3.wait().await;
37 info!("Button 3 toggled")
38 }
39 };
40
41 let button4 = async {
42 loop {
43 ch4.wait().await;
44 info!("Button 4 toggled")
45 }
46 };
47
48 embassy_futures::join::join4(button1, button2, button3, button4).await;
49}
diff --git a/examples/nrf54lm20/src/bin/gpiote_port.rs b/examples/nrf54lm20/src/bin/gpiote_port.rs
new file mode 100644
index 000000000..6dbd63d92
--- /dev/null
+++ b/examples/nrf54lm20/src/bin/gpiote_port.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::gpio::{Input, Pull};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task(pool_size = 4)]
10async fn button_task(n: usize, mut pin: Input<'static>) {
11 loop {
12 pin.wait_for_low().await;
13 info!("Button {:?} pressed!", n);
14 pin.wait_for_high().await;
15 info!("Button {:?} released!", n);
16 }
17}
18
19#[embassy_executor::main]
20async fn main(spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default());
22 info!("Starting!");
23
24 let btn1 = Input::new(p.P1_26, Pull::Up);
25 let btn2 = Input::new(p.P1_09, Pull::Up);
26 let btn3 = Input::new(p.P1_08, Pull::Up);
27 let btn4 = Input::new(p.P0_05, Pull::Up);
28
29 spawner.spawn(unwrap!(button_task(1, btn1)));
30 spawner.spawn(unwrap!(button_task(2, btn2)));
31 spawner.spawn(unwrap!(button_task(3, btn3)));
32 spawner.spawn(unwrap!(button_task(4, btn4)));
33}
diff --git a/examples/nrf54lm20/src/bin/timer.rs b/examples/nrf54lm20/src/bin/timer.rs
new file mode 100644
index 000000000..68acc91c1
--- /dev/null
+++ b/examples/nrf54lm20/src/bin/timer.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_time::Timer;
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::task]
10async fn run1() {
11 loop {
12 info!("BIG INFREQUENT TICK");
13 Timer::after_secs(10).await;
14 }
15}
16
17#[embassy_executor::task]
18async fn run2() {
19 loop {
20 info!("tick");
21 Timer::after_secs(1).await;
22 }
23}
24
25#[embassy_executor::main]
26async fn main(spawner: Spawner) {
27 let _p = embassy_nrf::init(Default::default());
28 spawner.spawn(unwrap!(run1()));
29 spawner.spawn(unwrap!(run2()));
30}
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml
index 89a6c7c94..f6d6aab6f 100644
--- a/examples/nrf9151/ns/Cargo.toml
+++ b/examples/nrf9151/ns/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf9151-non-secure-examples" 3name = "embassy-nrf9151-non-secure-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-nrf = { version = "0.8.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.9.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
12 12
13defmt = "1.0.1" 13defmt = "1.0.1"
14defmt-rtt = "1.0.0" 14defmt-rtt = "1.0.0"
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml
index 870311c5d..1c9e7fb35 100644
--- a/examples/nrf9151/s/Cargo.toml
+++ b/examples/nrf9151/s/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf9151-secure-examples" 3name = "embassy-nrf9151-secure-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-nrf = { version = "0.8.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.9.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
12 12
13defmt = "1.0.1" 13defmt = "1.0.1"
14defmt-rtt = "1.0.0" 14defmt-rtt = "1.0.0"
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml
index 274e26dd6..907b06e6d 100644
--- a/examples/nrf9160/Cargo.toml
+++ b/examples/nrf9160/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-nrf9160-examples" 3name = "embassy-nrf9160-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
12embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } 12embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] }
13embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } 13embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] }
14 14
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs
index 460a4cfae..07fa57e63 100644
--- a/examples/nrf9160/src/bin/modem_tcp_client.rs
+++ b/examples/nrf9160/src/bin/modem_tcp_client.rs
@@ -11,11 +11,11 @@ use defmt::{info, unwrap, warn};
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_net::{Ipv4Cidr, Stack, StackResources}; 12use embassy_net::{Ipv4Cidr, Stack, StackResources};
13use embassy_net_nrf91::context::Status; 13use embassy_net_nrf91::context::Status;
14use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader}; 14use embassy_net_nrf91::{Runner, State, TraceBuffer, TraceReader, context};
15use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; 15use embassy_nrf::buffered_uarte::{self, BufferedUarteTx};
16use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive}; 16use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
17use embassy_nrf::uarte::Baudrate; 17use embassy_nrf::uarte::Baudrate;
18use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte, Peri}; 18use embassy_nrf::{Peri, bind_interrupts, interrupt, peripherals, uarte};
19use embassy_time::{Duration, Timer}; 19use embassy_time::{Duration, Timer};
20use embedded_io_async::Write; 20use embedded_io_async::Write;
21use heapless::Vec; 21use heapless::Vec;
@@ -101,7 +101,7 @@ async fn blink_task(pin: Peri<'static, AnyPin>) {
101 } 101 }
102} 102}
103 103
104extern "C" { 104unsafe extern "C" {
105 static __start_ipc: u8; 105 static __start_ipc: u8;
106 static __end_ipc: u8; 106 static __end_ipc: u8;
107} 107}
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 97e019cdf..e247f6f7a 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-rp-examples" 3name = "embassy-rp-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -11,14 +11,14 @@ embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal",
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
14embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } 14embassy-rp = { version = "0.9.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } 16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] }
17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } 17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] }
18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } 19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" }
20cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } 20cyw43 = { version = "0.6.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] }
21cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } 21cyw43-pio = { version = "0.9.0", path = "../../cyw43-pio", features = ["defmt"] }
22 22
23defmt = "1.0.1" 23defmt = "1.0.1"
24defmt-rtt = "1.0.0" 24defmt-rtt = "1.0.0"
@@ -45,7 +45,7 @@ display-interface = "0.5.0"
45byte-slice-cast = { version = "1.2.0", default-features = false } 45byte-slice-cast = { version = "1.2.0", default-features = false }
46smart-leds = "0.4.0" 46smart-leds = "0.4.0"
47heapless = "0.8" 47heapless = "0.8"
48usbd-hid = "0.8.1" 48usbd-hid = "0.9.0"
49 49
50embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 50embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
51embedded-hal-async = "1.0" 51embedded-hal-async = "1.0"
diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs
index 4ee4278b5..aaa134768 100644
--- a/examples/rp/src/bin/assign_resources.rs
+++ b/examples/rp/src/bin/assign_resources.rs
@@ -14,9 +14,9 @@
14use assign_resources::assign_resources; 14use assign_resources::assign_resources;
15use defmt::*; 15use defmt::*;
16use embassy_executor::Spawner; 16use embassy_executor::Spawner;
17use embassy_rp::Peri;
17use embassy_rp::gpio::{Level, Output}; 18use embassy_rp::gpio::{Level, Output};
18use embassy_rp::peripherals::{self, PIN_20, PIN_21}; 19use embassy_rp::peripherals::{self, PIN_20, PIN_21};
19use embassy_rp::Peri;
20use embassy_time::Timer; 20use embassy_time::Timer;
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
22 22
diff --git a/examples/rp/src/bin/debounce.rs b/examples/rp/src/bin/debounce.rs
index 0077f19fc..6eeb01d0a 100644
--- a/examples/rp/src/bin/debounce.rs
+++ b/examples/rp/src/bin/debounce.rs
@@ -7,7 +7,7 @@
7use defmt::info; 7use defmt::info;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::gpio::{Input, Level, Pull}; 9use embassy_rp::gpio::{Input, Level, Pull};
10use embassy_time::{with_deadline, Duration, Instant, Timer}; 10use embassy_time::{Duration, Instant, Timer, with_deadline};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13pub struct Debouncer<'a> { 13pub struct Debouncer<'a> {
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
index 49d28071a..cb667f24f 100644
--- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
+++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
@@ -12,8 +12,8 @@ use core::str::FromStr;
12use defmt::*; 12use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_futures::yield_now; 14use embassy_futures::yield_now;
15use embassy_net::icmp::ping::{PingManager, PingParams};
16use embassy_net::icmp::PacketMetadata; 15use embassy_net::icmp::PacketMetadata;
16use embassy_net::icmp::ping::{PingManager, PingParams};
17use embassy_net::{Ipv4Cidr, Stack, StackResources}; 17use embassy_net::{Ipv4Cidr, Stack, StackResources};
18use embassy_net_wiznet::chip::W5500; 18use embassy_net_wiznet::chip::W5500;
19use embassy_net_wiznet::*; 19use embassy_net_wiznet::*;
@@ -99,7 +99,7 @@ async fn main(spawner: Spawner) {
99 // Create the ping manager instance 99 // Create the ping manager instance
100 let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); 100 let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
101 let addr = "192.168.8.1"; // Address to ping to 101 let addr = "192.168.8.1"; // Address to ping to
102 // Create the PingParams with the target address 102 // Create the PingParams with the target address
103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); 103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap());
104 // (optional) Set custom properties of the ping 104 // (optional) Set custom properties of the ping
105 ping_params.set_payload(b"Hello, Ping!"); // custom payload 105 ping_params.set_payload(b"Hello, Ping!"); // custom payload
diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
index f51df2df9..b402029b5 100644
--- a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
+++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
@@ -65,7 +65,7 @@ async fn main(spawner: Spawner) {
65 // Construct an SPI driver backed by a PIO state machine 65 // Construct an SPI driver backed by a PIO state machine
66 let mut spi_cfg = SpiConfig::default(); 66 let mut spi_cfg = SpiConfig::default();
67 spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI 67 spi_cfg.frequency = 12_500_000; // The PIO SPI program is much less stable than the actual SPI
68 // peripheral, use higher speeds at your peril 68 // peripheral, use higher speeds at your peril
69 let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); 69 let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
70 70
71 // Further control pins 71 // Further control pins
diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs
index 2748f778a..2605622ab 100644
--- a/examples/rp/src/bin/interrupt.rs
+++ b/examples/rp/src/bin/interrupt.rs
@@ -16,8 +16,8 @@ use embassy_rp::adc::{self, Adc, Blocking};
16use embassy_rp::gpio::Pull; 16use embassy_rp::gpio::Pull;
17use embassy_rp::interrupt; 17use embassy_rp::interrupt;
18use embassy_rp::pwm::{Config, Pwm}; 18use embassy_rp::pwm::{Config, Pwm};
19use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
20use embassy_sync::blocking_mutex::Mutex; 19use embassy_sync::blocking_mutex::Mutex;
20use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
21use embassy_sync::channel::Channel; 21use embassy_sync::channel::Channel;
22use embassy_time::{Duration, Ticker}; 22use embassy_time::{Duration, Ticker};
23use portable_atomic::{AtomicU32, Ordering}; 23use portable_atomic::{AtomicU32, Ordering};
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index 3a6367420..d289f8020 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -8,7 +8,7 @@
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_rp::gpio::{Level, Output}; 10use embassy_rp::gpio::{Level, Output};
11use embassy_rp::multicore::{spawn_core1, Stack}; 11use embassy_rp::multicore::{Stack, spawn_core1};
12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
13use embassy_sync::channel::Channel; 13use embassy_sync::channel::Channel;
14use embassy_time::Timer; 14use embassy_time::Timer;
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs
index 96cdf8fb1..310047505 100644
--- a/examples/rp/src/bin/multiprio.rs
+++ b/examples/rp/src/bin/multiprio.rs
@@ -61,7 +61,7 @@ use defmt::{info, unwrap};
61use embassy_executor::{Executor, InterruptExecutor}; 61use embassy_executor::{Executor, InterruptExecutor};
62use embassy_rp::interrupt; 62use embassy_rp::interrupt;
63use embassy_rp::interrupt::{InterruptExt, Priority}; 63use embassy_rp::interrupt::{InterruptExt, Priority};
64use embassy_time::{Instant, Timer, TICK_HZ}; 64use embassy_time::{Instant, TICK_HZ, Timer};
65use static_cell::StaticCell; 65use static_cell::StaticCell;
66use {defmt_rtt as _, panic_probe as _}; 66use {defmt_rtt as _, panic_probe as _};
67 67
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn SWI_IRQ_1() { 115unsafe fn SWI_IRQ_1() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn SWI_IRQ_0() { 120unsafe fn SWI_IRQ_0() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs
index 9f25e1087..cd26a5371 100644
--- a/examples/rp/src/bin/orchestrate_tasks.rs
+++ b/examples/rp/src/bin/orchestrate_tasks.rs
@@ -20,11 +20,11 @@
20use assign_resources::assign_resources; 20use assign_resources::assign_resources;
21use defmt::*; 21use defmt::*;
22use embassy_executor::Spawner; 22use embassy_executor::Spawner;
23use embassy_futures::select::{select, Either}; 23use embassy_futures::select::{Either, select};
24use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; 24use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler};
25use embassy_rp::clocks::RoscRng; 25use embassy_rp::clocks::RoscRng;
26use embassy_rp::gpio::{Input, Pull}; 26use embassy_rp::gpio::{Input, Pull};
27use embassy_rp::{bind_interrupts, peripherals, Peri}; 27use embassy_rp::{Peri, bind_interrupts, peripherals};
28use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 28use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
29use embassy_sync::mutex::Mutex; 29use embassy_sync::mutex::Mutex;
30use embassy_sync::{channel, signal}; 30use embassy_sync::{channel, signal};
diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs
index 83b17308b..a98185a8e 100644
--- a/examples/rp/src/bin/overclock.rs
+++ b/examples/rp/src/bin/overclock.rs
@@ -7,7 +7,7 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig}; 10use embassy_rp::clocks::{ClockConfig, clk_sys_freq, core_voltage};
11use embassy_rp::config::Config; 11use embassy_rp::config::Config;
12use embassy_rp::gpio::{Level, Output}; 12use embassy_rp::gpio::{Level, Output};
13use embassy_time::{Duration, Instant, Timer}; 13use embassy_time::{Duration, Instant, Timer};
diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs
index dea5cfb3c..18397f9a8 100644
--- a/examples/rp/src/bin/overclock_manual.rs
+++ b/examples/rp/src/bin/overclock_manual.rs
@@ -7,7 +7,7 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig}; 10use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig, clk_sys_freq, core_voltage};
11use embassy_rp::config::Config; 11use embassy_rp::config::Config;
12use embassy_rp::gpio::{Level, Output}; 12use embassy_rp::gpio::{Level, Output};
13use embassy_time::{Duration, Instant, Timer}; 13use embassy_time::{Duration, Instant, Timer};
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 1743a417e..55e983c36 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_rp::peripherals::PIO0; 7use embassy_rp::peripherals::PIO0;
8use embassy_rp::pio::program::pio_asm; 8use embassy_rp::pio::program::pio_asm;
9use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; 9use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine};
10use embassy_rp::{bind_interrupts, Peri}; 10use embassy_rp::{Peri, bind_interrupts};
11use fixed::traits::ToFixed; 11use fixed::traits::ToFixed;
12use fixed_macro::types::U56F8; 12use fixed_macro::types::U56F8;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp/src/bin/pio_onewire.rs
+++ b/examples/rp/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/rp/src/bin/pio_stepper.rs b/examples/rp/src/bin/pio_stepper.rs
index 3862c248b..e8f203990 100644
--- a/examples/rp/src/bin/pio_stepper.rs
+++ b/examples/rp/src/bin/pio_stepper.rs
@@ -10,7 +10,7 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::PIO0; 10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{InterruptHandler, Pio}; 11use embassy_rp::pio::{InterruptHandler, Pio};
12use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; 12use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram};
13use embassy_time::{with_timeout, Duration, Timer}; 13use embassy_time::{Duration, Timer, with_timeout};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs
index 9dd07ab6e..f985bf7cf 100644
--- a/examples/rp/src/bin/pwm.rs
+++ b/examples/rp/src/bin/pwm.rs
@@ -9,9 +9,9 @@
9 9
10use defmt::*; 10use defmt::*;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_rp::peripherals::{PIN_25, PIN_4, PWM_SLICE2, PWM_SLICE4};
13use embassy_rp::pwm::{Config, Pwm, SetDutyCycle};
14use embassy_rp::Peri; 12use embassy_rp::Peri;
13use embassy_rp::peripherals::{PIN_4, PIN_25, PWM_SLICE2, PWM_SLICE4};
14use embassy_rp::pwm::{Config, Pwm, SetDutyCycle};
15use embassy_time::Timer; 15use embassy_time::Timer;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
diff --git a/examples/rp/src/bin/rtc_alarm.rs b/examples/rp/src/bin/rtc_alarm.rs
index 94b5fbd27..bde49ccd5 100644
--- a/examples/rp/src/bin/rtc_alarm.rs
+++ b/examples/rp/src/bin/rtc_alarm.rs
@@ -5,7 +5,7 @@
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_futures::select::{select, Either}; 8use embassy_futures::select::{Either, select};
9use embassy_rp::bind_interrupts; 9use embassy_rp::bind_interrupts;
10use embassy_rp::rtc::{DateTime, DateTimeFilter, DayOfWeek, Rtc}; 10use embassy_rp::rtc::{DateTime, DateTimeFilter, DayOfWeek, Rtc};
11use embassy_time::Timer; 11use embassy_time::Timer;
diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs
index d4c89946b..618ab9117 100644
--- a/examples/rp/src/bin/sharing.rs
+++ b/examples/rp/src/bin/sharing.rs
@@ -52,7 +52,7 @@ bind_interrupts!(struct Irqs {
52 52
53#[interrupt] 53#[interrupt]
54unsafe fn SWI_IRQ_0() { 54unsafe fn SWI_IRQ_0() {
55 EXECUTOR_HI.on_interrupt() 55 unsafe { EXECUTOR_HI.on_interrupt() }
56} 56}
57 57
58#[entry] 58#[entry]
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs
index dd114a4ae..4bf924e56 100644
--- a/examples/rp/src/bin/spi_display.rs
+++ b/examples/rp/src/bin/spi_display.rs
@@ -15,19 +15,19 @@ use embassy_executor::Spawner;
15use embassy_rp::gpio::{Level, Output}; 15use embassy_rp::gpio::{Level, Output};
16use embassy_rp::spi; 16use embassy_rp::spi;
17use embassy_rp::spi::Spi; 17use embassy_rp::spi::Spi;
18use embassy_sync::blocking_mutex::raw::NoopRawMutex;
19use embassy_sync::blocking_mutex::Mutex; 18use embassy_sync::blocking_mutex::Mutex;
19use embassy_sync::blocking_mutex::raw::NoopRawMutex;
20use embassy_time::Delay; 20use embassy_time::Delay;
21use embedded_graphics::image::{Image, ImageRawLE}; 21use embedded_graphics::image::{Image, ImageRawLE};
22use embedded_graphics::mono_font::ascii::FONT_10X20;
23use embedded_graphics::mono_font::MonoTextStyle; 22use embedded_graphics::mono_font::MonoTextStyle;
23use embedded_graphics::mono_font::ascii::FONT_10X20;
24use embedded_graphics::pixelcolor::Rgb565; 24use embedded_graphics::pixelcolor::Rgb565;
25use embedded_graphics::prelude::*; 25use embedded_graphics::prelude::*;
26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; 26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
27use embedded_graphics::text::Text; 27use embedded_graphics::text::Text;
28use mipidsi::Builder;
28use mipidsi::models::ST7789; 29use mipidsi::models::ST7789;
29use mipidsi::options::{Orientation, Rotation}; 30use mipidsi::options::{Orientation, Rotation};
30use mipidsi::Builder;
31use {defmt_rtt as _, panic_probe as _}; 31use {defmt_rtt as _, panic_probe as _};
32 32
33use crate::touch::Touch; 33use crate::touch::Touch;
@@ -167,11 +167,7 @@ mod touch {
167 167
168 let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); 168 let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx);
169 let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); 169 let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy);
170 if x == 0 && y == 0 { 170 if x == 0 && y == 0 { None } else { Some((x, y)) }
171 None
172 } else {
173 Some((x, y))
174 }
175 } 171 }
176 } 172 }
177} 173}
diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs
index fdef09d4b..fd007b9bd 100644
--- a/examples/rp/src/bin/spi_gc9a01.rs
+++ b/examples/rp/src/bin/spi_gc9a01.rs
@@ -16,16 +16,16 @@ use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Level, Output}; 16use embassy_rp::gpio::{Level, Output};
17use embassy_rp::spi; 17use embassy_rp::spi;
18use embassy_rp::spi::{Blocking, Spi}; 18use embassy_rp::spi::{Blocking, Spi};
19use embassy_sync::blocking_mutex::raw::NoopRawMutex;
20use embassy_sync::blocking_mutex::Mutex; 19use embassy_sync::blocking_mutex::Mutex;
20use embassy_sync::blocking_mutex::raw::NoopRawMutex;
21use embassy_time::{Delay, Duration, Timer}; 21use embassy_time::{Delay, Duration, Timer};
22use embedded_graphics::image::{Image, ImageRawLE}; 22use embedded_graphics::image::{Image, ImageRawLE};
23use embedded_graphics::pixelcolor::Rgb565; 23use embedded_graphics::pixelcolor::Rgb565;
24use embedded_graphics::prelude::*; 24use embedded_graphics::prelude::*;
25use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; 25use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
26use mipidsi::Builder;
26use mipidsi::models::GC9A01; 27use mipidsi::models::GC9A01;
27use mipidsi::options::{ColorInversion, ColorOrder}; 28use mipidsi::options::{ColorInversion, ColorOrder};
28use mipidsi::Builder;
29use {defmt_rtt as _, panic_probe as _}; 29use {defmt_rtt as _, panic_probe as _};
30 30
31const DISPLAY_FREQ: u32 = 64_000_000; 31const DISPLAY_FREQ: u32 = 64_000_000;
diff --git a/examples/rp/src/bin/uart_r503.rs b/examples/rp/src/bin/uart_r503.rs
index 085be280b..a25d45b18 100644
--- a/examples/rp/src/bin/uart_r503.rs
+++ b/examples/rp/src/bin/uart_r503.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_rp::bind_interrupts; 6use embassy_rp::bind_interrupts;
7use embassy_rp::peripherals::UART0; 7use embassy_rp::peripherals::UART0;
8use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; 8use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart};
9use embassy_time::{with_timeout, Duration, Timer}; 9use embassy_time::{Duration, Timer, with_timeout};
10use heapless::Vec; 10use heapless::Vec;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 912e52e96..b62a602b1 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -7,8 +7,8 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_net::tcp::TcpSocket;
11use embassy_net::StackResources; 10use embassy_net::StackResources;
11use embassy_net::tcp::TcpSocket;
12use embassy_rp::clocks::RoscRng; 12use embassy_rp::clocks::RoscRng;
13use embassy_rp::peripherals::USB; 13use embassy_rp::peripherals::USB;
14use embassy_rp::usb::{Driver, InterruptHandler}; 14use embassy_rp::usb::{Driver, InterruptHandler};
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index a7cb322d8..2f6d169bf 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -1,7 +1,7 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Input, Pull}; 10use embassy_rp::gpio::{Input, Pull};
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver, InterruptHandler}; 12use embassy_rp::usb::{Driver, InterruptHandler};
13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
15};
14use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Config, Handler}; 17use embassy_usb::{Builder, Config, Handler};
16use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 18use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
@@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs {
20 USBCTRL_IRQ => InterruptHandler<USB>; 22 USBCTRL_IRQ => InterruptHandler<USB>;
21}); 23});
22 24
25static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
26
23#[embassy_executor::main] 27#[embassy_executor::main]
24async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
25 let p = embassy_rp::init(Default::default()); 29 let p = embassy_rp::init(Default::default());
@@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) {
33 config.serial_number = Some("12345678"); 37 config.serial_number = Some("12345678");
34 config.max_power = 100; 38 config.max_power = 100;
35 config.max_packet_size_0 = 64; 39 config.max_packet_size_0 = 64;
40 config.composite_with_iads = false;
41 config.device_class = 0;
42 config.device_sub_class = 0;
43 config.device_protocol = 0;
36 44
37 // Create embassy-usb DeviceBuilder using the driver and config. 45 // Create embassy-usb DeviceBuilder using the driver and config.
38 // It needs some buffers for building the descriptors. 46 // It needs some buffers for building the descriptors.
@@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) {
63 request_handler: None, 71 request_handler: None,
64 poll_ms: 60, 72 poll_ms: 60,
65 max_packet_size: 64, 73 max_packet_size: 64,
74 hid_subclass: HidSubclass::Boot,
75 hid_boot_protocol: HidBootProtocol::Keyboard,
66 }; 76 };
67 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); 77 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
68 78
@@ -86,30 +96,46 @@ async fn main(_spawner: Spawner) {
86 info!("Waiting for HIGH on pin 16"); 96 info!("Waiting for HIGH on pin 16");
87 signal_pin.wait_for_high().await; 97 signal_pin.wait_for_high().await;
88 info!("HIGH DETECTED"); 98 info!("HIGH DETECTED");
89 // Create a report with the A key pressed. (no shift modifier) 99
90 let report = KeyboardReport { 100 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
91 keycodes: [4, 0, 0, 0, 0, 0], 101 match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
92 leds: 0, 102 Ok(()) => {}
93 modifier: 0, 103 Err(e) => warn!("Failed to send boot report: {:?}", e),
94 reserved: 0, 104 };
95 }; 105 } else {
96 // Send the report. 106 // Create a report with the A key pressed. (no shift modifier)
97 match writer.write_serialize(&report).await { 107 let report = KeyboardReport {
98 Ok(()) => {} 108 keycodes: [4, 0, 0, 0, 0, 0],
99 Err(e) => warn!("Failed to send report: {:?}", e), 109 leds: 0,
100 }; 110 modifier: 0,
111 reserved: 0,
112 };
113 // Send the report.
114 match writer.write_serialize(&report).await {
115 Ok(()) => {}
116 Err(e) => warn!("Failed to send report: {:?}", e),
117 };
118 }
119
101 signal_pin.wait_for_low().await; 120 signal_pin.wait_for_low().await;
102 info!("LOW DETECTED"); 121 info!("LOW DETECTED");
103 let report = KeyboardReport { 122 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
104 keycodes: [0, 0, 0, 0, 0, 0], 123 match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
105 leds: 0, 124 Ok(()) => {}
106 modifier: 0, 125 Err(e) => warn!("Failed to send boot report: {:?}", e),
107 reserved: 0, 126 };
108 }; 127 } else {
109 match writer.write_serialize(&report).await { 128 let report = KeyboardReport {
110 Ok(()) => {} 129 keycodes: [0, 0, 0, 0, 0, 0],
111 Err(e) => warn!("Failed to send report: {:?}", e), 130 leds: 0,
112 }; 131 modifier: 0,
132 reserved: 0,
133 };
134 match writer.write_serialize(&report).await {
135 Ok(()) => {}
136 Err(e) => warn!("Failed to send report: {:?}", e),
137 };
138 }
113 } 139 }
114 }; 140 };
115 141
@@ -135,6 +161,18 @@ impl RequestHandler for MyRequestHandler {
135 OutResponse::Accepted 161 OutResponse::Accepted
136 } 162 }
137 163
164 fn get_protocol(&self) -> HidProtocolMode {
165 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
166 info!("The current HID protocol mode is: {}", protocol);
167 protocol
168 }
169
170 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
171 info!("Switching to HID protocol mode: {}", protocol);
172 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
173 OutResponse::Accepted
174 }
175
138 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 176 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
139 info!("Set idle rate for {:?} to {:?}", id, dur); 177 info!("Set idle rate for {:?} to {:?}", id, dur);
140 } 178 }
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs
index 4454c593c..dc331cbdd 100755
--- a/examples/rp/src/bin/usb_hid_mouse.rs
+++ b/examples/rp/src/bin/usb_hid_mouse.rs
@@ -1,7 +1,7 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -11,7 +11,9 @@ use embassy_rp::clocks::RoscRng;
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::Timer; 13use embassy_time::Timer;
14use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
16};
15use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
16use embassy_usb::{Builder, Config, Handler}; 18use embassy_usb::{Builder, Config, Handler};
17use rand::Rng; 19use rand::Rng;
@@ -22,6 +24,8 @@ bind_interrupts!(struct Irqs {
22 USBCTRL_IRQ => InterruptHandler<USB>; 24 USBCTRL_IRQ => InterruptHandler<USB>;
23}); 25});
24 26
27static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
28
25#[embassy_executor::main] 29#[embassy_executor::main]
26async fn main(_spawner: Spawner) { 30async fn main(_spawner: Spawner) {
27 let p = embassy_rp::init(Default::default()); 31 let p = embassy_rp::init(Default::default());
@@ -35,6 +39,10 @@ async fn main(_spawner: Spawner) {
35 config.serial_number = Some("12345678"); 39 config.serial_number = Some("12345678");
36 config.max_power = 100; 40 config.max_power = 100;
37 config.max_packet_size_0 = 64; 41 config.max_packet_size_0 = 64;
42 config.composite_with_iads = false;
43 config.device_class = 0;
44 config.device_sub_class = 0;
45 config.device_protocol = 0;
38 46
39 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
40 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
@@ -65,6 +73,8 @@ async fn main(_spawner: Spawner) {
65 request_handler: None, 73 request_handler: None,
66 poll_ms: 60, 74 poll_ms: 60,
67 max_packet_size: 64, 75 max_packet_size: 64,
76 hid_subclass: HidSubclass::Boot,
77 hid_boot_protocol: HidBootProtocol::Mouse,
68 }; 78 };
69 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); 79 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
70 80
@@ -83,17 +93,29 @@ async fn main(_spawner: Spawner) {
83 loop { 93 loop {
84 // every 1 second 94 // every 1 second
85 _ = Timer::after_secs(1).await; 95 _ = Timer::after_secs(1).await;
86 let report = MouseReport { 96
87 buttons: 0, 97 let x = rng.random_range(-100..100); // random small x movement
88 x: rng.random_range(-100..100), // random small x movement 98 let y = rng.random_range(-100..100); // random small y movement
89 y: rng.random_range(-100..100), // random small y movement 99
90 wheel: 0, 100 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
91 pan: 0, 101 let buttons = 0u8;
92 }; 102 match writer.write(&[buttons, x as u8, y as u8]).await {
93 // Send the report. 103 Ok(()) => {}
94 match writer.write_serialize(&report).await { 104 Err(e) => warn!("Failed to send boot report: {:?}", e),
95 Ok(()) => {} 105 }
96 Err(e) => warn!("Failed to send report: {:?}", e), 106 } else {
107 let report = MouseReport {
108 buttons: 0,
109 x,
110 y,
111 wheel: 0,
112 pan: 0,
113 };
114 // Send the report.
115 match writer.write_serialize(&report).await {
116 Ok(()) => {}
117 Err(e) => warn!("Failed to send report: {:?}", e),
118 }
97 } 119 }
98 } 120 }
99 }; 121 };
@@ -120,6 +142,18 @@ impl RequestHandler for MyRequestHandler {
120 OutResponse::Accepted 142 OutResponse::Accepted
121 } 143 }
122 144
145 fn get_protocol(&self) -> HidProtocolMode {
146 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
147 info!("The current HID protocol mode is: {}", protocol);
148 protocol
149 }
150
151 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
152 info!("Switching to HID protocol mode: {}", protocol);
153 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
154 OutResponse::Accepted
155 }
156
123 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 157 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
124 info!("Set idle rate for {:?} to {:?}", id, dur); 158 info!("Set idle rate for {:?} to {:?}", id, dur);
125 } 159 }
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index b79012acb..23d0c9e8b 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -10,9 +10,9 @@ 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, Instance, InterruptHandler}; 12use embassy_rp::usb::{Driver, Instance, InterruptHandler};
13use embassy_usb::UsbDevice;
13use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 14use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
14use embassy_usb::driver::EndpointError; 15use embassy_usb::driver::EndpointError;
15use embassy_usb::UsbDevice;
16use static_cell::StaticCell; 16use static_cell::StaticCell;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs
index 128599e0d..0828dbbb9 100644
--- a/examples/rp/src/bin/wifi_ap_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs
@@ -7,7 +7,7 @@
7 7
8use core::str::from_utf8; 8use core::str::from_utf8;
9 9
10use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; 10use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
11use defmt::*; 11use defmt::*;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_net::tcp::TcpSocket; 13use embassy_net::tcp::TcpSocket;
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs
index b2e08c517..aa6ee4df0 100644
--- a/examples/rp/src/bin/wifi_blinky.rs
+++ b/examples/rp/src/bin/wifi_blinky.rs
@@ -5,7 +5,7 @@
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7 7
8use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; 8use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::bind_interrupts; 11use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs
index c884aa2ba..7e3de1db9 100644
--- a/examples/rp/src/bin/wifi_scan.rs
+++ b/examples/rp/src/bin/wifi_scan.rs
@@ -7,7 +7,7 @@
7 7
8use core::str; 8use core::str;
9 9
10use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; 10use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
11use defmt::*; 11use defmt::*;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_rp::bind_interrupts; 13use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs
index 126475779..ef8d08b76 100644
--- a/examples/rp/src/bin/wifi_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_tcp_server.rs
@@ -8,7 +8,7 @@
8use core::str::from_utf8; 8use core::str::from_utf8;
9 9
10use cyw43::JoinOptions; 10use cyw43::JoinOptions;
11use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; 11use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
12use defmt::*; 12use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_net::tcp::TcpSocket; 14use embassy_net::tcp::TcpSocket;
@@ -101,7 +101,7 @@ async fn main(spawner: Spawner) {
101 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) 101 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
102 .await 102 .await
103 { 103 {
104 info!("join failed with status={}", err.status); 104 info!("join failed: {:?}", err);
105 } 105 }
106 106
107 info!("waiting for link..."); 107 info!("waiting for link...");
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs
index 079def370..069afc794 100644
--- a/examples/rp/src/bin/wifi_webrequest.rs
+++ b/examples/rp/src/bin/wifi_webrequest.rs
@@ -1,14 +1,13 @@
1//! This example uses the RP Pico W board Wifi chip (cyw43). 1//! This example uses the RP Pico W board Wifi chip (cyw43).
2//! Connects to Wifi network and makes a web request to get the current time. 2//! Connects to Wifi network and makes a web request to httpbin.org.
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![allow(async_fn_in_trait)]
7 6
8use core::str::from_utf8; 7use core::str::from_utf8;
9 8
10use cyw43::JoinOptions; 9use cyw43::JoinOptions;
11use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER}; 10use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
12use defmt::*; 11use defmt::*;
13use embassy_executor::Spawner; 12use embassy_executor::Spawner;
14use embassy_net::dns::DnsSocket; 13use embassy_net::dns::DnsSocket;
@@ -20,11 +19,14 @@ use embassy_rp::gpio::{Level, Output};
20use embassy_rp::peripherals::{DMA_CH0, PIO0}; 19use embassy_rp::peripherals::{DMA_CH0, PIO0};
21use embassy_rp::pio::{InterruptHandler, Pio}; 20use embassy_rp::pio::{InterruptHandler, Pio};
22use embassy_time::{Duration, Timer}; 21use embassy_time::{Duration, Timer};
23use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; 22use reqwless::client::HttpClient;
23// Uncomment these for TLS requests:
24// use reqwless::client::{HttpClient, TlsConfig, TlsVerify};
24use reqwless::request::Method; 25use reqwless::request::Method;
25use serde::Deserialize; 26use serde::Deserialize;
27use serde_json_core::from_slice;
26use static_cell::StaticCell; 28use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _, serde_json_core}; 29use {defmt_rtt as _, panic_probe as _};
28 30
29bind_interrupts!(struct Irqs { 31bind_interrupts!(struct Irqs {
30 PIO0_IRQ_0 => InterruptHandler<PIO0>; 32 PIO0_IRQ_0 => InterruptHandler<PIO0>;
@@ -104,7 +106,7 @@ async fn main(spawner: Spawner) {
104 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) 106 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
105 .await 107 .await
106 { 108 {
107 info!("join failed with status={}", err.status); 109 info!("join failed: {:?}", err);
108 } 110 }
109 111
110 info!("waiting for link..."); 112 info!("waiting for link...");
@@ -119,64 +121,90 @@ async fn main(spawner: Spawner) {
119 // And now we can use it! 121 // And now we can use it!
120 122
121 loop { 123 loop {
122 let mut rx_buffer = [0; 8192]; 124 let mut rx_buffer = [0; 4096];
123 let mut tls_read_buffer = [0; 16640]; 125 // Uncomment these for TLS requests:
124 let mut tls_write_buffer = [0; 16640]; 126 // let mut tls_read_buffer = [0; 16640];
127 // let mut tls_write_buffer = [0; 16640];
125 128
126 let client_state = TcpClientState::<1, 1024, 1024>::new(); 129 let client_state = TcpClientState::<1, 4096, 4096>::new();
127 let tcp_client = TcpClient::new(stack, &client_state); 130 let tcp_client = TcpClient::new(stack, &client_state);
128 let dns_client = DnsSocket::new(stack); 131 let dns_client = DnsSocket::new(stack);
129 let tls_config = TlsConfig::new(seed, &mut tls_read_buffer, &mut tls_write_buffer, TlsVerify::None); 132 // Uncomment these for TLS requests:
133 // let tls_config = TlsConfig::new(seed, &mut tls_read_buffer, &mut tls_write_buffer, TlsVerify::None);
130 134
131 let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config); 135 // Using non-TLS HTTP for this example
132 let url = "https://worldtimeapi.org/api/timezone/Europe/Berlin"; 136 let mut http_client = HttpClient::new(&tcp_client, &dns_client);
133 // for non-TLS requests, use this instead: 137 let url = "http://httpbin.org/json";
134 // let mut http_client = HttpClient::new(&tcp_client, &dns_client); 138 // For TLS requests, use this instead:
135 // let url = "http://worldtimeapi.org/api/timezone/Europe/Berlin"; 139 // let mut http_client = HttpClient::new_with_tls(&tcp_client, &dns_client, tls_config);
140 // let url = "https://httpbin.org/json";
136 141
137 info!("connecting to {}", &url); 142 info!("connecting to {}", &url);
138 143
139 let mut request = match http_client.request(Method::GET, &url).await { 144 let mut request = match http_client.request(Method::GET, url).await {
140 Ok(req) => req, 145 Ok(req) => req,
141 Err(e) => { 146 Err(e) => {
142 error!("Failed to make HTTP request: {:?}", e); 147 error!("Failed to make HTTP request: {:?}", e);
143 return; // handle the error 148 Timer::after(Duration::from_secs(5)).await;
149 continue;
144 } 150 }
145 }; 151 };
146 152
147 let response = match request.send(&mut rx_buffer).await { 153 let response = match request.send(&mut rx_buffer).await {
148 Ok(resp) => resp, 154 Ok(resp) => resp,
149 Err(_e) => { 155 Err(e) => {
150 error!("Failed to send HTTP request"); 156 error!("Failed to send HTTP request: {:?}", e);
151 return; // handle the error; 157 Timer::after(Duration::from_secs(5)).await;
158 continue;
152 } 159 }
153 }; 160 };
154 161
155 let body = match from_utf8(response.body().read_to_end().await.unwrap()) { 162 info!("Response status: {}", response.status.0);
163
164 let body_bytes = match response.body().read_to_end().await {
156 Ok(b) => b, 165 Ok(b) => b,
157 Err(_e) => { 166 Err(_e) => {
158 error!("Failed to read response body"); 167 error!("Failed to read response body");
159 return; // handle the error 168 Timer::after(Duration::from_secs(5)).await;
169 continue;
170 }
171 };
172
173 let body = match from_utf8(body_bytes) {
174 Ok(b) => b,
175 Err(_e) => {
176 error!("Failed to parse response body as UTF-8");
177 Timer::after(Duration::from_secs(5)).await;
178 continue;
160 } 179 }
161 }; 180 };
162 info!("Response body: {:?}", &body); 181 info!("Response body length: {} bytes", body.len());
163 182
164 // parse the response body and update the RTC 183 // Parse the JSON response from httpbin.org/json
184 #[derive(Deserialize)]
185 struct SlideShow<'a> {
186 author: &'a str,
187 title: &'a str,
188 }
165 189
166 #[derive(Deserialize)] 190 #[derive(Deserialize)]
167 struct ApiResponse<'a> { 191 struct HttpBinResponse<'a> {
168 datetime: &'a str, 192 #[serde(borrow)]
169 // other fields as needed 193 slideshow: SlideShow<'a>,
170 } 194 }
171 195
172 let bytes = body.as_bytes(); 196 let bytes = body.as_bytes();
173 match serde_json_core::de::from_slice::<ApiResponse>(bytes) { 197 match from_slice::<HttpBinResponse>(bytes) {
174 Ok((output, _used)) => { 198 Ok((output, _used)) => {
175 info!("Datetime: {:?}", output.datetime); 199 info!("Successfully parsed JSON response!");
200 info!("Slideshow title: {:?}", output.slideshow.title);
201 info!("Slideshow author: {:?}", output.slideshow.author);
176 } 202 }
177 Err(_e) => { 203 Err(e) => {
178 error!("Failed to parse response body"); 204 error!("Failed to parse JSON response: {}", Debug2Format(&e));
179 return; // handle the error 205 // Log preview of response for debugging
206 let preview = if body.len() > 200 { &body[..200] } else { body };
207 info!("Response preview: {:?}", preview);
180 } 208 }
181 } 209 }
182 210
diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs
index d603e1ed3..fc5f95e6e 100644
--- a/examples/rp/src/bin/zerocopy.rs
+++ b/examples/rp/src/bin/zerocopy.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; 11use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler};
12use embassy_rp::gpio::Pull; 12use embassy_rp::gpio::Pull;
13use embassy_rp::peripherals::DMA_CH0; 13use embassy_rp::peripherals::DMA_CH0;
14use embassy_rp::{bind_interrupts, Peri}; 14use embassy_rp::{Peri, bind_interrupts};
15use embassy_sync::blocking_mutex::raw::NoopRawMutex; 15use embassy_sync::blocking_mutex::raw::NoopRawMutex;
16use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; 16use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender};
17use embassy_time::{Duration, Ticker, Timer}; 17use embassy_time::{Duration, Ticker, Timer};
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml
index 40fbb5798..16dfb5b77 100644
--- a/examples/rp235x/Cargo.toml
+++ b/examples/rp235x/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-rp2350-examples" 3name = "embassy-rp2350-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -11,14 +11,14 @@ embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal",
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
14embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } 14embassy-rp = { version = "0.9.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } 16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] }
17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] } 17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] }
18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" } 19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" }
20cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } 20cyw43 = { version = "0.6.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] }
21cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] } 21cyw43-pio = { version = "0.9.0", path = "../../cyw43-pio", features = ["defmt"] }
22 22
23defmt = "1.0.1" 23defmt = "1.0.1"
24defmt-rtt = "1.0.0" 24defmt-rtt = "1.0.0"
@@ -46,7 +46,7 @@ display-interface = "0.5.0"
46byte-slice-cast = { version = "1.2.0", default-features = false } 46byte-slice-cast = { version = "1.2.0", default-features = false }
47smart-leds = "0.3.0" 47smart-leds = "0.3.0"
48heapless = "0.8" 48heapless = "0.8"
49usbd-hid = "0.8.1" 49usbd-hid = "0.9.0"
50 50
51embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 51embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
52embedded-hal-async = "1.0" 52embedded-hal-async = "1.0"
diff --git a/examples/rp235x/src/bin/assign_resources.rs b/examples/rp235x/src/bin/assign_resources.rs
index 4ee4278b5..aaa134768 100644
--- a/examples/rp235x/src/bin/assign_resources.rs
+++ b/examples/rp235x/src/bin/assign_resources.rs
@@ -14,9 +14,9 @@
14use assign_resources::assign_resources; 14use assign_resources::assign_resources;
15use defmt::*; 15use defmt::*;
16use embassy_executor::Spawner; 16use embassy_executor::Spawner;
17use embassy_rp::Peri;
17use embassy_rp::gpio::{Level, Output}; 18use embassy_rp::gpio::{Level, Output};
18use embassy_rp::peripherals::{self, PIN_20, PIN_21}; 19use embassy_rp::peripherals::{self, PIN_20, PIN_21};
19use embassy_rp::Peri;
20use embassy_time::Timer; 20use embassy_time::Timer;
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
22 22
diff --git a/examples/rp235x/src/bin/debounce.rs b/examples/rp235x/src/bin/debounce.rs
index 0077f19fc..6eeb01d0a 100644
--- a/examples/rp235x/src/bin/debounce.rs
+++ b/examples/rp235x/src/bin/debounce.rs
@@ -7,7 +7,7 @@
7use defmt::info; 7use defmt::info;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_rp::gpio::{Input, Level, Pull}; 9use embassy_rp::gpio::{Input, Level, Pull};
10use embassy_time::{with_deadline, Duration, Instant, Timer}; 10use embassy_time::{Duration, Instant, Timer, with_deadline};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13pub struct Debouncer<'a> { 13pub struct Debouncer<'a> {
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
index 309d3e4f7..227e68029 100644
--- a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
+++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
@@ -12,8 +12,8 @@ use core::str::FromStr;
12use defmt::*; 12use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_futures::yield_now; 14use embassy_futures::yield_now;
15use embassy_net::icmp::ping::{PingManager, PingParams};
16use embassy_net::icmp::PacketMetadata; 15use embassy_net::icmp::PacketMetadata;
16use embassy_net::icmp::ping::{PingManager, PingParams};
17use embassy_net::{Ipv4Cidr, Stack, StackResources}; 17use embassy_net::{Ipv4Cidr, Stack, StackResources};
18use embassy_net_wiznet::chip::W5500; 18use embassy_net_wiznet::chip::W5500;
19use embassy_net_wiznet::*; 19use embassy_net_wiznet::*;
@@ -99,7 +99,7 @@ async fn main(spawner: Spawner) {
99 // Create the ping manager instance 99 // Create the ping manager instance
100 let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); 100 let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
101 let addr = "192.168.8.1"; // Address to ping to 101 let addr = "192.168.8.1"; // Address to ping to
102 // Create the PingParams with the target address 102 // Create the PingParams with the target address
103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap()); 103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap());
104 // (optional) Set custom properties of the ping 104 // (optional) Set custom properties of the ping
105 ping_params.set_payload(b"Hello, Ping!"); // custom payload 105 ping_params.set_payload(b"Hello, Ping!"); // custom payload
diff --git a/examples/rp235x/src/bin/interrupt.rs b/examples/rp235x/src/bin/interrupt.rs
index 88513180c..1b18f6931 100644
--- a/examples/rp235x/src/bin/interrupt.rs
+++ b/examples/rp235x/src/bin/interrupt.rs
@@ -16,8 +16,8 @@ use embassy_rp::adc::{self, Adc, Blocking};
16use embassy_rp::gpio::Pull; 16use embassy_rp::gpio::Pull;
17use embassy_rp::interrupt; 17use embassy_rp::interrupt;
18use embassy_rp::pwm::{Config, Pwm}; 18use embassy_rp::pwm::{Config, Pwm};
19use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
20use embassy_sync::blocking_mutex::Mutex; 19use embassy_sync::blocking_mutex::Mutex;
20use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
21use embassy_sync::channel::Channel; 21use embassy_sync::channel::Channel;
22use embassy_time::{Duration, Ticker}; 22use embassy_time::{Duration, Ticker};
23use portable_atomic::{AtomicU32, Ordering}; 23use portable_atomic::{AtomicU32, Ordering};
diff --git a/examples/rp235x/src/bin/multicore.rs b/examples/rp235x/src/bin/multicore.rs
index 4f82801d6..9b61fdbca 100644
--- a/examples/rp235x/src/bin/multicore.rs
+++ b/examples/rp235x/src/bin/multicore.rs
@@ -8,7 +8,7 @@
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_rp::gpio::{Level, Output}; 10use embassy_rp::gpio::{Level, Output};
11use embassy_rp::multicore::{spawn_core1, Stack}; 11use embassy_rp::multicore::{Stack, spawn_core1};
12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
13use embassy_sync::channel::Channel; 13use embassy_sync::channel::Channel;
14use embassy_time::Timer; 14use embassy_time::Timer;
diff --git a/examples/rp235x/src/bin/multicore_stack_overflow.rs b/examples/rp235x/src/bin/multicore_stack_overflow.rs
index dba44aa23..9efe89318 100644
--- a/examples/rp235x/src/bin/multicore_stack_overflow.rs
+++ b/examples/rp235x/src/bin/multicore_stack_overflow.rs
@@ -6,7 +6,7 @@
6use defmt::*; 6use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_rp::gpio::{Level, Output}; 8use embassy_rp::gpio::{Level, Output};
9use embassy_rp::multicore::{spawn_core1, Stack}; 9use embassy_rp::multicore::{Stack, spawn_core1};
10use embassy_time::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 _};
diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs
index 96cdf8fb1..310047505 100644
--- a/examples/rp235x/src/bin/multiprio.rs
+++ b/examples/rp235x/src/bin/multiprio.rs
@@ -61,7 +61,7 @@ use defmt::{info, unwrap};
61use embassy_executor::{Executor, InterruptExecutor}; 61use embassy_executor::{Executor, InterruptExecutor};
62use embassy_rp::interrupt; 62use embassy_rp::interrupt;
63use embassy_rp::interrupt::{InterruptExt, Priority}; 63use embassy_rp::interrupt::{InterruptExt, Priority};
64use embassy_time::{Instant, Timer, TICK_HZ}; 64use embassy_time::{Instant, TICK_HZ, Timer};
65use static_cell::StaticCell; 65use static_cell::StaticCell;
66use {defmt_rtt as _, panic_probe as _}; 66use {defmt_rtt as _, panic_probe as _};
67 67
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn SWI_IRQ_1() { 115unsafe fn SWI_IRQ_1() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn SWI_IRQ_0() { 120unsafe fn SWI_IRQ_0() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs
index 5fd97ef97..cba137f3a 100644
--- a/examples/rp235x/src/bin/overclock.rs
+++ b/examples/rp235x/src/bin/overclock.rs
@@ -12,7 +12,7 @@
12 12
13use defmt::*; 13use defmt::*;
14use embassy_executor::Spawner; 14use embassy_executor::Spawner;
15use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage}; 15use embassy_rp::clocks::{ClockConfig, CoreVoltage, clk_sys_freq, core_voltage};
16use embassy_rp::config::Config; 16use embassy_rp::config::Config;
17use embassy_rp::gpio::{Level, Output}; 17use embassy_rp::gpio::{Level, Output};
18use embassy_time::{Duration, Instant, Timer}; 18use embassy_time::{Duration, Instant, Timer};
diff --git a/examples/rp235x/src/bin/pio_async.rs b/examples/rp235x/src/bin/pio_async.rs
index d76930f5c..a392fe37e 100644
--- a/examples/rp235x/src/bin/pio_async.rs
+++ b/examples/rp235x/src/bin/pio_async.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_rp::peripherals::PIO0; 7use embassy_rp::peripherals::PIO0;
8use embassy_rp::pio::program::pio_asm; 8use embassy_rp::pio::program::pio_asm;
9use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; 9use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine};
10use embassy_rp::{bind_interrupts, Peri}; 10use embassy_rp::{Peri, bind_interrupts};
11use fixed::traits::ToFixed; 11use fixed::traits::ToFixed;
12use fixed_macro::types::U56F8; 12use fixed_macro::types::U56F8;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs
index cfcb0221d..7ed952a40 100644
--- a/examples/rp235x/src/bin/pio_i2s.rs
+++ b/examples/rp235x/src/bin/pio_i2s.rs
@@ -5,7 +5,7 @@
5//! bclk : GPIO 18 5//! bclk : GPIO 18
6//! lrc : GPIO 19 6//! lrc : GPIO 19
7//! din : GPIO 20 7//! din : GPIO 20
8//! Then hold down the boot select button to trigger a rising triangle waveform. 8//! Then short GPIO 0 to GND to trigger a rising triangle waveform.
9 9
10#![no_std] 10#![no_std]
11#![no_main] 11#![no_main]
@@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) {
70 // but don't await the returned future, yet 70 // but don't await the returned future, yet
71 let dma_future = i2s.write(front_buffer); 71 let dma_future = i2s.write(front_buffer);
72 72
73 // fade in audio when bootsel is pressed 73 // fade in audio when GPIO 0 pin is shorted to GND
74 let fade_target = if fade_input.is_low() { i32::MAX } else { 0 }; 74 let fade_target = if fade_input.is_low() { i32::MAX } else { 0 };
75 75
76 // fill back buffer with fresh audio samples before awaiting the dma future 76 // fill back buffer with fresh audio samples before awaiting the dma future
diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs
index c3f505b13..6735c402f 100644
--- a/examples/rp235x/src/bin/pio_i2s_rx.rs
+++ b/examples/rp235x/src/bin/pio_i2s_rx.rs
@@ -34,7 +34,7 @@ const SAMPLE_RATE: u32 = 48_000;
34const BIT_DEPTH: u32 = 16; 34const BIT_DEPTH: u32 = 16;
35const CHANNELS: u32 = 2; 35const CHANNELS: u32 = 2;
36const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor, 36const USE_ONBOARD_PULLDOWN: bool = false; // whether or not to use the onboard pull-down resistor,
37 // which has documented issues on many RP235x boards 37// which has documented issues on many RP235x boards
38#[embassy_executor::main] 38#[embassy_executor::main]
39async fn main(_spawner: Spawner) { 39async fn main(_spawner: Spawner) {
40 let p = embassy_rp::init(Default::default()); 40 let p = embassy_rp::init(Default::default());
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs
index 102f13c45..6432edb8a 100644
--- a/examples/rp235x/src/bin/pio_onewire.rs
+++ b/examples/rp235x/src/bin/pio_onewire.rs
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 let mut data = [0; 9]; 61 let mut data = [0; 9];
62 onewire.read_bytes(&mut data).await; 62 onewire.read_bytes(&mut data).await;
63 if crc8(&data) == 0 { 63 if crc8(&data) == 0 {
64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 64 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
65 info!("Read device {:x}: {} deg C", device, temp); 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else { 66 } else {
67 warn!("Reading device {:x} failed", device); 67 warn!("Reading device {:x} failed", device);
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs
index fd076dee0..78fb94b18 100644
--- a/examples/rp235x/src/bin/pio_onewire_parasite.rs
+++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 let mut data = [0; 9]; 63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await; 64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 { 65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.; 66 let temp = ((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp); 67 info!("Read device {:x}: {} deg C", device, temp);
68 } else { 68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data); 69 warn!("Reading device {:x} failed. {:02x}", device, data);
diff --git a/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs b/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs
index 61af94560..948699e40 100644
--- a/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs
+++ b/examples/rp235x/src/bin/pio_rotary_encoder_rxf.rs
@@ -9,7 +9,7 @@ use embassy_executor::Spawner;
9use embassy_rp::gpio::Pull; 9use embassy_rp::gpio::Pull;
10use embassy_rp::peripherals::PIO0; 10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::program::pio_asm; 11use embassy_rp::pio::program::pio_asm;
12use embassy_rp::{bind_interrupts, pio, Peri}; 12use embassy_rp::{Peri, bind_interrupts, pio};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use fixed::traits::ToFixed; 14use fixed::traits::ToFixed;
15use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; 15use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine};
diff --git a/examples/rp235x/src/bin/pio_stepper.rs b/examples/rp235x/src/bin/pio_stepper.rs
index 931adbeda..9b33710ad 100644
--- a/examples/rp235x/src/bin/pio_stepper.rs
+++ b/examples/rp235x/src/bin/pio_stepper.rs
@@ -10,7 +10,7 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::peripherals::PIO0; 10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{InterruptHandler, Pio}; 11use embassy_rp::pio::{InterruptHandler, Pio};
12use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram}; 12use embassy_rp::pio_programs::stepper::{PioStepper, PioStepperProgram};
13use embassy_time::{with_timeout, Duration, Timer}; 13use embassy_time::{Duration, Timer, with_timeout};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
diff --git a/examples/rp235x/src/bin/pwm.rs b/examples/rp235x/src/bin/pwm.rs
index 289480c85..971e86aa7 100644
--- a/examples/rp235x/src/bin/pwm.rs
+++ b/examples/rp235x/src/bin/pwm.rs
@@ -9,9 +9,9 @@
9 9
10use defmt::*; 10use defmt::*;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_rp::peripherals::{PIN_25, PIN_4, PWM_SLICE2, PWM_SLICE4};
13use embassy_rp::pwm::{Config, Pwm, SetDutyCycle};
14use embassy_rp::Peri; 12use embassy_rp::Peri;
13use embassy_rp::peripherals::{PIN_4, PIN_25, PWM_SLICE2, PWM_SLICE4};
14use embassy_rp::pwm::{Config, Pwm, SetDutyCycle};
15use embassy_time::Timer; 15use embassy_time::Timer;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
diff --git a/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs b/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs
index 2cfb2038d..670f302a4 100644
--- a/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs
+++ b/examples/rp235x/src/bin/pwm_tb6612fng_motor_driver.rs
@@ -10,7 +10,7 @@ use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::config::Config; 11use embassy_rp::config::Config;
12use embassy_rp::gpio::Output; 12use embassy_rp::gpio::Output;
13use embassy_rp::{gpio, peripherals, pwm, Peri}; 13use embassy_rp::{Peri, gpio, peripherals, pwm};
14use embassy_time::{Duration, Timer}; 14use embassy_time::{Duration, Timer};
15use tb6612fng::{DriveCommand, Motor, Tb6612fng}; 15use tb6612fng::{DriveCommand, Motor, Tb6612fng};
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs
index d4c89946b..618ab9117 100644
--- a/examples/rp235x/src/bin/sharing.rs
+++ b/examples/rp235x/src/bin/sharing.rs
@@ -52,7 +52,7 @@ bind_interrupts!(struct Irqs {
52 52
53#[interrupt] 53#[interrupt]
54unsafe fn SWI_IRQ_0() { 54unsafe fn SWI_IRQ_0() {
55 EXECUTOR_HI.on_interrupt() 55 unsafe { EXECUTOR_HI.on_interrupt() }
56} 56}
57 57
58#[entry] 58#[entry]
diff --git a/examples/rp235x/src/bin/spi_display.rs b/examples/rp235x/src/bin/spi_display.rs
index 9967abefd..3cef93f62 100644
--- a/examples/rp235x/src/bin/spi_display.rs
+++ b/examples/rp235x/src/bin/spi_display.rs
@@ -15,19 +15,19 @@ use embassy_executor::Spawner;
15use embassy_rp::gpio::{Level, Output}; 15use embassy_rp::gpio::{Level, Output};
16use embassy_rp::spi; 16use embassy_rp::spi;
17use embassy_rp::spi::{Blocking, Spi}; 17use embassy_rp::spi::{Blocking, Spi};
18use embassy_sync::blocking_mutex::raw::NoopRawMutex;
19use embassy_sync::blocking_mutex::Mutex; 18use embassy_sync::blocking_mutex::Mutex;
19use embassy_sync::blocking_mutex::raw::NoopRawMutex;
20use embassy_time::Delay; 20use embassy_time::Delay;
21use embedded_graphics::image::{Image, ImageRawLE}; 21use embedded_graphics::image::{Image, ImageRawLE};
22use embedded_graphics::mono_font::ascii::FONT_10X20;
23use embedded_graphics::mono_font::MonoTextStyle; 22use embedded_graphics::mono_font::MonoTextStyle;
23use embedded_graphics::mono_font::ascii::FONT_10X20;
24use embedded_graphics::pixelcolor::Rgb565; 24use embedded_graphics::pixelcolor::Rgb565;
25use embedded_graphics::prelude::*; 25use embedded_graphics::prelude::*;
26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; 26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
27use embedded_graphics::text::Text; 27use embedded_graphics::text::Text;
28use mipidsi::Builder;
28use mipidsi::models::ST7789; 29use mipidsi::models::ST7789;
29use mipidsi::options::{Orientation, Rotation}; 30use mipidsi::options::{Orientation, Rotation};
30use mipidsi::Builder;
31use {defmt_rtt as _, panic_probe as _}; 31use {defmt_rtt as _, panic_probe as _};
32 32
33use crate::touch::Touch; 33use crate::touch::Touch;
@@ -167,11 +167,7 @@ mod touch {
167 167
168 let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx); 168 let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx);
169 let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy); 169 let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy);
170 if x == 0 && y == 0 { 170 if x == 0 && y == 0 { None } else { Some((x, y)) }
171 None
172 } else {
173 Some((x, y))
174 }
175 } 171 }
176 } 172 }
177} 173}
diff --git a/examples/rp235x/src/bin/uart_r503.rs b/examples/rp235x/src/bin/uart_r503.rs
index 085be280b..a25d45b18 100644
--- a/examples/rp235x/src/bin/uart_r503.rs
+++ b/examples/rp235x/src/bin/uart_r503.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_rp::bind_interrupts; 6use embassy_rp::bind_interrupts;
7use embassy_rp::peripherals::UART0; 7use embassy_rp::peripherals::UART0;
8use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; 8use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart};
9use embassy_time::{with_timeout, Duration, Timer}; 9use embassy_time::{Duration, Timer, with_timeout};
10use heapless::Vec; 10use heapless::Vec;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/rp235x/src/bin/usb_hid_keyboard.rs b/examples/rp235x/src/bin/usb_hid_keyboard.rs
index 6f496e23a..d8f64c470 100644
--- a/examples/rp235x/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp235x/src/bin/usb_hid_keyboard.rs
@@ -1,7 +1,7 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
@@ -10,7 +10,9 @@ use embassy_rp::bind_interrupts;
10use embassy_rp::gpio::{Input, Pull}; 10use embassy_rp::gpio::{Input, Pull};
11use embassy_rp::peripherals::USB; 11use embassy_rp::peripherals::USB;
12use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler}; 12use embassy_rp::usb::{Driver as UsbDriver, InterruptHandler};
13use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State as HidState}; 13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State as HidState,
15};
14use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Config, Handler}; 17use embassy_usb::{Builder, Config, Handler};
16use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 18use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
@@ -20,6 +22,8 @@ bind_interrupts!(struct Irqs {
20 USBCTRL_IRQ => InterruptHandler<USB>; 22 USBCTRL_IRQ => InterruptHandler<USB>;
21}); 23});
22 24
25static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
26
23#[embassy_executor::main] 27#[embassy_executor::main]
24async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
25 let p = embassy_rp::init(Default::default()); 29 let p = embassy_rp::init(Default::default());
@@ -33,6 +37,10 @@ async fn main(_spawner: Spawner) {
33 config.serial_number = Some("12345678"); 37 config.serial_number = Some("12345678");
34 config.max_power = 100; 38 config.max_power = 100;
35 config.max_packet_size_0 = 64; 39 config.max_packet_size_0 = 64;
40 config.composite_with_iads = false;
41 config.device_class = 0;
42 config.device_sub_class = 0;
43 config.device_protocol = 0;
36 44
37 // Create embassy-usb DeviceBuilder using the driver and config. 45 // Create embassy-usb DeviceBuilder using the driver and config.
38 // It needs some buffers for building the descriptors. 46 // It needs some buffers for building the descriptors.
@@ -63,6 +71,8 @@ async fn main(_spawner: Spawner) {
63 request_handler: None, 71 request_handler: None,
64 poll_ms: 60, 72 poll_ms: 60,
65 max_packet_size: 64, 73 max_packet_size: 64,
74 hid_subclass: HidSubclass::Boot,
75 hid_boot_protocol: HidBootProtocol::Keyboard,
66 }; 76 };
67 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); 77 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
68 78
@@ -86,30 +96,45 @@ async fn main(_spawner: Spawner) {
86 info!("Waiting for HIGH on pin 16"); 96 info!("Waiting for HIGH on pin 16");
87 signal_pin.wait_for_high().await; 97 signal_pin.wait_for_high().await;
88 info!("HIGH DETECTED"); 98 info!("HIGH DETECTED");
89 // Create a report with the A key pressed. (no shift modifier) 99
90 let report = KeyboardReport { 100 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
91 keycodes: [4, 0, 0, 0, 0, 0], 101 match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
92 leds: 0, 102 Ok(()) => {}
93 modifier: 0, 103 Err(e) => warn!("Failed to send boot report: {:?}", e),
94 reserved: 0, 104 };
95 }; 105 } else {
96 // Send the report. 106 // Create a report with the A key pressed. (no shift modifier)
97 match writer.write_serialize(&report).await { 107 let report = KeyboardReport {
98 Ok(()) => {} 108 keycodes: [4, 0, 0, 0, 0, 0],
99 Err(e) => warn!("Failed to send report: {:?}", e), 109 leds: 0,
100 }; 110 modifier: 0,
111 reserved: 0,
112 };
113 // Send the report.
114 match writer.write_serialize(&report).await {
115 Ok(()) => {}
116 Err(e) => warn!("Failed to send report: {:?}", e),
117 };
118 }
101 signal_pin.wait_for_low().await; 119 signal_pin.wait_for_low().await;
102 info!("LOW DETECTED"); 120 info!("LOW DETECTED");
103 let report = KeyboardReport { 121 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
104 keycodes: [0, 0, 0, 0, 0, 0], 122 match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
105 leds: 0, 123 Ok(()) => {}
106 modifier: 0, 124 Err(e) => warn!("Failed to send boot report: {:?}", e),
107 reserved: 0, 125 };
108 }; 126 } else {
109 match writer.write_serialize(&report).await { 127 let report = KeyboardReport {
110 Ok(()) => {} 128 keycodes: [0, 0, 0, 0, 0, 0],
111 Err(e) => warn!("Failed to send report: {:?}", e), 129 leds: 0,
112 }; 130 modifier: 0,
131 reserved: 0,
132 };
133 match writer.write_serialize(&report).await {
134 Ok(()) => {}
135 Err(e) => warn!("Failed to send report: {:?}", e),
136 };
137 }
113 } 138 }
114 }; 139 };
115 140
@@ -135,6 +160,18 @@ impl RequestHandler for MyRequestHandler {
135 OutResponse::Accepted 160 OutResponse::Accepted
136 } 161 }
137 162
163 fn get_protocol(&self) -> HidProtocolMode {
164 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
165 info!("The current HID protocol mode is: {}", protocol);
166 protocol
167 }
168
169 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
170 info!("Switching to HID protocol mode: {}", protocol);
171 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
172 OutResponse::Accepted
173 }
174
138 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 175 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
139 info!("Set idle rate for {:?} to {:?}", id, dur); 176 info!("Set idle rate for {:?} to {:?}", id, dur);
140 } 177 }
diff --git a/examples/rp235x/src/bin/zerocopy.rs b/examples/rp235x/src/bin/zerocopy.rs
index 62ba4cfb8..55deffd5f 100644
--- a/examples/rp235x/src/bin/zerocopy.rs
+++ b/examples/rp235x/src/bin/zerocopy.rs
@@ -11,7 +11,7 @@ use embassy_executor::Spawner;
11use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler}; 11use embassy_rp::adc::{self, Adc, Async, Config, InterruptHandler};
12use embassy_rp::gpio::Pull; 12use embassy_rp::gpio::Pull;
13use embassy_rp::peripherals::DMA_CH0; 13use embassy_rp::peripherals::DMA_CH0;
14use embassy_rp::{bind_interrupts, Peri}; 14use embassy_rp::{Peri, bind_interrupts};
15use embassy_sync::blocking_mutex::raw::NoopRawMutex; 15use embassy_sync::blocking_mutex::raw::NoopRawMutex;
16use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender}; 16use embassy_sync::zerocopy_channel::{Channel, Receiver, Sender};
17use embassy_time::{Duration, Ticker, Timer}; 17use embassy_time::{Duration, Ticker, Timer};
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index 449c5ddca..6dc6a353d 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-std-examples" 3name = "embassy-std-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs
index 82272c798..685dbf3d3 100644
--- a/examples/std/src/bin/net_ppp.rs
+++ b/examples/std/src/bin/net_ppp.rs
@@ -52,7 +52,7 @@ async fn ppp_task(stack: Stack<'static>, mut runner: Runner<'static>, port: Seri
52 password: b"mypass", 52 password: b"mypass",
53 }; 53 };
54 54
55 runner 55 let r = runner
56 .run(port, config, |ipv4| { 56 .run(port, config, |ipv4| {
57 let Some(addr) = ipv4.address else { 57 let Some(addr) = ipv4.address else {
58 warn!("PPP did not provide an IP address."); 58 warn!("PPP did not provide an IP address.");
@@ -69,9 +69,10 @@ async fn ppp_task(stack: Stack<'static>, mut runner: Runner<'static>, port: Seri
69 }); 69 });
70 stack.set_config_v4(config); 70 stack.set_config_v4(config);
71 }) 71 })
72 .await 72 .await;
73 .unwrap(); 73 match r {
74 unreachable!() 74 Err(e) => panic!("{:?}", e),
75 }
75} 76}
76 77
77#[embassy_executor::task] 78#[embassy_executor::task]
diff --git a/examples/std/src/bin/tick_cancel.rs b/examples/std/src/bin/tick_cancel.rs
new file mode 100644
index 000000000..54e44790f
--- /dev/null
+++ b/examples/std/src/bin/tick_cancel.rs
@@ -0,0 +1,47 @@
1use std::sync::atomic::{AtomicBool, Ordering};
2use std::thread;
3use std::time::Duration;
4
5use embassy_executor::Executor;
6use embassy_time::Timer;
7use log::*;
8use static_cell::StaticCell;
9
10#[embassy_executor::task]
11async fn run() {
12 loop {
13 info!("tick");
14 Timer::after_secs(1).await;
15 }
16}
17
18static DONE: StaticCell<AtomicBool> = StaticCell::new();
19static EXECUTOR: StaticCell<Executor> = StaticCell::new();
20
21fn main() {
22 env_logger::builder()
23 .filter_level(log::LevelFilter::Debug)
24 .format_timestamp_nanos()
25 .init();
26
27 let done = DONE.init(AtomicBool::new(false));
28 let done_cb = || done.load(Ordering::Relaxed);
29
30 let server_thread = thread::spawn(move || {
31 let executor = EXECUTOR.init(Executor::new());
32 executor.run_until(
33 |spawner| {
34 spawner.spawn(run().unwrap());
35 },
36 done_cb,
37 );
38 info!("Executor finished");
39 });
40
41 thread::sleep(Duration::from_secs(5));
42
43 info!("Cancelling executor");
44 done.store(true, Ordering::Relaxed);
45
46 server_thread.join().unwrap();
47}
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index bb7b57496..696a95854 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32c0-examples" 3name = "embassy-stm32c0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32c0/src/bin/adc.rs b/examples/stm32c0/src/bin/adc.rs
index 1f54b0b18..ad597b63c 100644
--- a/examples/stm32c0/src/bin/adc.rs
+++ b/examples/stm32c0/src/bin/adc.rs
@@ -3,7 +3,6 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::vals::Scandir;
7use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime}; 6use embassy_stm32::adc::{Adc, AdcChannel, AnyAdcChannel, Resolution, SampleTime};
8use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
9use embassy_time::Timer; 8use embassy_time::Timer;
@@ -17,7 +16,7 @@ async fn main(_spawner: Spawner) {
17 info!("ADC STM32C0 example."); 16 info!("ADC STM32C0 example.");
18 17
19 // We need to set certain sample time to be able to read temp sensor. 18 // We need to set certain sample time to be able to read temp sensor.
20 let mut adc = Adc::new(p.ADC1, SampleTime::CYCLES12_5, Resolution::BITS12); 19 let mut adc = Adc::new(p.ADC1, Resolution::BITS12);
21 let mut temp = adc.enable_temperature().degrade_adc(); 20 let mut temp = adc.enable_temperature().degrade_adc();
22 let mut vref = adc.enable_vrefint().degrade_adc(); 21 let mut vref = adc.enable_vrefint().degrade_adc();
23 let mut pin0 = p.PA0.degrade_adc(); 22 let mut pin0 = p.PA0.degrade_adc();
@@ -27,16 +26,20 @@ async fn main(_spawner: Spawner) {
27 26
28 loop { 27 loop {
29 info!("============================"); 28 info!("============================");
30 let blocking_temp = adc.blocking_read(&mut temp); 29 let blocking_temp = adc.blocking_read(&mut temp, SampleTime::CYCLES12_5);
31 let blocking_vref = adc.blocking_read(&mut vref); 30 let blocking_vref = adc.blocking_read(&mut vref, SampleTime::CYCLES12_5);
32 let blocing_pin0 = adc.blocking_read(&mut pin0); 31 let blocing_pin0 = adc.blocking_read(&mut pin0, SampleTime::CYCLES12_5);
33 info!( 32 info!(
34 "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", 33 "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.",
35 blocking_vref, blocking_temp, blocing_pin0 34 blocking_vref, blocking_temp, blocing_pin0
36 ); 35 );
37 36
38 let channels_seqence: [&mut AnyAdcChannel<ADC1>; 3] = [&mut vref, &mut temp, &mut pin0]; 37 let channels_sequence: [(&mut AnyAdcChannel<ADC1>, SampleTime); 3] = [
39 adc.read(dma.reborrow(), channels_seqence.into_iter(), &mut read_buffer) 38 (&mut vref, SampleTime::CYCLES12_5),
39 (&mut temp, SampleTime::CYCLES12_5),
40 (&mut pin0, SampleTime::CYCLES12_5),
41 ];
42 adc.read(dma.reborrow(), channels_sequence.into_iter(), &mut read_buffer)
40 .await; 43 .await;
41 // Values are ordered according to hardware ADC channel number! 44 // Values are ordered according to hardware ADC channel number!
42 info!( 45 info!(
@@ -44,15 +47,6 @@ async fn main(_spawner: Spawner) {
44 read_buffer[0], read_buffer[1], read_buffer[2] 47 read_buffer[0], read_buffer[1], read_buffer[2]
45 ); 48 );
46 49
47 let hw_channel_selection: u32 =
48 (1 << temp.get_hw_channel()) + (1 << vref.get_hw_channel()) + (1 << pin0.get_hw_channel());
49 adc.read_in_hw_order(dma.reborrow(), hw_channel_selection, Scandir::UP, &mut read_buffer)
50 .await;
51 info!(
52 "DMA ADC read in hardware order: vref = {}, temp = {}, pin0 = {}.",
53 read_buffer[2], read_buffer[1], read_buffer[0]
54 );
55
56 Timer::after_millis(2000).await; 50 Timer::after_millis(2000).await;
57 } 51 }
58} 52}
diff --git a/examples/stm32c0/src/bin/button_exti.rs b/examples/stm32c0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32c0/src/bin/button_exti.rs
+++ b/examples/stm32c0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs
index 82d8a37ba..5ff705ca2 100644
--- a/examples/stm32c0/src/bin/rtc.rs
+++ b/examples/stm32c0/src/bin/rtc.rs
@@ -4,8 +4,8 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rtc::{Rtc, RtcConfig};
8use embassy_stm32::Config; 7use embassy_stm32::Config;
8use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 11ecbe3c2..177dd0ac2 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -1,7 +1,7 @@
1[package] 1[package]
2name = "embassy-stm32f0-examples" 2name = "embassy-stm32f0-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2024"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
@@ -16,6 +16,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
16embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 16embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
17embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 17embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
18embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 18embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
19embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
19static_cell = "2" 20static_cell = "2"
20portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 21portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
21 22
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs
index ff98aac8e..6879dd10a 100644
--- a/examples/stm32f0/src/bin/adc-watchdog.rs
+++ b/examples/stm32f0/src/bin/adc-watchdog.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{self, Adc, WatchdogChannels}; 6use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels};
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::peripherals::ADC1; 8use embassy_stm32::peripherals::ADC1;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
@@ -23,12 +23,12 @@ async fn main(_spawner: Spawner) {
23 loop { 23 loop {
24 // Wait for pin to go high 24 // Wait for pin to go high
25 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); 25 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F);
26 let v_high = adc.monitor_watchdog().await; 26 let v_high = adc.monitor_watchdog(SampleTime::CYCLES13_5).await;
27 info!("ADC sample is high {}", v_high); 27 info!("ADC sample is high {}", v_high);
28 28
29 // Wait for pin to go low 29 // Wait for pin to go low
30 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); 30 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF);
31 let v_low = adc.monitor_watchdog().await; 31 let v_low = adc.monitor_watchdog(SampleTime::CYCLES13_5).await;
32 info!("ADC sample is low {}", v_low); 32 info!("ADC sample is low {}", v_low);
33 } 33 }
34} 34}
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs
index 8825e2687..fafeeffaf 100644
--- a/examples/stm32f0/src/bin/adc.rs
+++ b/examples/stm32f0/src/bin/adc.rs
@@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) {
19 info!("Hello World!"); 19 info!("Hello World!");
20 20
21 let mut adc = Adc::new(p.ADC1, Irqs); 21 let mut adc = Adc::new(p.ADC1, Irqs);
22 adc.set_sample_time(SampleTime::CYCLES71_5);
23 let mut pin = p.PA1; 22 let mut pin = p.PA1;
24 23
25 let mut vrefint = adc.enable_vref(); 24 let mut vrefint = adc.enable_vref();
26 let vrefint_sample = adc.read(&mut vrefint).await; 25 let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await;
27 let convert_to_millivolts = |sample| { 26 let convert_to_millivolts = |sample| {
28 // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf 27 // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf
29 // 6.3.4 Embedded reference voltage 28 // 6.3.4 Embedded reference voltage
@@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) {
33 }; 32 };
34 33
35 loop { 34 loop {
36 let v = adc.read(&mut pin).await; 35 let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await;
37 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 36 info!("--> {} - {} mV", v, convert_to_millivolts(v));
38 Timer::after_millis(100).await; 37 Timer::after_millis(100).await;
39 } 38 }
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs
index f232e3290..9c7bf8a95 100644
--- a/examples/stm32f0/src/bin/button_controlled_blink.rs
+++ b/examples/stm32f0/src/bin/button_controlled_blink.rs
@@ -7,14 +7,19 @@ use core::sync::atomic::{AtomicU32, Ordering};
7 7
8use defmt::info; 8use defmt::info;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed};
12use embassy_stm32::Peri; 12use embassy_stm32::{Peri, bind_interrupts, interrupt};
13use embassy_time::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);
17 17
18bind_interrupts!(
19 pub struct Irqs{
20 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
21});
22
18#[embassy_executor::task] 23#[embassy_executor::task]
19async fn led_task(led: Peri<'static, AnyPin>) { 24async fn led_task(led: Peri<'static, AnyPin>) {
20 // Configure the LED pin as a push pull output and obtain handler. 25 // Configure the LED pin as a push pull output and obtain handler.
@@ -37,7 +42,7 @@ async fn main(spawner: Spawner) {
37 42
38 // Configure the button pin and obtain handler. 43 // Configure the button pin and obtain handler.
39 // On the Nucleo F091RC there is a button connected to pin PC13. 44 // On the Nucleo F091RC there is a button connected to pin PC13.
40 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None); 45 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None, Irqs);
41 46
42 // Create and initialize a delay variable to manage delay loop 47 // Create and initialize a delay variable to manage delay loop
43 let mut del_var = 2000; 48 let mut del_var = 2000;
diff --git a/examples/stm32f0/src/bin/button_exti.rs b/examples/stm32f0/src/bin/button_exti.rs
index fd615a215..d1312e1be 100644
--- a/examples/stm32f0/src/bin/button_exti.rs
+++ b/examples/stm32f0/src/bin/button_exti.rs
@@ -3,17 +3,23 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 // Initialize and create handle for devicer peripherals 18 // Initialize and create handle for devicer peripherals
13 let p = embassy_stm32::init(Default::default()); 19 let p = embassy_stm32::init(Default::default());
14 // Configure the button pin and obtain handler. 20 // Configure the button pin and obtain handler.
15 // On the Nucleo F091RC there is a button connected to pin PC13. 21 // On the Nucleo F091RC there is a button connected to pin PC13.
16 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 22 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
17 23
18 info!("Press the USER button..."); 24 info!("Press the USER button...");
19 loop { 25 loop {
diff --git a/examples/stm32f0/src/bin/i2c_master.rs b/examples/stm32f0/src/bin/i2c_master.rs
new file mode 100644
index 000000000..2e61ecdf7
--- /dev/null
+++ b/examples/stm32f0/src/bin/i2c_master.rs
@@ -0,0 +1,609 @@
1#![no_std]
2#![no_main]
3
4// Hardware Setup for NUCLEO-F072RB:
5// - I2C1 pins: PB8 (SCL), PB9 (SDA) on CN5 connector
6// - Connect to I2C slave device (e.g., Digilent Analog Discovery I2C slave, or EEPROM)
7// - Default slave address: 0x50
8// - Pull-up resistors: 4.7kΩ on both SCL and SDA
9// - CN5 Pin 10 (PB8/SCL) and CN5 Pin 9 (PB9/SDA)
10//
11// Analog Discovery - Waveforms Setup:
12// - Increase buffer size: Settings -> Device Manager -> Option 4
13// - Run Protocol Analyzer
14// - Configure as I2C Slave at address 0x50
15// - Connect and configure DIO pins for SCL and SDA
16// - Frequency: 100kHz - [✓] Clock Stretching
17
18use defmt::*;
19use embassy_executor::Spawner;
20use embassy_stm32::i2c::{Config, I2c, Master};
21use embassy_stm32::mode::{Async, Blocking};
22use embassy_stm32::time::Hertz;
23use embassy_stm32::{bind_interrupts, i2c, peripherals};
24use embassy_time::Timer;
25use embedded_hal_1::i2c::Operation;
26use {defmt_rtt as _, panic_probe as _};
27
28bind_interrupts!(struct Irqs {
29 I2C1 => i2c::EventInterruptHandler<peripherals::I2C1>, i2c::ErrorInterruptHandler<peripherals::I2C1>;
30});
31
32#[embassy_executor::main]
33async fn main(_spawner: Spawner) {
34 let p = embassy_stm32::init(Default::default());
35 info!("Run stm32 I2C v2 Master Tests...");
36
37 let mut i2c_peri = p.I2C1;
38 let mut scl = p.PB8;
39 let mut sda = p.PB9;
40
41 let mut config = Config::default();
42 config.frequency = Hertz(100_000);
43
44 // I2C slave address for Analog Discovery or test EEPROM
45 let slave_addr = 0x50u8;
46
47 // Wait for slave device to be ready
48 Timer::after_millis(100).await;
49
50 // ========== BLOCKING DIRECT API TESTS ==========
51 info!("========== BLOCKING DIRECT API TESTS ==========");
52 {
53 let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config);
54
55 info!("=== Test 1: Direct blocking_write ===");
56 test_blocking_write(&mut i2c, slave_addr);
57
58 info!("=== Test 2: Direct blocking_read ===");
59 test_blocking_read(&mut i2c, slave_addr);
60
61 info!("=== Test 3: Direct blocking_write_read ===");
62 test_blocking_write_read(&mut i2c, slave_addr);
63
64 info!("=== Test 4: Direct blocking_write_vectored ===");
65 test_blocking_write_vectored(&mut i2c, slave_addr);
66
67 info!("=== Test 5: Large buffer (>255 bytes) ===");
68 test_blocking_large_buffer(&mut i2c, slave_addr);
69
70 info!("Blocking direct API tests OK");
71 }
72
73 Timer::after_millis(100).await;
74
75 // ========== BLOCKING TRANSACTION TESTS ==========
76 info!("========== BLOCKING TRANSACTION TESTS ==========");
77 {
78 let mut i2c = I2c::new_blocking(i2c_peri.reborrow(), scl.reborrow(), sda.reborrow(), config);
79
80 info!("=== Test 6: Consecutive Writes (Should Merge) ===");
81 test_consecutive_writes_blocking(&mut i2c, slave_addr);
82
83 info!("=== Test 7: Consecutive Reads (Should Merge) ===");
84 test_consecutive_reads_blocking(&mut i2c, slave_addr);
85
86 info!("=== Test 8: Write then Read (RESTART) ===");
87 test_write_then_read_blocking(&mut i2c, slave_addr);
88
89 info!("=== Test 9: Read then Write (RESTART) ===");
90 test_read_then_write_blocking(&mut i2c, slave_addr);
91
92 info!("=== Test 10: Complex Mixed Sequence ===");
93 test_mixed_sequence_blocking(&mut i2c, slave_addr);
94
95 info!("=== Test 11: Single Operations ===");
96 test_single_operations_blocking(&mut i2c, slave_addr);
97
98 info!("Blocking transaction tests OK");
99 }
100
101 Timer::after_millis(100).await;
102
103 // ========== ASYNC TESTS (DMA) ==========
104 info!("========== ASYNC TESTS (DMA) ==========");
105 {
106 let tx_dma = p.DMA1_CH2;
107 let rx_dma = p.DMA1_CH3;
108
109 let mut i2c = I2c::new(i2c_peri, scl, sda, Irqs, tx_dma, rx_dma, config);
110
111 // Direct API tests (reusing same I2C instance)
112 info!("=== Direct API Test 1: write() ===");
113 test_async_write(&mut i2c, slave_addr).await;
114
115 info!("=== Direct API Test 2: read() ===");
116 test_async_read(&mut i2c, slave_addr).await;
117
118 info!("=== Direct API Test 3: write_read() ===");
119 test_async_write_read(&mut i2c, slave_addr).await;
120
121 info!("=== Direct API Test 4: write_vectored() ===");
122 test_async_write_vectored(&mut i2c, slave_addr).await;
123
124 info!("=== Direct API Test 5: Large buffer (>255 bytes) ===");
125 test_async_large_buffer(&mut i2c, slave_addr).await;
126
127 info!("Async Direct API tests OK");
128
129 // Transaction tests
130 info!("=== Transaction Test 6: Consecutive Writes (Should Merge) ===");
131 test_consecutive_writes_async(&mut i2c, slave_addr).await;
132
133 info!("=== Transaction Test 7: Consecutive Reads (Should Merge) ===");
134 test_consecutive_reads_async(&mut i2c, slave_addr).await;
135
136 info!("=== Transaction Test 8: Write then Read (RESTART) ===");
137 test_write_then_read_async(&mut i2c, slave_addr).await;
138
139 info!("=== Transaction Test 9: Read then Write (RESTART) ===");
140 test_read_then_write_async(&mut i2c, slave_addr).await;
141
142 info!("=== Transaction Test 10: Complex Mixed Sequence ===");
143 test_mixed_sequence_async(&mut i2c, slave_addr).await;
144
145 info!("=== Transaction Test 11: Single Operations ===");
146 test_single_operations_async(&mut i2c, slave_addr).await;
147
148 info!("Async transaction tests OK");
149 }
150
151 info!("All tests OK");
152 cortex_m::asm::bkpt();
153}
154
155// ==================== BLOCKING DIRECT API TEST FUNCTIONS ====================
156
157fn test_blocking_write(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
158 let write_data = [0x42, 0x43, 0x44, 0x45];
159
160 match i2c.blocking_write(addr, &write_data) {
161 Ok(_) => info!("✓ blocking_write succeeded: {:02x}", write_data),
162 Err(e) => {
163 error!("✗ blocking_write failed: {:?}", e);
164 defmt::panic!("Test failed: blocking_write");
165 }
166 }
167}
168
169fn test_blocking_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
170 let mut read_buf = [0u8; 8];
171
172 match i2c.blocking_read(addr, &mut read_buf) {
173 Ok(_) => info!("✓ blocking_read succeeded: {:02x}", read_buf),
174 Err(e) => {
175 error!("✗ blocking_read failed: {:?}", e);
176 defmt::panic!("Test failed: blocking_read");
177 }
178 }
179}
180
181fn test_blocking_write_read(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
182 let write_data = [0x50, 0x51];
183 let mut read_buf = [0u8; 6];
184
185 match i2c.blocking_write_read(addr, &write_data, &mut read_buf) {
186 Ok(_) => {
187 info!("✓ blocking_write_read succeeded");
188 info!(" Written: {:02x}", write_data);
189 info!(" Read: {:02x}", read_buf);
190 }
191 Err(e) => {
192 error!("✗ blocking_write_read failed: {:?}", e);
193 defmt::panic!("Test failed: blocking_write_read");
194 }
195 }
196}
197
198fn test_blocking_write_vectored(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
199 let buf1 = [0x60, 0x61, 0x62];
200 let buf2 = [0x70, 0x71];
201 let buf3 = [0x80, 0x81, 0x82, 0x83];
202 let bufs = [&buf1[..], &buf2[..], &buf3[..]];
203
204 match i2c.blocking_write_vectored(addr, &bufs) {
205 Ok(_) => info!("✓ blocking_write_vectored succeeded (9 bytes total)"),
206 Err(e) => {
207 error!("✗ blocking_write_vectored failed: {:?}", e);
208 defmt::panic!("Test failed: blocking_write_vectored");
209 }
210 }
211}
212
213fn test_blocking_large_buffer(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
214 // Test with 300 bytes to verify RELOAD mechanism works (needs chunking at 255 bytes)
215 let mut write_buf = [0u8; 300];
216 for (i, byte) in write_buf.iter_mut().enumerate() {
217 *byte = (i & 0xFF) as u8;
218 }
219
220 match i2c.blocking_write(addr, &write_buf) {
221 Ok(_) => info!("✓ Large buffer write succeeded (300 bytes, tests RELOAD)"),
222 Err(e) => {
223 error!("✗ Large buffer write failed: {:?}", e);
224 defmt::panic!("Test failed: large buffer write");
225 }
226 }
227
228 // Test large read
229 let mut read_buf = [0u8; 300];
230 match i2c.blocking_read(addr, &mut read_buf) {
231 Ok(_) => info!("✓ Large buffer read succeeded (300 bytes, tests RELOAD)"),
232 Err(e) => {
233 error!("✗ Large buffer read failed: {:?}", e);
234 defmt::panic!("Test failed: large buffer read");
235 }
236 }
237}
238
239// ==================== BLOCKING TRANSACTION TEST FUNCTIONS ====================
240
241fn test_consecutive_writes_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
242 // Expected on bus: START, ADDR+W, data1, data2, data3, STOP
243 // NO intermediate RESTART/STOP between writes - they should be merged
244 let data1 = [0x10, 0x11, 0x12];
245 let data2 = [0x20, 0x21];
246 let data3 = [0x30, 0x31, 0x32, 0x33];
247
248 let mut ops = [
249 Operation::Write(&data1),
250 Operation::Write(&data2),
251 Operation::Write(&data3),
252 ];
253
254 match i2c.blocking_transaction(addr, &mut ops) {
255 Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"),
256 Err(e) => {
257 error!("✗ Consecutive writes failed: {:?}", e);
258 defmt::panic!("Test failed: consecutive writes");
259 }
260 }
261}
262
263fn test_consecutive_reads_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
264 // Expected on bus: START, ADDR+R, data1, data2, data3, NACK, STOP
265 // NO intermediate RESTART/STOP between reads - they should be merged
266 let mut buf1 = [0u8; 4];
267 let mut buf2 = [0u8; 3];
268 let mut buf3 = [0u8; 2];
269
270 let mut ops = [
271 Operation::Read(&mut buf1),
272 Operation::Read(&mut buf2),
273 Operation::Read(&mut buf3),
274 ];
275
276 match i2c.blocking_transaction(addr, &mut ops) {
277 Ok(_) => {
278 info!("✓ Consecutive reads succeeded (merged 9 bytes)");
279 info!(" buf1: {:02x}", buf1);
280 info!(" buf2: {:02x}", buf2);
281 info!(" buf3: {:02x}", buf3);
282 }
283 Err(e) => {
284 error!("✗ Consecutive reads failed: {:?}", e);
285 defmt::panic!("Test failed: consecutive reads");
286 }
287 }
288}
289
290fn test_write_then_read_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
291 // Expected: START, ADDR+W, data, RESTART, ADDR+R, data, NACK, STOP
292 let write_data = [0xAA, 0xBB];
293 let mut read_buf = [0u8; 4];
294
295 let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)];
296
297 match i2c.blocking_transaction(addr, &mut ops) {
298 Ok(_) => {
299 info!("✓ Write-then-read succeeded with RESTART");
300 info!(" Written: {:02x}", write_data);
301 info!(" Read: {:02x}", read_buf);
302 }
303 Err(e) => {
304 error!("✗ Write-then-read failed: {:?}", e);
305 defmt::panic!("Test failed: write-then-read");
306 }
307 }
308}
309
310fn test_read_then_write_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
311 // Expected: START, ADDR+R, data, NACK, RESTART, ADDR+W, data, STOP
312 let mut read_buf = [0u8; 3];
313 let write_data = [0xCC, 0xDD, 0xEE];
314
315 let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)];
316
317 match i2c.blocking_transaction(addr, &mut ops) {
318 Ok(_) => {
319 info!("✓ Read-then-write succeeded with RESTART");
320 info!(" Read: {:02x}", read_buf);
321 info!(" Written: {:02x}", write_data);
322 }
323 Err(e) => {
324 error!("✗ Read-then-write failed: {:?}", e);
325 defmt::panic!("Test failed: read-then-write");
326 }
327 }
328}
329
330fn test_mixed_sequence_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
331 // Complex: W, W, R, R, W, R
332 // Groups: [W,W] RESTART [R,R] RESTART [W] RESTART [R]
333 let w1 = [0x01, 0x02];
334 let w2 = [0x03, 0x04];
335 let mut r1 = [0u8; 2];
336 let mut r2 = [0u8; 2];
337 let w3 = [0x05];
338 let mut r3 = [0u8; 1];
339
340 let mut ops = [
341 Operation::Write(&w1),
342 Operation::Write(&w2),
343 Operation::Read(&mut r1),
344 Operation::Read(&mut r2),
345 Operation::Write(&w3),
346 Operation::Read(&mut r3),
347 ];
348
349 match i2c.blocking_transaction(addr, &mut ops) {
350 Ok(_) => {
351 info!("✓ Mixed sequence succeeded");
352 info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]");
353 }
354 Err(e) => {
355 error!("✗ Mixed sequence failed: {:?}", e);
356 defmt::panic!("Test failed: mixed sequence");
357 }
358 }
359}
360
361fn test_single_operations_blocking(i2c: &mut I2c<'_, Blocking, Master>, addr: u8) {
362 // Test single write
363 let write_data = [0xFF];
364 let mut ops = [Operation::Write(&write_data)];
365
366 match i2c.blocking_transaction(addr, &mut ops) {
367 Ok(_) => info!("✓ Single write succeeded"),
368 Err(e) => {
369 error!("✗ Single write failed: {:?}", e);
370 defmt::panic!("Test failed: single write");
371 }
372 }
373
374 // Test single read
375 let mut read_buf = [0u8; 1];
376 let mut ops = [Operation::Read(&mut read_buf)];
377
378 match i2c.blocking_transaction(addr, &mut ops) {
379 Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]),
380 Err(e) => {
381 error!("✗ Single read failed: {:?}", e);
382 defmt::panic!("Test failed: single read");
383 }
384 }
385}
386
387// ==================== ASYNC DIRECT API TEST FUNCTIONS ====================
388
389async fn test_async_write(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
390 let write_data = [0x42, 0x43, 0x44, 0x45];
391
392 match i2c.write(addr, &write_data).await {
393 Ok(_) => info!("✓ async write succeeded: {:02x}", write_data),
394 Err(e) => {
395 error!("✗ async write failed: {:?}", e);
396 defmt::panic!("Test failed: async write");
397 }
398 }
399}
400
401async fn test_async_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
402 let mut read_buf = [0u8; 8];
403
404 match i2c.read(addr, &mut read_buf).await {
405 Ok(_) => info!("✓ async read succeeded: {:02x}", read_buf),
406 Err(e) => {
407 error!("✗ async read failed: {:?}", e);
408 defmt::panic!("Test failed: async read");
409 }
410 }
411}
412
413async fn test_async_write_read(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
414 let write_data = [0x50, 0x51];
415 let mut read_buf = [0u8; 6];
416
417 match i2c.write_read(addr, &write_data, &mut read_buf).await {
418 Ok(_) => {
419 info!("✓ async write_read succeeded");
420 info!(" Written: {:02x}", write_data);
421 info!(" Read: {:02x}", read_buf);
422 }
423 Err(e) => {
424 error!("✗ async write_read failed: {:?}", e);
425 defmt::panic!("Test failed: async write_read");
426 }
427 }
428}
429
430async fn test_async_write_vectored(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
431 let buf1 = [0x60, 0x61, 0x62];
432 let buf2 = [0x70, 0x71];
433 let buf3 = [0x80, 0x81, 0x82, 0x83];
434 let bufs = [&buf1[..], &buf2[..], &buf3[..]];
435
436 match i2c.write_vectored(addr.into(), &bufs).await {
437 Ok(_) => info!("✓ async write_vectored succeeded (9 bytes total)"),
438 Err(e) => {
439 error!("✗ async write_vectored failed: {:?}", e);
440 defmt::panic!("Test failed: async write_vectored");
441 }
442 }
443}
444
445async fn test_async_large_buffer(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
446 // Test with 300 bytes to verify RELOAD mechanism works with DMA (needs chunking at 255 bytes)
447 let mut write_buf = [0u8; 300];
448 for (i, byte) in write_buf.iter_mut().enumerate() {
449 *byte = (i & 0xFF) as u8;
450 }
451
452 match i2c.write(addr, &write_buf).await {
453 Ok(_) => info!("✓ Large buffer async write succeeded (300 bytes, tests RELOAD with DMA)"),
454 Err(e) => {
455 error!("✗ Large buffer async write failed: {:?}", e);
456 defmt::panic!("Test failed: large buffer async write");
457 }
458 }
459
460 // Test large read
461 let mut read_buf = [0u8; 300];
462 match i2c.read(addr, &mut read_buf).await {
463 Ok(_) => info!("✓ Large buffer async read succeeded (300 bytes, tests RELOAD with DMA)"),
464 Err(e) => {
465 error!("✗ Large buffer async read failed: {:?}", e);
466 defmt::panic!("Test failed: large buffer async read");
467 }
468 }
469}
470
471// ==================== ASYNC TRANSACTION TEST FUNCTIONS ====================
472
473async fn test_consecutive_writes_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
474 let data1 = [0x10, 0x11, 0x12];
475 let data2 = [0x20, 0x21];
476 let data3 = [0x30, 0x31, 0x32, 0x33];
477
478 let mut ops = [
479 Operation::Write(&data1),
480 Operation::Write(&data2),
481 Operation::Write(&data3),
482 ];
483
484 match i2c.transaction(addr, &mut ops).await {
485 Ok(_) => info!("✓ Consecutive writes succeeded (merged 9 bytes)"),
486 Err(e) => {
487 error!("✗ Consecutive writes failed: {:?}", e);
488 defmt::panic!("Test failed: consecutive writes");
489 }
490 }
491}
492
493async fn test_consecutive_reads_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
494 let mut buf1 = [0u8; 4];
495 let mut buf2 = [0u8; 3];
496 let mut buf3 = [0u8; 2];
497
498 let mut ops = [
499 Operation::Read(&mut buf1),
500 Operation::Read(&mut buf2),
501 Operation::Read(&mut buf3),
502 ];
503
504 match i2c.transaction(addr, &mut ops).await {
505 Ok(_) => {
506 info!("✓ Consecutive reads succeeded (merged 9 bytes)");
507 info!(" buf1: {:02x}", buf1);
508 info!(" buf2: {:02x}", buf2);
509 info!(" buf3: {:02x}", buf3);
510 }
511 Err(e) => {
512 error!("✗ Consecutive reads failed: {:?}", e);
513 defmt::panic!("Test failed: consecutive reads");
514 }
515 }
516}
517
518async fn test_write_then_read_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
519 let write_data = [0xAA, 0xBB];
520 let mut read_buf = [0u8; 4];
521
522 let mut ops = [Operation::Write(&write_data), Operation::Read(&mut read_buf)];
523
524 match i2c.transaction(addr, &mut ops).await {
525 Ok(_) => {
526 info!("✓ Write-then-read succeeded with RESTART");
527 info!(" Written: {:02x}", write_data);
528 info!(" Read: {:02x}", read_buf);
529 }
530 Err(e) => {
531 error!("✗ Write-then-read failed: {:?}", e);
532 defmt::panic!("Test failed: write-then-read");
533 }
534 }
535}
536
537async fn test_read_then_write_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
538 let mut read_buf = [0u8; 3];
539 let write_data = [0xCC, 0xDD, 0xEE];
540
541 let mut ops = [Operation::Read(&mut read_buf), Operation::Write(&write_data)];
542
543 match i2c.transaction(addr, &mut ops).await {
544 Ok(_) => {
545 info!("✓ Read-then-write succeeded with RESTART");
546 info!(" Read: {:02x}", read_buf);
547 info!(" Written: {:02x}", write_data);
548 }
549 Err(e) => {
550 error!("✗ Read-then-write failed: {:?}", e);
551 defmt::panic!("Test failed: read-then-write");
552 }
553 }
554}
555
556async fn test_mixed_sequence_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
557 let w1 = [0x01, 0x02];
558 let w2 = [0x03, 0x04];
559 let mut r1 = [0u8; 2];
560 let mut r2 = [0u8; 2];
561 let w3 = [0x05];
562 let mut r3 = [0u8; 1];
563
564 let mut ops = [
565 Operation::Write(&w1),
566 Operation::Write(&w2),
567 Operation::Read(&mut r1),
568 Operation::Read(&mut r2),
569 Operation::Write(&w3),
570 Operation::Read(&mut r3),
571 ];
572
573 match i2c.transaction(addr, &mut ops).await {
574 Ok(_) => {
575 info!("✓ Mixed sequence succeeded");
576 info!(" Groups: [W4] RESTART [R4] RESTART [W1] RESTART [R1]");
577 }
578 Err(e) => {
579 error!("✗ Mixed sequence failed: {:?}", e);
580 defmt::panic!("Test failed: mixed sequence");
581 }
582 }
583}
584
585async fn test_single_operations_async(i2c: &mut I2c<'_, Async, Master>, addr: u8) {
586 // Test single write
587 let write_data = [0xFF];
588 let mut ops = [Operation::Write(&write_data)];
589
590 match i2c.transaction(addr, &mut ops).await {
591 Ok(_) => info!("✓ Single write succeeded"),
592 Err(e) => {
593 error!("✗ Single write failed: {:?}", e);
594 defmt::panic!("Test failed: single write");
595 }
596 }
597
598 // Test single read
599 let mut read_buf = [0u8; 1];
600 let mut ops = [Operation::Read(&mut read_buf)];
601
602 match i2c.transaction(addr, &mut ops).await {
603 Ok(_) => info!("✓ Single read succeeded, data: 0x{:02x}", read_buf[0]),
604 Err(e) => {
605 error!("✗ Single read failed: {:?}", e);
606 defmt::panic!("Test failed: single read");
607 }
608 }
609}
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs
index b5244afc8..9a8dc5685 100644
--- a/examples/stm32f0/src/bin/multiprio.rs
+++ b/examples/stm32f0/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn USART1() { 115unsafe fn USART1() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn USART2() { 120unsafe fn USART2() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index dcb58796b..5714b149a 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f1-examples" 3name = "embassy-stm32f1-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs
index 541ff159e..2451aee3d 100644
--- a/examples/stm32f1/src/bin/adc.rs
+++ b/examples/stm32f1/src/bin/adc.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::{adc, bind_interrupts}; 8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::Timer; 9use embassy_time::Timer;
@@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) {
22 let mut pin = p.PB1; 22 let mut pin = p.PB1;
23 23
24 let mut vrefint = adc.enable_vref(); 24 let mut vrefint = adc.enable_vref();
25 let vrefint_sample = adc.read(&mut vrefint).await; 25 let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await;
26 let convert_to_millivolts = |sample| { 26 let convert_to_millivolts = |sample| {
27 // From http://www.st.com/resource/en/datasheet/CD00161566.pdf 27 // From http://www.st.com/resource/en/datasheet/CD00161566.pdf
28 // 5.3.4 Embedded reference voltage 28 // 5.3.4 Embedded reference voltage
@@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) {
32 }; 32 };
33 33
34 loop { 34 loop {
35 let v = adc.read(&mut pin).await; 35 let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await;
36 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 36 info!("--> {} - {} mV", v, convert_to_millivolts(v));
37 Timer::after_millis(100).await; 37 Timer::after_millis(100).await;
38 } 38 }
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs
index ad0c8a5a5..cbe13b206 100644
--- a/examples/stm32f1/src/bin/can.rs
+++ b/examples/stm32f1/src/bin/can.rs
@@ -5,11 +5,11 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::can::frame::Envelope; 6use embassy_stm32::can::frame::Envelope;
7use embassy_stm32::can::{ 7use embassy_stm32::can::{
8 filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, 8 Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId,
9 TxInterruptHandler, 9 TxInterruptHandler, filter,
10}; 10};
11use embassy_stm32::peripherals::CAN; 11use embassy_stm32::peripherals::CAN;
12use embassy_stm32::{bind_interrupts, Config}; 12use embassy_stm32::{Config, bind_interrupts};
13use static_cell::StaticCell; 13use static_cell::StaticCell;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs
index b5b26938d..6232d8c17 100644
--- a/examples/stm32f1/src/bin/input_capture.rs
+++ b/examples/stm32f1/src/bin/input_capture.rs
@@ -7,7 +7,7 @@ use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed};
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; 8use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
9use embassy_stm32::timer::{self, Channel}; 9use embassy_stm32::timer::{self, Channel};
10use embassy_stm32::{bind_interrupts, peripherals, Peri}; 10use embassy_stm32::{Peri, bind_interrupts, peripherals};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs
index 9ae747018..136c5c555 100644
--- a/examples/stm32f1/src/bin/pwm_input.rs
+++ b/examples/stm32f1/src/bin/pwm_input.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed}; 6use embassy_stm32::gpio::{AfioRemap, Level, Output, Pull, Speed};
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::pwm_input::PwmInput; 8use embassy_stm32::timer::pwm_input::PwmInput;
9use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; 9use embassy_stm32::{Peri, bind_interrupts, peripherals, timer};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index 77ec307b9..5ff54a521 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -7,11 +7,11 @@ use embassy_futures::join::join;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::usb::{Driver, Instance}; 9use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use embassy_usb::Builder;
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::Builder;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs { 17bind_interrupts!(struct Irqs {
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 498c20d84..f726018c3 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f2-examples" 3name = "embassy-stm32f2-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs
index e39e2daec..4418bf502 100644
--- a/examples/stm32f2/src/bin/pll.rs
+++ b/examples/stm32f2/src/bin/pll.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz;
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::time::Hertz;
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 23025ef0b..4349e8055 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f3-examples" 3name = "embassy-stm32f3-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index a54d03212..643f499ed 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -11,13 +11,19 @@
11 11
12use defmt::*; 12use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_stm32::exti::ExtiInput; 14use embassy_stm32::exti::{self, ExtiInput};
15use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 15use embassy_stm32::gpio::{Level, Output, Pull, Speed};
16use embassy_stm32::{bind_interrupts, interrupt};
16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 17use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
17use embassy_sync::channel::Channel; 18use embassy_sync::channel::Channel;
18use embassy_time::{with_timeout, Duration, Timer}; 19use embassy_time::{Duration, Timer, with_timeout};
19use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
20 21
22bind_interrupts!(
23 pub struct Irqs{
24 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
25});
26
21struct Leds<'a> { 27struct Leds<'a> {
22 leds: [Output<'a>; 8], 28 leds: [Output<'a>; 8],
23 direction: i8, 29 direction: i8,
@@ -99,7 +105,7 @@ static CHANNEL: Channel<ThreadModeRawMutex, ButtonEvent, 4> = Channel::new();
99#[embassy_executor::main] 105#[embassy_executor::main]
100async fn main(spawner: Spawner) { 106async fn main(spawner: Spawner) {
101 let p = embassy_stm32::init(Default::default()); 107 let p = embassy_stm32::init(Default::default());
102 let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); 108 let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs);
103 info!("Press the USER button..."); 109 info!("Press the USER button...");
104 let leds = [ 110 let leds = [
105 Output::new(p.PE9, Level::Low, Speed::Low), 111 Output::new(p.PE9, Level::Low, Speed::Low),
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs
index a55530e0e..1df4735ca 100644
--- a/examples/stm32f3/src/bin/button_exti.rs
+++ b/examples/stm32f3/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); 21 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index 2f2ffdea2..8375e0e8e 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn UART4() { 115unsafe fn UART4() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn UART5() { 120unsafe fn UART5() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index 5760f2c1c..58b801c36 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -7,11 +7,11 @@ use embassy_futures::join::join;
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::usb::{Driver, Instance}; 9use embassy_stm32::usb::{Driver, Instance};
10use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use embassy_usb::Builder;
12use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 13use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
13use embassy_usb::driver::EndpointError; 14use embassy_usb::driver::EndpointError;
14use embassy_usb::Builder;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17bind_interrupts!(struct Irqs { 17bind_interrupts!(struct Irqs {
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml
index 3495b118c..cf22633dd 100644
--- a/examples/stm32f334/Cargo.toml
+++ b/examples/stm32f334/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f334-examples" 3name = "embassy-stm32f334-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index 0528a9637..486f160ec 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::{adc, bind_interrupts, Config}; 9use embassy_stm32::{Config, adc, bind_interrupts};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
@@ -40,24 +40,22 @@ async fn main(_spawner: Spawner) -> ! {
40 40
41 let mut adc = Adc::new(p.ADC1, Irqs); 41 let mut adc = Adc::new(p.ADC1, Irqs);
42 42
43 adc.set_sample_time(SampleTime::CYCLES601_5);
44
45 info!("enable vrefint..."); 43 info!("enable vrefint...");
46 44
47 let mut vrefint = adc.enable_vref(); 45 let mut vrefint = adc.enable_vref();
48 let mut temperature = adc.enable_temperature(); 46 let mut temperature = adc.enable_temperature();
49 47
50 loop { 48 loop {
51 let vref = adc.read(&mut vrefint).await; 49 let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await;
52 info!("read vref: {} (should be {})", vref, vrefint.value()); 50 info!("read vref: {} (should be {})", vref, vrefint.calibrated_value());
53 51
54 let temp = adc.read(&mut temperature).await; 52 let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await;
55 info!("read temperature: {}", temp); 53 info!("read temperature: {}", temp);
56 54
57 let pin = adc.read(&mut p.PA0).await; 55 let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await;
58 info!("read pin: {}", pin); 56 info!("read pin: {}", pin);
59 57
60 let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; 58 let pin_mv = (pin as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095;
61 info!("computed pin mv: {}", pin_mv); 59 info!("computed pin mv: {}", pin_mv);
62 60
63 Timer::after_millis(500).await; 61 Timer::after_millis(500).await;
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index c344935d7..9555fd35d 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -7,7 +7,7 @@ use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::opamp::OpAmp; 7use embassy_stm32::opamp::OpAmp;
8use embassy_stm32::peripherals::ADC2; 8use embassy_stm32::peripherals::ADC2;
9use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::{adc, bind_interrupts, Config}; 10use embassy_stm32::{Config, adc, bind_interrupts};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -42,8 +42,6 @@ async fn main(_spawner: Spawner) -> ! {
42 let mut adc = Adc::new(p.ADC2, Irqs); 42 let mut adc = Adc::new(p.ADC2, Irqs);
43 let mut opamp = OpAmp::new(p.OPAMP2); 43 let mut opamp = OpAmp::new(p.OPAMP2);
44 44
45 adc.set_sample_time(SampleTime::CYCLES601_5);
46
47 info!("enable vrefint..."); 45 info!("enable vrefint...");
48 46
49 let mut vrefint = adc.enable_vref(); 47 let mut vrefint = adc.enable_vref();
@@ -51,16 +49,16 @@ async fn main(_spawner: Spawner) -> ! {
51 let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); 49 let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow());
52 50
53 loop { 51 loop {
54 let vref = adc.read(&mut vrefint).await; 52 let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await;
55 info!("read vref: {} (should be {})", vref, vrefint.value()); 53 info!("read vref: {} (should be {})", vref, vrefint.calibrated_value());
56 54
57 let temp = adc.read(&mut temperature).await; 55 let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await;
58 info!("read temperature: {}", temp); 56 info!("read temperature: {}", temp);
59 57
60 let buffer = adc.read(&mut buffer).await; 58 let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await;
61 info!("read buffer: {}", buffer); 59 info!("read buffer: {}", buffer);
62 60
63 let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; 61 let pin_mv = (buffer as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095;
64 info!("computed pin mv: {}", pin_mv); 62 info!("computed pin mv: {}", pin_mv);
65 63
66 Timer::after_millis(500).await; 64 Timer::after_millis(500).await;
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
index 2b0686121..68a61ae22 100644
--- a/examples/stm32f334/src/bin/pwm.rs
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -3,9 +3,9 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config;
6use embassy_stm32::hrtim::*; 7use embassy_stm32::hrtim::*;
7use embassy_stm32::time::{khz, mhz}; 8use embassy_stm32::time::{khz, mhz};
8use embassy_stm32::Config;
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index fb5f86aac..b4555045a 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f4-examples" 3name = "embassy-stm32f4-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -32,7 +32,7 @@ critical-section = "1.1"
32nb = "1.0.0" 32nb = "1.0.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34micromath = "2.0.0" 34micromath = "2.0.0"
35usbd-hid = "0.8.1" 35usbd-hid = "0.9.0"
36static_cell = "2" 36static_cell = "2"
37chrono = { version = "^0.4", default-features = false} 37chrono = { version = "^0.4", default-features = false}
38 38
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs
index 423d29225..694e85657 100644
--- a/examples/stm32f4/src/bin/adc.rs
+++ b/examples/stm32f4/src/bin/adc.rs
@@ -4,7 +4,7 @@
4use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; 4use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs;
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, Temperature, VrefInt}; 7use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt};
8use embassy_time::{Delay, Timer}; 8use embassy_time::{Delay, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
14 info!("Hello World!"); 14 info!("Hello World!");
15 15
16 let mut delay = Delay; 16 let mut delay = Delay;
17 let mut adc = Adc::new(p.ADC1); 17 let mut adc = Adc::new_with_config(p.ADC1, Default::default());
18 let mut pin = p.PC1; 18 let mut pin = p.PC1;
19 19
20 let mut vrefint = adc.enable_vrefint(); 20 let mut vrefint = adc.enable_vrefint();
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 // Startup delay can be combined to the maximum of either 23 // Startup delay can be combined to the maximum of either
24 delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); 24 delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us()));
25 25
26 let vrefint_sample = adc.blocking_read(&mut vrefint); 26 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112);
27 27
28 let convert_to_millivolts = |sample| { 28 let convert_to_millivolts = |sample| {
29 // From http://www.st.com/resource/en/datasheet/DM00071990.pdf 29 // From http://www.st.com/resource/en/datasheet/DM00071990.pdf
@@ -50,16 +50,16 @@ async fn main(_spawner: Spawner) {
50 50
51 loop { 51 loop {
52 // Read pin 52 // Read pin
53 let v = adc.blocking_read(&mut pin); 53 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112);
54 info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); 54 info!("PC1: {} ({} mV)", v, convert_to_millivolts(v));
55 55
56 // Read internal temperature 56 // Read internal temperature
57 let v = adc.blocking_read(&mut temp); 57 let v = adc.blocking_read(&mut temp, SampleTime::CYCLES112);
58 let celcius = convert_to_celcius(v); 58 let celcius = convert_to_celcius(v);
59 info!("Internal temp: {} ({} C)", v, celcius); 59 info!("Internal temp: {} ({} C)", v, celcius);
60 60
61 // Read internal voltage reference 61 // Read internal voltage reference
62 let v = adc.blocking_read(&mut vrefint); 62 let v = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112);
63 info!("VrefInt: {}", v); 63 info!("VrefInt: {}", v);
64 64
65 Timer::after_millis(100).await; 65 Timer::after_millis(100).await;
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs
index 2ec48640e..d61b1b2eb 100644
--- a/examples/stm32f4/src/bin/adc_dma.rs
+++ b/examples/stm32f4/src/bin/adc_dma.rs
@@ -3,8 +3,8 @@
3use cortex_m::singleton; 3use cortex_m::singleton;
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, RingBufferedAdc, SampleTime, Sequence};
7use embassy_stm32::Peripherals; 6use embassy_stm32::Peripherals;
7use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, RingBufferedAdc, SampleTime};
8use embassy_time::Instant; 8use embassy_time::Instant;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -15,21 +15,34 @@ async fn main(spawner: Spawner) {
15} 15}
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn adc_task(mut p: Peripherals) { 18async fn adc_task(p: Peripherals) {
19 const ADC_BUF_SIZE: usize = 1024; 19 const ADC_BUF_SIZE: usize = 1024;
20 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); 20 let adc_data: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
21 let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap(); 21 let adc_data2: &mut [u16; ADC_BUF_SIZE] = singleton!(ADCDAT2 : [u16; ADC_BUF_SIZE] = [0u16; ADC_BUF_SIZE]).unwrap();
22 22
23 let adc = Adc::new(p.ADC1); 23 let adc = Adc::new_with_config(p.ADC1, Default::default());
24 let adc2 = Adc::new(p.ADC2); 24 let adc2 = Adc::new_with_config(p.ADC2, Default::default());
25 25
26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(p.DMA2_CH0, adc_data); 26 let mut adc: RingBufferedAdc<embassy_stm32::peripherals::ADC1> = adc.into_ring_buffered(
27 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(p.DMA2_CH2, adc_data2); 27 p.DMA2_CH0,
28 28 adc_data,
29 adc.set_sample_sequence(Sequence::One, &mut p.PA0, SampleTime::CYCLES112); 29 [
30 adc.set_sample_sequence(Sequence::Two, &mut p.PA2, SampleTime::CYCLES112); 30 (p.PA0.degrade_adc(), SampleTime::CYCLES112),
31 adc2.set_sample_sequence(Sequence::One, &mut p.PA1, SampleTime::CYCLES112); 31 (p.PA2.degrade_adc(), SampleTime::CYCLES112),
32 adc2.set_sample_sequence(Sequence::Two, &mut p.PA3, SampleTime::CYCLES112); 32 ]
33 .into_iter(),
34 RegularConversionMode::Continuous,
35 );
36 let mut adc2: RingBufferedAdc<embassy_stm32::peripherals::ADC2> = adc2.into_ring_buffered(
37 p.DMA2_CH2,
38 adc_data2,
39 [
40 (p.PA1.degrade_adc(), SampleTime::CYCLES112),
41 (p.PA3.degrade_adc(), SampleTime::CYCLES112),
42 ]
43 .into_iter(),
44 RegularConversionMode::Continuous,
45 );
33 46
34 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around 47 // Note that overrun is a big consideration in this implementation. Whatever task is running the adc.read() calls absolutely must circle back around
35 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of 48 // to the adc.read() call before the DMA buffer is wrapped around > 1 time. At this point, the overrun is so significant that the context of
diff --git a/examples/stm32f4/src/bin/button_exti.rs b/examples/stm32f4/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32f4/src/bin/button_exti.rs
+++ b/examples/stm32f4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs
index f41a60529..8dfa0916d 100644
--- a/examples/stm32f4/src/bin/eth.rs
+++ b/examples/stm32f4/src/bin/eth.rs
@@ -5,11 +5,11 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket; 6use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
9use embassy_stm32::peripherals::ETH; 9use embassy_stm32::peripherals::{ETH, ETH_SMA};
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 12use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use embedded_io_async::Write; 14use embedded_io_async::Write;
15use static_cell::StaticCell; 15use static_cell::StaticCell;
@@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs {
20 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 20 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
21}); 21});
22 22
23type Device = Ethernet<'static, ETH, GenericPhy>; 23type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
24 24
25#[embassy_executor::task] 25#[embassy_executor::task]
26async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 26async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -67,16 +67,16 @@ async fn main(spawner: Spawner) -> ! {
67 p.ETH, 67 p.ETH,
68 Irqs, 68 Irqs,
69 p.PA1, 69 p.PA1,
70 p.PA2,
71 p.PC1,
72 p.PA7, 70 p.PA7,
73 p.PC4, 71 p.PC4,
74 p.PC5, 72 p.PC5,
75 p.PG13, 73 p.PG13,
76 p.PB13, 74 p.PB13,
77 p.PG11, 75 p.PG11,
78 GenericPhy::new_auto(),
79 mac_addr, 76 mac_addr,
77 p.ETH_SMA,
78 p.PA2,
79 p.PC1,
80 ); 80 );
81 81
82 let config = embassy_net::Config::dhcpv4(Default::default()); 82 let config = embassy_net::Config::dhcpv4(Default::default());
diff --git a/examples/stm32f4/src/bin/eth_compliance_test.rs b/examples/stm32f4/src/bin/eth_compliance_test.rs
index 52f9d57f6..dc5d7dbb6 100644
--- a/examples/stm32f4/src/bin/eth_compliance_test.rs
+++ b/examples/stm32f4/src/bin/eth_compliance_test.rs
@@ -3,9 +3,9 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, StationManagement}; 6use embassy_stm32::eth::{Ethernet, PacketQueue, StationManagement};
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 8use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use static_cell::StaticCell; 10use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
@@ -43,27 +43,27 @@ async fn main(_spawner: Spawner) -> ! {
43 43
44 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; 44 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
45 45
46 const PHY_ADDR: u8 = 0;
47 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new(); 46 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
48 let mut device = Ethernet::new( 47 let mut device = Ethernet::new(
49 PACKETS.init(PacketQueue::<4, 4>::new()), 48 PACKETS.init(PacketQueue::<4, 4>::new()),
50 p.ETH, 49 p.ETH,
51 Irqs, 50 Irqs,
52 p.PA1, 51 p.PA1,
53 p.PA2,
54 p.PC1,
55 p.PA7, 52 p.PA7,
56 p.PC4, 53 p.PC4,
57 p.PC5, 54 p.PC5,
58 p.PG13, 55 p.PG13,
59 p.PB13, 56 p.PB13,
60 p.PG11, 57 p.PG11,
61 GenericPhy::new(PHY_ADDR),
62 mac_addr, 58 mac_addr,
59 p.ETH_SMA,
60 p.PA2,
61 p.PC1,
63 ); 62 );
64 63
65 let sm = device.station_management(); 64 let sm = device.phy_mut().station_management();
66 65
66 const PHY_ADDR: u8 = 0;
67 // Just an example. Exact register settings depend on the specific PHY and test. 67 // Just an example. Exact register settings depend on the specific PHY and test.
68 sm.smi_write(PHY_ADDR, 0, 0x2100); 68 sm.smi_write(PHY_ADDR, 0, 0x2100);
69 sm.smi_write(PHY_ADDR, 11, 0xA000); 69 sm.smi_write(PHY_ADDR, 11, 0xA000);
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs
index 7ce3bfe75..e274d2a66 100644
--- a/examples/stm32f4/src/bin/eth_w5500.rs
+++ b/examples/stm32f4/src/bin/eth_w5500.rs
@@ -7,13 +7,14 @@ use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_net_wiznet::chip::W5500; 8use embassy_net_wiznet::chip::W5500;
9use embassy_net_wiznet::{Device, Runner, State}; 9use embassy_net_wiznet::{Device, Runner, State};
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::mode::Async; 12use embassy_stm32::mode::Async;
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::spi::mode::Master;
15use embassy_stm32::time::Hertz; 16use embassy_stm32::time::Hertz;
16use embassy_stm32::{bind_interrupts, peripherals, rng, spi, Config}; 17use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, rng, spi};
17use embassy_time::{Delay, Timer}; 18use embassy_time::{Delay, Timer};
18use embedded_hal_bus::spi::ExclusiveDevice; 19use embedded_hal_bus::spi::ExclusiveDevice;
19use embedded_io_async::Write; 20use embedded_io_async::Write;
@@ -22,9 +23,10 @@ use {defmt_rtt as _, panic_probe as _};
22 23
23bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
24 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
26 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
25}); 27});
26 28
27type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; 29type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>;
28#[embassy_executor::task] 30#[embassy_executor::task]
29async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { 31async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! {
30 runner.run().await 32 runner.run().await
@@ -74,7 +76,7 @@ async fn main(spawner: Spawner) -> ! {
74 let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); 76 let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh);
75 let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); 77 let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay));
76 78
77 let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); 79 let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up, Irqs);
78 let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); 80 let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh);
79 81
80 let mac_addr = [0x02, 234, 3, 4, 82, 231]; 82 let mac_addr = [0x02, 234, 3, 4, 82, 231];
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs
index 2feb9de09..14f029747 100644
--- a/examples/stm32f4/src/bin/flash_async.rs
+++ b/examples/stm32f4/src/bin/flash_async.rs
@@ -5,7 +5,7 @@ use defmt::{info, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, InterruptHandler}; 6use embassy_stm32::flash::{Flash, InterruptHandler};
7use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 7use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
8use embassy_stm32::{bind_interrupts, Peri}; 8use embassy_stm32::{Peri, bind_interrupts};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
diff --git a/examples/stm32f4/src/bin/i2c_slave_async.rs b/examples/stm32f4/src/bin/i2c_slave_async.rs
new file mode 100644
index 000000000..5065bcdd8
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_async.rs
@@ -0,0 +1,135 @@
1//! I2C slave example using async operations with DMA
2//!
3//! This example demonstrates DMA-accelerated I2C slave operations,
4//! which provide better performance and lower CPU overhead for
5//! high-frequency I2C transactions.
6
7#![no_std]
8#![no_main]
9
10use defmt::{error, info};
11use embassy_executor::Spawner;
12use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, peripherals};
15use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
16use embassy_sync::mutex::Mutex;
17use embassy_time::{Duration, Timer};
18use {defmt_rtt as _, panic_probe as _};
19
20pub const I2C_SLAVE_ADDR: u8 = 0x42;
21pub const BUFFER_SIZE: usize = 8;
22static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
23
24bind_interrupts!(struct Irqs {
25 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
26 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
27});
28
29#[embassy_executor::main]
30async fn main(spawner: Spawner) {
31 let p = embassy_stm32::init(Default::default());
32
33 // Configure I2C
34 let mut i2c_config = i2c::Config::default();
35 i2c_config.sda_pullup = false;
36 i2c_config.scl_pullup = false;
37 i2c_config.frequency = Hertz(100_000); // 100kHz I2C speed
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 Irqs, p.DMA1_CH6, // TX DMA
44 p.DMA1_CH0, // RX DMA
45 i2c_config,
46 );
47
48 // Convert to MultiMaster mode
49 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
50 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
51
52 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
53}
54
55#[embassy_executor::task]
56pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Async, i2c::mode::MultiMaster>) {
57 info!("Async I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
58
59 loop {
60 match i2c_slave.listen().await {
61 Ok(SlaveCommand {
62 kind: SlaveCommandKind::Write,
63 address,
64 }) => {
65 let addr_val = match address {
66 Address::SevenBit(addr) => addr,
67 Address::TenBit(addr) => (addr & 0xFF) as u8,
68 };
69
70 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
71
72 let mut data_buffer = I2C_BUFFER.lock().await;
73
74 match i2c_slave.respond_to_write(&mut *data_buffer).await {
75 Ok(_) => {
76 info!(
77 "I2C: Data received - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
78 data_buffer[0],
79 data_buffer[1],
80 data_buffer[2],
81 data_buffer[3],
82 data_buffer[4],
83 data_buffer[5],
84 data_buffer[6],
85 data_buffer[7]
86 );
87 }
88 Err(e) => {
89 error!("I2C: Write error: {}", format_i2c_error(&e));
90 }
91 }
92 }
93
94 Ok(SlaveCommand {
95 kind: SlaveCommandKind::Read,
96 address,
97 }) => {
98 let addr_val = match address {
99 Address::SevenBit(addr) => addr,
100 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
101 };
102
103 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
104
105 let data_buffer = I2C_BUFFER.lock().await;
106
107 match i2c_slave.respond_to_read(&data_buffer[..BUFFER_SIZE]).await {
108 Ok(_) => {
109 info!("I2C: Responded to read command");
110 }
111 Err(e) => {
112 error!("I2C: Read error: {}", format_i2c_error(&e));
113 }
114 }
115 }
116
117 Err(e) => {
118 error!("I2C: Listen error: {}", format_i2c_error(&e));
119 Timer::after(Duration::from_millis(100)).await;
120 }
121 }
122 }
123}
124
125fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
126 match e {
127 embassy_stm32::i2c::Error::Bus => "Bus",
128 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
129 embassy_stm32::i2c::Error::Nack => "Nack",
130 embassy_stm32::i2c::Error::Timeout => "Timeout",
131 embassy_stm32::i2c::Error::Crc => "Crc",
132 embassy_stm32::i2c::Error::Overrun => "Overrun",
133 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
134 }
135}
diff --git a/examples/stm32f4/src/bin/i2c_slave_blocking.rs b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
new file mode 100644
index 000000000..ee06d4ac4
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c_slave_blocking.rs
@@ -0,0 +1,132 @@
1//! Complete I2C slave example using blocking operations
2//!
3//! This example shows how to set up an STM32F4 as an I2C slave device
4//! that can handle both read and write transactions from master devices.
5
6#![no_std]
7#![no_main]
8
9use defmt::{error, info};
10use embassy_executor::Spawner;
11use embassy_stm32::i2c::{self, Address, I2c, SlaveAddrConfig, SlaveCommand, SlaveCommandKind};
12use embassy_stm32::time::Hertz;
13use embassy_stm32::{bind_interrupts, peripherals};
14use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
15use embassy_sync::mutex::Mutex;
16use embassy_time::{Duration, Timer};
17use {defmt_rtt as _, panic_probe as _};
18
19pub const I2C_SLAVE_ADDR: u8 = 0x42;
20pub const BUFFER_SIZE: usize = 8;
21static I2C_BUFFER: Mutex<ThreadModeRawMutex, [u8; BUFFER_SIZE]> = Mutex::new([0; BUFFER_SIZE]);
22
23bind_interrupts!(struct Irqs {
24 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
25 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
26});
27
28#[embassy_executor::main]
29async fn main(spawner: Spawner) {
30 let p = embassy_stm32::init(Default::default());
31
32 // Configure I2C
33 let mut i2c_config = i2c::Config::default();
34 i2c_config.sda_pullup = false;
35 i2c_config.scl_pullup = false;
36 i2c_config.frequency = Hertz(100_000);
37 i2c_config.timeout = embassy_time::Duration::from_millis(30000);
38
39 // Initialize I2C as master first
40 let i2c_master = I2c::new_blocking(
41 p.I2C1, p.PB8, // SCL
42 p.PB9, // SDA
43 i2c_config,
44 );
45
46 // Convert to slave+master mode
47 let slave_config = SlaveAddrConfig::basic(I2C_SLAVE_ADDR);
48 let i2c_slave = i2c_master.into_slave_multimaster(slave_config);
49
50 spawner.spawn(i2c_slave_task(i2c_slave).unwrap());
51}
52
53#[embassy_executor::task]
54pub async fn i2c_slave_task(mut i2c_slave: I2c<'static, embassy_stm32::mode::Blocking, i2c::mode::MultiMaster>) {
55 info!("Blocking I2C slave ready at address 0x{:02X}", I2C_SLAVE_ADDR);
56
57 loop {
58 match i2c_slave.blocking_listen() {
59 Ok(SlaveCommand {
60 kind: SlaveCommandKind::Write,
61 address,
62 }) => {
63 let addr_val = match address {
64 Address::SevenBit(addr) => addr,
65 Address::TenBit(addr) => (addr & 0xFF) as u8,
66 };
67
68 info!("I2C: Received write command - Address 0x{:02X}", addr_val);
69 let mut data_buffer = I2C_BUFFER.lock().await;
70
71 match i2c_slave.blocking_respond_to_write(&mut *data_buffer) {
72 Ok(bytes_received) => {
73 info!(
74 "I2C: Received {} bytes - Buffer now contains: 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}, 0x{:02X}",
75 bytes_received,
76 data_buffer[0],
77 data_buffer[1],
78 data_buffer[2],
79 data_buffer[3],
80 data_buffer[4],
81 data_buffer[5],
82 data_buffer[6],
83 data_buffer[7]
84 );
85 }
86 Err(e) => {
87 error!("I2C: Write error: {}", format_i2c_error(&e));
88 }
89 }
90 }
91
92 Ok(SlaveCommand {
93 kind: SlaveCommandKind::Read,
94 address,
95 }) => {
96 let addr_val = match address {
97 Address::SevenBit(addr) => addr,
98 Address::TenBit(addr) => (addr & 0xFF) as u8, // Show low byte for 10-bit
99 };
100
101 info!("I2C: Received read command - Address 0x{:02X}", addr_val);
102 let data_buffer = I2C_BUFFER.lock().await;
103
104 match i2c_slave.blocking_respond_to_read(&data_buffer[..BUFFER_SIZE]) {
105 Ok(bytes_sent) => {
106 info!("I2C: Responded to read - {} bytes sent", bytes_sent);
107 }
108 Err(e) => {
109 error!("I2C: Read error: {}", format_i2c_error(&e));
110 }
111 }
112 }
113
114 Err(e) => {
115 error!("I2C: Listen error: {}", format_i2c_error(&e));
116 Timer::after(Duration::from_millis(100)).await;
117 }
118 }
119 }
120}
121
122fn format_i2c_error(e: &embassy_stm32::i2c::Error) -> &'static str {
123 match e {
124 embassy_stm32::i2c::Error::Bus => "Bus",
125 embassy_stm32::i2c::Error::Arbitration => "Arbitration",
126 embassy_stm32::i2c::Error::Nack => "Nack",
127 embassy_stm32::i2c::Error::Timeout => "Timeout",
128 embassy_stm32::i2c::Error::Crc => "Crc",
129 embassy_stm32::i2c::Error::Overrun => "Overrun",
130 embassy_stm32::i2c::Error::ZeroLengthTransfer => "ZeroLengthTransfer",
131 }
132}
diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs
index 9998c4733..3ff96584d 100644
--- a/examples/stm32f4/src/bin/input_capture.rs
+++ b/examples/stm32f4/src/bin/input_capture.rs
@@ -7,7 +7,7 @@ use embassy_stm32::gpio::{Level, Output, Pull, Speed};
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; 8use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
9use embassy_stm32::timer::{self, Channel}; 9use embassy_stm32::timer::{self, Channel};
10use embassy_stm32::{bind_interrupts, peripherals, Peri}; 10use embassy_stm32::{Peri, bind_interrupts, peripherals};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs
index eb7bb6261..a2e229770 100644
--- a/examples/stm32f4/src/bin/mco.rs
+++ b/examples/stm32f4/src/bin/mco.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler}; 7use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoConfig, McoPrescaler};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -13,8 +13,20 @@ async fn main(_spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
14 info!("Hello World!"); 14 info!("Hello World!");
15 15
16 let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1); 16 let config_mco1 = {
17 let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4); 17 let mut config = McoConfig::default();
18 config.prescaler = McoPrescaler::DIV1;
19 config
20 };
21
22 let config_mco2 = {
23 let mut config = McoConfig::default();
24 config.prescaler = McoPrescaler::DIV4;
25 config
26 };
27
28 let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config_mco1);
29 let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, config_mco2);
18 let mut led = Output::new(p.PB7, Level::High, Speed::Low); 30 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
19 31
20 loop { 32 loop {
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index 2f2ffdea2..8375e0e8e 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn UART4() { 115unsafe fn UART4() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn UART5() { 120unsafe fn UART5() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index c981f1a76..5e39a06f5 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -5,9 +5,9 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::OutputType; 6use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::Channel;
8use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; 9use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
9use embassy_stm32::timer::simple_pwm::PwmPin; 10use embassy_stm32::timer::simple_pwm::PwmPin;
10use embassy_stm32::timer::Channel;
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) {
33 ); 33 );
34 34
35 let max = pwm.get_max_duty(); 35 let max = pwm.get_max_duty();
36 pwm.set_dead_time(max / 1024); 36 pwm.set_dead_time((max / 1024) as u16);
37 37
38 pwm.enable(Channel::Ch1); 38 pwm.enable(Channel::Ch1);
39 39
diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs
index e8bfa524f..d8ea56a34 100644
--- a/examples/stm32f4/src/bin/pwm_input.rs
+++ b/examples/stm32f4/src/bin/pwm_input.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 6use embassy_stm32::gpio::{Level, Output, Pull, Speed};
7use embassy_stm32::time::khz; 7use embassy_stm32::time::khz;
8use embassy_stm32::timer::pwm_input::PwmInput; 8use embassy_stm32::timer::pwm_input::PwmInput;
9use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; 9use embassy_stm32::{Peri, bind_interrupts, peripherals, timer};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs
index 82d8a37ba..5ff705ca2 100644
--- a/examples/stm32f4/src/bin/rtc.rs
+++ b/examples/stm32f4/src/bin/rtc.rs
@@ -4,8 +4,8 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rtc::{Rtc, RtcConfig};
8use embassy_stm32::Config; 7use embassy_stm32::Config;
8use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -21,12 +21,12 @@ async fn main(_spawner: Spawner) {
21 .and_hms_opt(10, 30, 15) 21 .and_hms_opt(10, 30, 15)
22 .unwrap(); 22 .unwrap();
23 23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 24 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
25 25
26 rtc.set_datetime(now.into()).expect("datetime not set"); 26 rtc.set_datetime(now.into()).expect("datetime not set");
27 27
28 loop { 28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into(); 29 let now: NaiveDateTime = time_provider.now().unwrap().into();
30 30
31 info!("{}", now.and_utc().timestamp()); 31 info!("{}", now.and_utc().timestamp());
32 32
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index e97b63925..098fd6986 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -3,9 +3,10 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; 6use embassy_stm32::sdmmc::Sdmmc;
7use embassy_stm32::time::{mhz, Hertz}; 7use embassy_stm32::sdmmc::sd::{CmdBlock, DataBlock, StorageDevice};
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 8use embassy_stm32::time::{Hertz, mhz};
9use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
11/// This is a safeguard to not overwrite any data on the SD card. 12/// This is a safeguard to not overwrite any data on the SD card.
@@ -57,31 +58,24 @@ async fn main(_spawner: Spawner) {
57 // Should print 400kHz for initialization 58 // Should print 400kHz for initialization
58 info!("Configured clock: {}", sdmmc.clock().0); 59 info!("Configured clock: {}", sdmmc.clock().0);
59 60
60 let mut err = None; 61 let mut cmd_block = CmdBlock::new();
61 loop { 62
62 match sdmmc.init_sd_card(mhz(24)).await { 63 let mut storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(24))
63 Ok(_) => break, 64 .await
64 Err(e) => { 65 .unwrap();
65 if err != Some(e) {
66 info!("waiting for card error, retrying: {:?}", e);
67 err = Some(e);
68 }
69 }
70 }
71 }
72 66
73 let card = unwrap!(sdmmc.card()); 67 let card = storage.card();
74 68
75 info!("Card: {:#?}", Debug2Format(card)); 69 info!("Card: {:#?}", Debug2Format(&card));
76 info!("Clock: {}", sdmmc.clock()); 70 info!("Clock: {}", storage.sdmmc.clock());
77 71
78 // Arbitrary block index 72 // Arbitrary block index
79 let block_idx = 16; 73 let block_idx = 16;
80 74
81 // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware. 75 // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware.
82 let mut block = DataBlock([0u8; 512]); 76 let mut block = DataBlock::new();
83 77
84 sdmmc.read_block(block_idx, &mut block).await.unwrap(); 78 storage.read_block(block_idx, &mut block).await.unwrap();
85 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); 79 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
86 80
87 if !ALLOW_WRITES { 81 if !ALLOW_WRITES {
@@ -91,17 +85,17 @@ async fn main(_spawner: Spawner) {
91 85
92 info!("Filling block with 0x55"); 86 info!("Filling block with 0x55");
93 block.fill(0x55); 87 block.fill(0x55);
94 sdmmc.write_block(block_idx, &block).await.unwrap(); 88 storage.write_block(block_idx, &block).await.unwrap();
95 info!("Write done"); 89 info!("Write done");
96 90
97 sdmmc.read_block(block_idx, &mut block).await.unwrap(); 91 storage.read_block(block_idx, &mut block).await.unwrap();
98 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); 92 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
99 93
100 info!("Filling block with 0xAA"); 94 info!("Filling block with 0xAA");
101 block.fill(0xAA); 95 block.fill(0xAA);
102 sdmmc.write_block(block_idx, &block).await.unwrap(); 96 storage.write_block(block_idx, &block).await.unwrap();
103 info!("Write done"); 97 info!("Write done");
104 98
105 sdmmc.read_block(block_idx, &mut block).await.unwrap(); 99 storage.read_block(block_idx, &mut block).await.unwrap();
106 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); 100 info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
107} 101}
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 7abbe8719..a5e625edd 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -3,12 +3,12 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket;
7use embassy_net::StackResources; 6use embassy_net::StackResources;
7use embassy_net::tcp::TcpSocket;
8use embassy_stm32::rng::{self, Rng}; 8use embassy_stm32::rng::{self, Rng};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::usb::Driver; 10use embassy_stm32::usb::Driver;
11use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 11use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
14use embassy_usb::{Builder, UsbDevice}; 14use embassy_usb::{Builder, UsbDevice};
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
index d6b4a9bc9..2d834dcf7 100644
--- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs
+++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
@@ -1,17 +1,19 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_futures::join::join; 8use embassy_futures::join::join;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::gpio::Pull; 10use embassy_stm32::gpio::Pull;
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::usb::Driver; 12use embassy_stm32::usb::Driver;
13use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 13use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, usb};
14use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
16};
15use embassy_usb::control::OutResponse; 17use embassy_usb::control::OutResponse;
16use embassy_usb::{Builder, Handler}; 18use embassy_usb::{Builder, Handler};
17use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 19use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
@@ -19,8 +21,11 @@ use {defmt_rtt as _, panic_probe as _};
19 21
20bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
21 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; 23 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
24 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
22}); 25});
23 26
27static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
28
24// If you are trying this and your USB device doesn't connect, the most 29// If you are trying this and your USB device doesn't connect, the most
25// common issues are the RCC config and vbus_detection 30// common issues are the RCC config and vbus_detection
26// 31//
@@ -70,6 +75,10 @@ async fn main(_spawner: Spawner) {
70 config.serial_number = Some("12345678"); 75 config.serial_number = Some("12345678");
71 config.max_power = 100; 76 config.max_power = 100;
72 config.max_packet_size_0 = 64; 77 config.max_packet_size_0 = 64;
78 config.composite_with_iads = false;
79 config.device_class = 0;
80 config.device_sub_class = 0;
81 config.device_protocol = 0;
73 82
74 // Create embassy-usb DeviceBuilder using the driver and config. 83 // Create embassy-usb DeviceBuilder using the driver and config.
75 // It needs some buffers for building the descriptors. 84 // It needs some buffers for building the descriptors.
@@ -101,6 +110,8 @@ async fn main(_spawner: Spawner) {
101 request_handler: None, 110 request_handler: None,
102 poll_ms: 60, 111 poll_ms: 60,
103 max_packet_size: 8, 112 max_packet_size: 8,
113 hid_subclass: HidSubclass::Boot,
114 hid_boot_protocol: HidBootProtocol::Keyboard,
104 }; 115 };
105 116
106 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); 117 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
@@ -113,7 +124,7 @@ async fn main(_spawner: Spawner) {
113 124
114 let (reader, mut writer) = hid.split(); 125 let (reader, mut writer) = hid.split();
115 126
116 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 127 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
117 128
118 // Do stuff with the class! 129 // Do stuff with the class!
119 let in_fut = async { 130 let in_fut = async {
@@ -121,32 +132,46 @@ async fn main(_spawner: Spawner) {
121 button.wait_for_rising_edge().await; 132 button.wait_for_rising_edge().await;
122 // signal_pin.wait_for_high().await; 133 // signal_pin.wait_for_high().await;
123 info!("Button pressed!"); 134 info!("Button pressed!");
124 // Create a report with the A key pressed. (no shift modifier) 135 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
125 let report = KeyboardReport { 136 match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
126 keycodes: [4, 0, 0, 0, 0, 0], 137 Ok(()) => {}
127 leds: 0, 138 Err(e) => warn!("Failed to send boot report: {:?}", e),
128 modifier: 0, 139 };
129 reserved: 0, 140 } else {
130 }; 141 // Create a report with the A key pressed. (no shift modifier)
131 // Send the report. 142 let report = KeyboardReport {
132 match writer.write_serialize(&report).await { 143 keycodes: [4, 0, 0, 0, 0, 0],
133 Ok(()) => {} 144 leds: 0,
134 Err(e) => warn!("Failed to send report: {:?}", e), 145 modifier: 0,
135 }; 146 reserved: 0,
147 };
148 // Send the report.
149 match writer.write_serialize(&report).await {
150 Ok(()) => {}
151 Err(e) => warn!("Failed to send report: {:?}", e),
152 };
153 }
136 154
137 button.wait_for_falling_edge().await; 155 button.wait_for_falling_edge().await;
138 // signal_pin.wait_for_low().await; 156 // signal_pin.wait_for_low().await;
139 info!("Button released!"); 157 info!("Button released!");
140 let report = KeyboardReport { 158 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
141 keycodes: [0, 0, 0, 0, 0, 0], 159 match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
142 leds: 0, 160 Ok(()) => {}
143 modifier: 0, 161 Err(e) => warn!("Failed to send boot report: {:?}", e),
144 reserved: 0, 162 };
145 }; 163 } else {
146 match writer.write_serialize(&report).await { 164 let report = KeyboardReport {
147 Ok(()) => {} 165 keycodes: [0, 0, 0, 0, 0, 0],
148 Err(e) => warn!("Failed to send report: {:?}", e), 166 leds: 0,
149 }; 167 modifier: 0,
168 reserved: 0,
169 };
170 match writer.write_serialize(&report).await {
171 Ok(()) => {}
172 Err(e) => warn!("Failed to send report: {:?}", e),
173 };
174 }
150 } 175 }
151 }; 176 };
152 177
@@ -172,6 +197,18 @@ impl RequestHandler for MyRequestHandler {
172 OutResponse::Accepted 197 OutResponse::Accepted
173 } 198 }
174 199
200 fn get_protocol(&self) -> HidProtocolMode {
201 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
202 info!("The current HID protocol mode is: {}", protocol);
203 protocol
204 }
205
206 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
207 info!("Switching to HID protocol mode: {}", protocol);
208 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
209 OutResponse::Accepted
210 }
211
175 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 212 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
176 info!("Set idle rate for {:?} to {:?}", id, dur); 213 info!("Set idle rate for {:?} to {:?}", id, dur);
177 } 214 }
diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs
index badb65e98..e83d01f88 100644
--- a/examples/stm32f4/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs
@@ -1,16 +1,20 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::Driver; 10use embassy_stm32::usb::Driver;
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 11use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_time::Timer; 12use embassy_time::Timer;
11use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
12use embassy_usb::control::OutResponse;
13use embassy_usb::Builder; 13use embassy_usb::Builder;
14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
16};
17use embassy_usb::control::OutResponse;
14use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 18use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
15use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
16 20
@@ -18,6 +22,8 @@ bind_interrupts!(struct Irqs {
18 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; 22 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
19}); 23});
20 24
25static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
26
21// If you are trying this and your USB device doesn't connect, the most 27// If you are trying this and your USB device doesn't connect, the most
22// common issues are the RCC config and vbus_detection 28// common issues are the RCC config and vbus_detection
23// 29//
@@ -65,6 +71,10 @@ async fn main(_spawner: Spawner) {
65 config.manufacturer = Some("Embassy"); 71 config.manufacturer = Some("Embassy");
66 config.product = Some("HID mouse example"); 72 config.product = Some("HID mouse example");
67 config.serial_number = Some("12345678"); 73 config.serial_number = Some("12345678");
74 config.composite_with_iads = false;
75 config.device_class = 0;
76 config.device_sub_class = 0;
77 config.device_protocol = 0;
68 78
69 // Create embassy-usb DeviceBuilder using the driver and config. 79 // Create embassy-usb DeviceBuilder using the driver and config.
70 // It needs some buffers for building the descriptors. 80 // It needs some buffers for building the descriptors.
@@ -91,6 +101,8 @@ async fn main(_spawner: Spawner) {
91 request_handler: Some(&mut request_handler), 101 request_handler: Some(&mut request_handler),
92 poll_ms: 60, 102 poll_ms: 60,
93 max_packet_size: 8, 103 max_packet_size: 8,
104 hid_subclass: HidSubclass::Boot,
105 hid_boot_protocol: HidBootProtocol::Mouse,
94 }; 106 };
95 107
96 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); 108 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config);
@@ -108,16 +120,26 @@ async fn main(_spawner: Spawner) {
108 Timer::after_millis(500).await; 120 Timer::after_millis(500).await;
109 121
110 y = -y; 122 y = -y;
111 let report = MouseReport { 123
112 buttons: 0, 124 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
113 x: 0, 125 let buttons = 0u8;
114 y, 126 let x = 0i8;
115 wheel: 0, 127 match writer.write(&[buttons, x as u8, y as u8]).await {
116 pan: 0, 128 Ok(()) => {}
117 }; 129 Err(e) => warn!("Failed to send boot report: {:?}", e),
118 match writer.write_serialize(&report).await { 130 }
119 Ok(()) => {} 131 } else {
120 Err(e) => warn!("Failed to send report: {:?}", e), 132 let report = MouseReport {
133 buttons: 0,
134 x: 0,
135 y,
136 wheel: 0,
137 pan: 0,
138 };
139 match writer.write_serialize(&report).await {
140 Ok(()) => {}
141 Err(e) => warn!("Failed to send report: {:?}", e),
142 }
121 } 143 }
122 } 144 }
123 }; 145 };
@@ -140,6 +162,18 @@ impl RequestHandler for MyRequestHandler {
140 OutResponse::Accepted 162 OutResponse::Accepted
141 } 163 }
142 164
165 fn get_protocol(&self) -> HidProtocolMode {
166 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
167 info!("The current HID protocol mode is: {}", protocol);
168 protocol
169 }
170
171 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
172 info!("Switching to HID protocol mode: {}", protocol);
173 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
174 OutResponse::Accepted
175 }
176
143 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 177 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
144 info!("Set idle rate for {:?} to {:?}", id, dur); 178 info!("Set idle rate for {:?} to {:?}", id, dur);
145 } 179 }
diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs
index bbbcc082b..511f0b281 100644
--- a/examples/stm32f4/src/bin/usb_raw.rs
+++ b/examples/stm32f4/src/bin/usb_raw.rs
@@ -53,7 +53,7 @@ use defmt::*;
53use embassy_executor::Spawner; 53use embassy_executor::Spawner;
54use embassy_stm32::time::Hertz; 54use embassy_stm32::time::Hertz;
55use embassy_stm32::usb::Driver; 55use embassy_stm32::usb::Driver;
56use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 56use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
57use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; 57use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType};
58use embassy_usb::msos::{self, windows_version}; 58use embassy_usb::msos::{self, windows_version};
59use embassy_usb::types::InterfaceNumber; 59use embassy_usb::types::InterfaceNumber;
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index e62b2d8d6..2e81e0a59 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32f4/src/bin/usb_uac_speaker.rs b/examples/stm32f4/src/bin/usb_uac_speaker.rs
index 79bd2d914..b92f4531e 100644
--- a/examples/stm32f4/src/bin/usb_uac_speaker.rs
+++ b/examples/stm32f4/src/bin/usb_uac_speaker.rs
@@ -6,9 +6,9 @@ use core::cell::{Cell, RefCell};
6use defmt::{panic, *}; 6use defmt::{panic, *};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, interrupt, peripherals, timer, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, timer, usb};
10use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
11use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
12use embassy_sync::signal::Signal; 12use embassy_sync::signal::Signal;
13use embassy_sync::zerocopy_channel; 13use embassy_sync::zerocopy_channel;
14use embassy_usb::class::uac1; 14use embassy_usb::class::uac1;
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs
index 5153e1cfd..4e556f0d4 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm.rs
@@ -15,9 +15,9 @@
15use embassy_executor::Spawner; 15use embassy_executor::Spawner;
16use embassy_stm32::gpio::OutputType; 16use embassy_stm32::gpio::OutputType;
17use embassy_stm32::time::khz; 17use embassy_stm32::time::khz;
18use embassy_stm32::timer::Channel;
18use embassy_stm32::timer::low_level::CountingMode; 19use embassy_stm32::timer::low_level::CountingMode;
19use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 20use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
20use embassy_stm32::timer::Channel;
21use embassy_time::{Duration, Ticker, Timer}; 21use embassy_time::{Duration, Ticker, Timer};
22use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
23 23
@@ -61,7 +61,7 @@ async fn main(_spawner: Spawner) {
61 // construct ws2812 non-return-to-zero (NRZ) code bit by bit 61 // construct ws2812 non-return-to-zero (NRZ) code bit by bit
62 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low 62 // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low
63 63
64 let max_duty = ws2812_pwm.max_duty_cycle(); 64 let max_duty = ws2812_pwm.max_duty_cycle() as u16;
65 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing 65 let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing
66 let n1 = 2 * n0; // ws2812 Bit 1 high level timing 66 let n1 = 2 * n0; // ws2812 Bit 1 high level timing
67 67
diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml
index f1d0e411a..5216e19b4 100644
--- a/examples/stm32f469/Cargo.toml
+++ b/examples/stm32f469/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f469-examples" 3name = "embassy-stm32f469-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f469/src/bin/dsi_bsp.rs b/examples/stm32f469/src/bin/dsi_bsp.rs
index 3a24d5dcf..7ba4da72b 100644
--- a/examples/stm32f469/src/bin/dsi_bsp.rs
+++ b/examples/stm32f469/src/bin/dsi_bsp.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dsihost::{blocking_delay_ms, DsiHost, PacketType}; 6use embassy_stm32::dsihost::{DsiHost, PacketType};
7use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::ltdc::Ltdc; 8use embassy_stm32::ltdc::Ltdc;
9use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1}; 9use embassy_stm32::pac::dsihost::regs::{Ier0, Ier1};
@@ -13,7 +13,7 @@ use embassy_stm32::rcc::{
13 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk, 13 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk,
14}; 14};
15use embassy_stm32::time::mhz; 15use embassy_stm32::time::mhz;
16use embassy_time::Timer; 16use embassy_time::{Duration, Timer, block_for};
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19enum _Orientation { 19enum _Orientation {
@@ -211,7 +211,7 @@ async fn main(_spawner: Spawner) {
211 const HORIZONTAL_SYNC_ACTIVE: u16 = 4; // ((HSA as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; 211 const HORIZONTAL_SYNC_ACTIVE: u16 = 4; // ((HSA as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16;
212 const HORIZONTAL_BACK_PORCH: u16 = 77; //((HBP as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32) as u16; 212 const HORIZONTAL_BACK_PORCH: u16 = 77; //((HBP as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32) as u16;
213 const HORIZONTAL_LINE: u16 = 1982; //(((HACT + HSA + HBP + HFP) as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; /* Value depending on display orientation choice portrait/landscape */ 213 const HORIZONTAL_LINE: u16 = 1982; //(((HACT + HSA + HBP + HFP) as u32 * LANE_BYTE_CLK_K_HZ as u32 ) / LCD_CLOCK as u32 ) as u16; /* Value depending on display orientation choice portrait/landscape */
214 // FIXME: Make depend on orientation 214 // FIXME: Make depend on orientation
215 const VERTICAL_SYNC_ACTIVE: u16 = VSA; 215 const VERTICAL_SYNC_ACTIVE: u16 = VSA;
216 const VERTICAL_BACK_PORCH: u16 = VBP; 216 const VERTICAL_BACK_PORCH: u16 = VBP;
217 const VERTICAL_FRONT_PORCH: u16 = VFP; 217 const VERTICAL_FRONT_PORCH: u16 = VFP;
@@ -444,7 +444,7 @@ async fn main(_spawner: Spawner) {
444 dsi.enable_wrapper_dsi(); 444 dsi.enable_wrapper_dsi();
445 445
446 // First, delay 120 ms (reason unknown, STM32 Cube Example does it) 446 // First, delay 120 ms (reason unknown, STM32 Cube Example does it)
447 blocking_delay_ms(120); 447 block_for(Duration::from_millis(120));
448 448
449 // 1 to 26 449 // 1 to 26
450 dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap(); 450 dsi.write_cmd(0, NT35510_WRITES_0[0], &NT35510_WRITES_0[1..]).unwrap();
@@ -480,7 +480,7 @@ async fn main(_spawner: Spawner) {
480 dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); 480 dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap();
481 481
482 // Add a delay, otherwise MADCTL not taken 482 // Add a delay, otherwise MADCTL not taken
483 blocking_delay_ms(200); 483 block_for(Duration::from_millis(200));
484 484
485 // Configure orientation as landscape 485 // Configure orientation as landscape
486 dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..]) 486 dsi.write_cmd(0, NT35510_MADCTL_LANDSCAPE[0], &NT35510_MADCTL_LANDSCAPE[1..])
@@ -494,7 +494,7 @@ async fn main(_spawner: Spawner) {
494 dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap(); 494 dsi.write_cmd(0, NT35510_WRITES_27[0], &NT35510_WRITES_27[1..]).unwrap();
495 495
496 // Wait for sleep out exit 496 // Wait for sleep out exit
497 blocking_delay_ms(120); 497 block_for(Duration::from_millis(120));
498 498
499 // Configure COLOR_CODING 499 // Configure COLOR_CODING
500 dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap(); 500 dsi.write_cmd(0, NT35510_WRITES_37[0], &NT35510_WRITES_37[1..]).unwrap();
@@ -590,7 +590,7 @@ async fn main(_spawner: Spawner) {
590 //LTDC->SRCR = LTDC_SRCR_IMR; 590 //LTDC->SRCR = LTDC_SRCR_IMR;
591 LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD)); 591 LTDC.srcr().modify(|w| w.set_imr(Imr::RELOAD));
592 592
593 blocking_delay_ms(5000); 593 block_for(Duration::from_millis(5000));
594 594
595 const READ_SIZE: u16 = 1; 595 const READ_SIZE: u16 = 1;
596 let mut data = [1u8; READ_SIZE as usize]; 596 let mut data = [1u8; READ_SIZE as usize];
@@ -606,7 +606,7 @@ async fn main(_spawner: Spawner) {
606 .unwrap(); 606 .unwrap();
607 info!("Display ID3: {:#04x}", data); 607 info!("Display ID3: {:#04x}", data);
608 608
609 blocking_delay_ms(500); 609 block_for(Duration::from_millis(500));
610 610
611 info!("Config done, start blinking LED"); 611 info!("Config done, start blinking LED");
612 loop { 612 loop {
@@ -658,7 +658,7 @@ const NT35510_RASET_LANDSCAPE: &[u8] = &[NT35510_CMD_RASET, 0x00, 0x00, 0x01, 0x
658 658
659const NT35510_WRITES_26: &[u8] = &[NT35510_CMD_TEEON, 0x00]; // Tear on 659const NT35510_WRITES_26: &[u8] = &[NT35510_CMD_TEEON, 0x00]; // Tear on
660const NT35510_WRITES_27: &[u8] = &[NT35510_CMD_SLPOUT, 0x00]; // Sleep out 660const NT35510_WRITES_27: &[u8] = &[NT35510_CMD_SLPOUT, 0x00]; // Sleep out
661 // 28,29 missing 661// 28,29 missing
662const NT35510_WRITES_30: &[u8] = &[NT35510_CMD_DISPON, 0x00]; // Display on 662const NT35510_WRITES_30: &[u8] = &[NT35510_CMD_DISPON, 0x00]; // Display on
663 663
664const NT35510_WRITES_31: &[u8] = &[NT35510_CMD_WRDISBV, 0x7F]; 664const NT35510_WRITES_31: &[u8] = &[NT35510_CMD_WRDISBV, 0x7F];
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 5d7763334..565277394 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32f7-examples" 3name = "embassy-stm32f7-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs
index 6689e3b5d..0f226d34e 100644
--- a/examples/stm32f7/src/bin/adc.rs
+++ b/examples/stm32f7/src/bin/adc.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) {
16 let mut pin = p.PA3; 16 let mut pin = p.PA3;
17 17
18 let mut vrefint = adc.enable_vrefint(); 18 let mut vrefint = adc.enable_vrefint();
19 let vrefint_sample = adc.blocking_read(&mut vrefint); 19 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112);
20 let convert_to_millivolts = |sample| { 20 let convert_to_millivolts = |sample| {
21 // From http://www.st.com/resource/en/datasheet/DM00273119.pdf 21 // From http://www.st.com/resource/en/datasheet/DM00273119.pdf
22 // 6.3.27 Reference voltage 22 // 6.3.27 Reference voltage
@@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) {
26 }; 26 };
27 27
28 loop { 28 loop {
29 let v = adc.blocking_read(&mut pin); 29 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112);
30 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 30 info!("--> {} - {} mV", v, convert_to_millivolts(v));
31 Timer::after_millis(100).await; 31 Timer::after_millis(100).await;
32 } 32 }
diff --git a/examples/stm32f7/src/bin/button_exti.rs b/examples/stm32f7/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32f7/src/bin/button_exti.rs
+++ b/examples/stm32f7/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index 9a91ac814..2f3f6db84 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -1,7 +1,7 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::num::{NonZeroU16, NonZeroU8}; 4use core::num::{NonZeroU8, NonZeroU16};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs
index a31e9b4f2..9ccef0b82 100644
--- a/examples/stm32f7/src/bin/cryp.rs
+++ b/examples/stm32f7/src/bin/cryp.rs
@@ -1,13 +1,13 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use aes_gcm::Aes128Gcm;
4use aes_gcm::aead::heapless::Vec; 5use aes_gcm::aead::heapless::Vec;
5use aes_gcm::aead::{AeadInPlace, KeyInit}; 6use aes_gcm::aead::{AeadInPlace, KeyInit};
6use aes_gcm::Aes128Gcm;
7use defmt::info; 7use defmt::info;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::cryp::{self, *}; 9use embassy_stm32::cryp::{self, *};
10use embassy_stm32::{bind_interrupts, peripherals, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals};
11use embassy_time::Instant; 11use embassy_time::Instant;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index b13b7bdda..8613376b8 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -5,11 +5,11 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket; 6use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
9use embassy_stm32::peripherals::ETH; 9use embassy_stm32::peripherals::{ETH, ETH_SMA};
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 12use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use embedded_io_async::Write; 14use embedded_io_async::Write;
15use static_cell::StaticCell; 15use static_cell::StaticCell;
@@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs {
20 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 20 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
21}); 21});
22 22
23type Device = Ethernet<'static, ETH, GenericPhy>; 23type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
24 24
25#[embassy_executor::task] 25#[embassy_executor::task]
26async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 26async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -67,16 +67,16 @@ async fn main(spawner: Spawner) -> ! {
67 p.ETH, 67 p.ETH,
68 Irqs, 68 Irqs,
69 p.PA1, 69 p.PA1,
70 p.PA2,
71 p.PC1,
72 p.PA7, 70 p.PA7,
73 p.PC4, 71 p.PC4,
74 p.PC5, 72 p.PC5,
75 p.PG13, 73 p.PG13,
76 p.PB13, 74 p.PB13,
77 p.PG11, 75 p.PG11,
78 GenericPhy::new_auto(),
79 mac_addr, 76 mac_addr,
77 p.ETH_SMA,
78 p.PA2,
79 p.PC1,
80 ); 80 );
81 81
82 let config = embassy_net::Config::dhcpv4(Default::default()); 82 let config = embassy_net::Config::dhcpv4(Default::default());
diff --git a/examples/stm32f7/src/bin/hash.rs b/examples/stm32f7/src/bin/hash.rs
index c2d1a7158..4fd465df6 100644
--- a/examples/stm32f7/src/bin/hash.rs
+++ b/examples/stm32f7/src/bin/hash.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::hash::*; 6use embassy_stm32::hash::*;
7use embassy_stm32::{bind_interrupts, hash, peripherals, Config}; 7use embassy_stm32::{Config, bind_interrupts, hash, peripherals};
8use embassy_time::Instant; 8use embassy_time::Instant;
9use hmac::{Hmac, Mac}; 9use hmac::{Hmac, Mac};
10use sha2::{Digest, Sha256}; 10use sha2::{Digest, Sha256};
diff --git a/examples/stm32f7/src/bin/pwm.rs b/examples/stm32f7/src/bin/pwm.rs
new file mode 100644
index 000000000..b071eb597
--- /dev/null
+++ b/examples/stm32f7/src/bin/pwm.rs
@@ -0,0 +1,61 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::time::{Hertz, mhz};
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _};
12
13// If you are trying this and your USB device doesn't connect, the most
14// common issues are the RCC config and vbus_detection
15//
16// See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure
17// for more information.
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 info!("Hello World!");
21
22 let mut config = Config::default();
23 {
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::MUL200,
33 divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 200 / 2 = 200Mhz
34 divq: Some(PllQDiv::DIV4), // 8mhz / 4 * 200 / 4 = 100Mhz
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 }
42 let p = embassy_stm32::init(config);
43 let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull);
44 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, mhz(1), Default::default());
45 let mut ch1 = pwm.ch1();
46 ch1.enable();
47
48 info!("PWM initialized");
49 info!("PWM max duty {}", ch1.max_duty_cycle());
50
51 loop {
52 ch1.set_duty_cycle_fully_off();
53 Timer::after_millis(300).await;
54 ch1.set_duty_cycle_fraction(1, 4);
55 Timer::after_millis(300).await;
56 ch1.set_duty_cycle_fraction(1, 2);
57 Timer::after_millis(300).await;
58 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
59 Timer::after_millis(300).await;
60 }
61}
diff --git a/examples/stm32f7/src/bin/pwm_ringbuffer.rs b/examples/stm32f7/src/bin/pwm_ringbuffer.rs
new file mode 100644
index 000000000..4d191ac13
--- /dev/null
+++ b/examples/stm32f7/src/bin/pwm_ringbuffer.rs
@@ -0,0 +1,153 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::time::mhz;
9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _};
12
13// If you are trying this and your USB device doesn't connect, the most
14// common issues are the RCC config and vbus_detection
15//
16// See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure
17// for more information.
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 info!("PWM Ring Buffer Example");
21
22 let mut config = Config::default();
23 {
24 use embassy_stm32::rcc::*;
25 use embassy_stm32::time::Hertz;
26 config.rcc.hse = Some(Hse {
27 freq: Hertz(8_000_000),
28 mode: HseMode::Bypass,
29 });
30 config.rcc.pll_src = PllSource::HSE;
31 config.rcc.pll = Some(Pll {
32 prediv: PllPreDiv::DIV4,
33 mul: PllMul::MUL200,
34 divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 200 / 2 = 200Mhz
35 divq: Some(PllQDiv::DIV4), // 8mhz / 4 * 200 / 4 = 100Mhz
36 divr: None,
37 });
38 config.rcc.ahb_pre = AHBPrescaler::DIV1;
39 config.rcc.apb1_pre = APBPrescaler::DIV4;
40 config.rcc.apb2_pre = APBPrescaler::DIV2;
41 config.rcc.sys = Sysclk::PLL1_P;
42 }
43 let p = embassy_stm32::init(config);
44
45 // Initialize PWM on TIM1
46 let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull);
47 let ch2_pin = PwmPin::new(p.PE11, OutputType::PushPull);
48 let mut pwm = SimplePwm::new(
49 p.TIM1,
50 Some(ch1_pin),
51 Some(ch2_pin),
52 None,
53 None,
54 mhz(1),
55 Default::default(),
56 );
57
58 // Use channel 1 for static PWM at 50%
59 let mut ch1 = pwm.ch1();
60 ch1.enable();
61 ch1.set_duty_cycle_fraction(1, 2);
62 info!("Channel 1 (PE9/D6): Static 50% duty cycle");
63
64 // Get max duty from channel 1 before converting channel 2
65 let max_duty = ch1.max_duty_cycle();
66 info!("PWM max duty: {}", max_duty);
67
68 // Create a DMA ring buffer for channel 2
69 const BUFFER_SIZE: usize = 128;
70 static mut DMA_BUFFER: [u16; BUFFER_SIZE] = [0u16; BUFFER_SIZE];
71 let dma_buffer = unsafe { &mut *core::ptr::addr_of_mut!(DMA_BUFFER) };
72
73 // Pre-fill buffer with initial sine wave using lookup table approach
74 for i in 0..BUFFER_SIZE {
75 // Simple sine approximation using triangle wave
76 let phase = (i * 256) / BUFFER_SIZE;
77 let sine_approx = if phase < 128 {
78 phase as u16 * 2
79 } else {
80 (255 - phase) as u16 * 2
81 };
82 dma_buffer[i] = (sine_approx as u32 * max_duty as u32 / 256) as u16;
83 }
84
85 // Convert channel 2 to ring-buffered PWM
86 let mut ring_pwm = pwm.ch1().into_ring_buffered_channel(p.DMA2_CH5, dma_buffer);
87
88 info!("Ring buffer capacity: {}", ring_pwm.capacity());
89
90 // Pre-write some initial data to the buffer before starting
91 info!("Pre-writing initial waveform data...");
92
93 ring_pwm.write(&[0; BUFFER_SIZE]).unwrap();
94
95 // Enable the PWM channel output
96 ring_pwm.enable();
97
98 // Start the DMA ring buffer
99 ring_pwm.start();
100 info!("Channel 2 (PE11/D5): Ring buffered sine wave started");
101
102 // Give DMA time to start consuming
103 Timer::after_millis(10).await;
104
105 // Continuously update the waveform
106 let mut phase: f32 = 0.0;
107 let mut amplitude: f32 = 1.0;
108 let mut amplitude_direction = -0.05;
109
110 loop {
111 // Generate new waveform data with varying amplitude
112 let mut new_data = [0u16; 32];
113 for i in 0..new_data.len() {
114 // Triangle wave approximation for sine
115 let pos = ((i as u32 + phase as u32) * 4) % 256;
116 let sine_approx = if pos < 128 {
117 pos as u16 * 2
118 } else {
119 (255 - pos) as u16 * 2
120 };
121 let scaled = (sine_approx as u32 * (amplitude * 256.0) as u32) / (256 * 256);
122 new_data[i] = ((scaled * max_duty as u32) / 256) as u16;
123 }
124
125 // Write new data to the ring buffer
126 match ring_pwm.write_exact(&new_data).await {
127 Ok(_remaining) => {}
128 Err(e) => {
129 info!("Write error: {:?}", e);
130 }
131 }
132
133 // Update phase for animation effect
134 phase += 2.0;
135 if phase >= 64.0 {
136 phase = 0.0;
137 }
138
139 // Vary amplitude for breathing effect
140 amplitude += amplitude_direction;
141 if amplitude <= 0.2 || amplitude >= 1.0 {
142 amplitude_direction = -amplitude_direction;
143 }
144
145 // Log buffer status periodically
146 if (phase as u32) % 10 == 0 {
147 match ring_pwm.len() {
148 Ok(len) => info!("Ring buffer fill: {}/{}", len, ring_pwm.capacity()),
149 Err(_) => info!("Error reading buffer length"),
150 }
151 }
152 }
153}
diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs
index 80652b865..e8ef3ad81 100644
--- a/examples/stm32f7/src/bin/qspi.rs
+++ b/examples/stm32f7/src/bin/qspi.rs
@@ -4,11 +4,11 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config as StmCfg;
7use embassy_stm32::mode::Async; 8use embassy_stm32::mode::Async;
8use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; 9use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *};
9use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; 10use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig};
10use embassy_stm32::time::mhz; 11use embassy_stm32::time::mhz;
11use embassy_stm32::Config as StmCfg;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14const MEMORY_PAGE_SIZE: usize = 256; 14const MEMORY_PAGE_SIZE: usize = 256;
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs
index 787bef25e..e5d261d89 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -4,8 +4,9 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::sdmmc::Sdmmc; 6use embassy_stm32::sdmmc::Sdmmc;
7use embassy_stm32::time::{mhz, Hertz}; 7use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice};
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 8use embassy_stm32::time::{Hertz, mhz};
9use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
11bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -54,9 +55,13 @@ async fn main(_spawner: Spawner) {
54 // Should print 400kHz for initialization 55 // Should print 400kHz for initialization
55 info!("Configured clock: {}", sdmmc.clock().0); 56 info!("Configured clock: {}", sdmmc.clock().0);
56 57
57 unwrap!(sdmmc.init_sd_card(mhz(25)).await); 58 let mut cmd_block = CmdBlock::new();
58 59
59 let card = unwrap!(sdmmc.card()); 60 let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25))
61 .await
62 .unwrap();
60 63
61 info!("Card: {:#?}", Debug2Format(card)); 64 let card = storage.card();
65
66 info!("Card: {:#?}", Debug2Format(&card));
62} 67}
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index 349012888..9a30b2c20 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index 1c9451469..16f28500d 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32g0-examples" 3name = "embassy-stm32g0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs
index 7d8653ef2..972e43b55 100644
--- a/examples/stm32g0/src/bin/adc.rs
+++ b/examples/stm32g0/src/bin/adc.rs
@@ -13,11 +13,10 @@ async fn main(_spawner: Spawner) {
13 info!("Hello World!"); 13 info!("Hello World!");
14 14
15 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); 15 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 });
16 adc.set_sample_time(SampleTime::CYCLES79_5);
17 let mut pin = p.PA1; 16 let mut pin = p.PA1;
18 17
19 let mut vrefint = adc.enable_vrefint(); 18 let mut vrefint = adc.enable_vrefint();
20 let vrefint_sample = adc.blocking_read(&mut vrefint); 19 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5);
21 let convert_to_millivolts = |sample| { 20 let convert_to_millivolts = |sample| {
22 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf 21 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
23 // 6.3.3 Embedded internal reference voltage 22 // 6.3.3 Embedded internal reference voltage
@@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) {
27 }; 26 };
28 27
29 loop { 28 loop {
30 let v = adc.blocking_read(&mut pin); 29 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5);
31 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 30 info!("--> {} - {} mV", v, convert_to_millivolts(v));
32 Timer::after_millis(100).await; 31 Timer::after_millis(100).await;
33 } 32 }
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs
index 834d1cd4a..aa8b1771b 100644
--- a/examples/stm32g0/src/bin/adc_oversampling.rs
+++ b/examples/stm32g0/src/bin/adc_oversampling.rs
@@ -7,7 +7,7 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::adc::{Adc, Clock, Ovsr, Ovss, Presc, SampleTime}; 10use embassy_stm32::adc::{Adc, AdcConfig, Clock, Ovsr, Ovss, Presc, SampleTime};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
@@ -16,16 +16,17 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
17 info!("Adc oversample test"); 17 info!("Adc oversample test");
18 18
19 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); 19 let mut config = AdcConfig::default();
20 adc.set_sample_time(SampleTime::CYCLES1_5); 20 config.clock = Some(Clock::Async { div: Presc::DIV1 });
21 let mut pin = p.PA1; 21 config.oversampling_ratio = Some(Ovsr::MUL16);
22 config.oversampling_shift = Some(Ovss::NO_SHIFT);
23 config.oversampling_enable = Some(true);
22 24
23 adc.set_oversampling_ratio(Ovsr::MUL16); 25 let mut adc = Adc::new_with_config(p.ADC1, config);
24 adc.set_oversampling_shift(Ovss::NO_SHIFT); 26 let mut pin = p.PA1;
25 adc.oversampling_enable(true);
26 27
27 loop { 28 loop {
28 let v = adc.blocking_read(&mut pin); 29 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES1_5);
29 info!("--> {} ", v); //max 65520 = 0xFFF0 30 info!("--> {} ", v); //max 65520 = 0xFFF0
30 Timer::after_millis(100).await; 31 Timer::after_millis(100).await;
31 } 32 }
diff --git a/examples/stm32g0/src/bin/button_exti.rs b/examples/stm32g0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32g0/src/bin/button_exti.rs
+++ b/examples/stm32g0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs
index 705905f01..88ee7ea86 100644
--- a/examples/stm32g0/src/bin/hf_timer.rs
+++ b/examples/stm32g0/src/bin/hf_timer.rs
@@ -3,12 +3,12 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config as PeripheralConfig;
6use embassy_stm32::gpio::OutputType; 7use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
9use embassy_stm32::timer::Channel;
8use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; 10use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
9use embassy_stm32::timer::simple_pwm::PwmPin; 11use embassy_stm32::timer::simple_pwm::PwmPin;
10use embassy_stm32::timer::Channel;
11use embassy_stm32::Config as PeripheralConfig;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs
index 5501a6941..ca3e8eb41 100644
--- a/examples/stm32g0/src/bin/input_capture.rs
+++ b/examples/stm32g0/src/bin/input_capture.rs
@@ -13,10 +13,10 @@ use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed}; 14use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed};
15use embassy_stm32::time::khz; 15use embassy_stm32::time::khz;
16use embassy_stm32::timer::Channel;
16use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; 17use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
17use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 18use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
18use embassy_stm32::timer::Channel; 19use embassy_stm32::{Peri, bind_interrupts, peripherals, timer};
19use embassy_stm32::{bind_interrupts, peripherals, timer, Peri};
20use embassy_time::Timer; 20use embassy_time::Timer;
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
22 22
diff --git a/examples/stm32g0/src/bin/onewire_ds18b20.rs b/examples/stm32g0/src/bin/onewire_ds18b20.rs
index 62f8711a6..43ecca8c4 100644
--- a/examples/stm32g0/src/bin/onewire_ds18b20.rs
+++ b/examples/stm32g0/src/bin/onewire_ds18b20.rs
@@ -267,7 +267,7 @@ where
267 } 267 }
268 268
269 match Self::crc8(&data) == 0 { 269 match Self::crc8(&data) == 0 {
270 true => Ok(((data[1] as u16) << 8 | data[0] as u16) as f32 / 16.), 270 true => Ok(((data[1] as i16) << 8 | data[0] as i16) as f32 / 16.),
271 false => Err(()), 271 false => Err(()),
272 } 272 }
273 } 273 }
diff --git a/examples/stm32g0/src/bin/pwm_complementary.rs b/examples/stm32g0/src/bin/pwm_complementary.rs
index dbd9194c9..9856dd953 100644
--- a/examples/stm32g0/src/bin/pwm_complementary.rs
+++ b/examples/stm32g0/src/bin/pwm_complementary.rs
@@ -17,9 +17,9 @@ use defmt::info;
17use embassy_executor::Spawner; 17use embassy_executor::Spawner;
18use embassy_stm32::gpio::OutputType; 18use embassy_stm32::gpio::OutputType;
19use embassy_stm32::time::khz; 19use embassy_stm32::time::khz;
20use embassy_stm32::timer::Channel;
20use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; 21use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
21use embassy_stm32::timer::simple_pwm::PwmPin; 22use embassy_stm32::timer::simple_pwm::PwmPin;
22use embassy_stm32::timer::Channel;
23use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
24 24
25#[embassy_executor::main] 25#[embassy_executor::main]
diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs
index 72aa07c03..5da19e077 100644
--- a/examples/stm32g0/src/bin/pwm_input.rs
+++ b/examples/stm32g0/src/bin/pwm_input.rs
@@ -14,7 +14,7 @@ use embassy_stm32::gpio::{Level, Output, OutputType, Pull, Speed};
14use embassy_stm32::time::khz; 14use embassy_stm32::time::khz;
15use embassy_stm32::timer::pwm_input::PwmInput; 15use embassy_stm32::timer::pwm_input::PwmInput;
16use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 16use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
17use embassy_stm32::{bind_interrupts, peripherals, timer, Peri}; 17use embassy_stm32::{Peri, bind_interrupts, peripherals, timer};
18use embassy_time::Timer; 18use embassy_time::Timer;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20 20
diff --git a/examples/stm32g0/src/bin/rtc.rs b/examples/stm32g0/src/bin/rtc.rs
index 50fb6398e..d8b58de22 100644
--- a/examples/stm32g0/src/bin/rtc.rs
+++ b/examples/stm32g0/src/bin/rtc.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -17,12 +17,12 @@ async fn main(_spawner: Spawner) {
17 17
18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0); 18 let now = DateTime::from(2023, 6, 14, DayOfWeek::Friday, 15, 59, 10, 0);
19 19
20 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 20 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
21 21
22 rtc.set_datetime(now.unwrap()).expect("datetime not set"); 22 rtc.set_datetime(now.unwrap()).expect("datetime not set");
23 23
24 loop { 24 loop {
25 let now: DateTime = rtc.now().unwrap().into(); 25 let now: DateTime = time_provider.now().unwrap().into();
26 26
27 info!("{}:{}:{}", now.hour(), now.minute(), now.second()); 27 info!("{}:{}:{}", now.hour(), now.minute(), now.second());
28 28
diff --git a/examples/stm32g0/src/bin/usb_serial.rs b/examples/stm32g0/src/bin/usb_serial.rs
index 162dfd86b..7dab393ac 100644
--- a/examples/stm32g0/src/bin/usb_serial.rs
+++ b/examples/stm32g0/src/bin/usb_serial.rs
@@ -5,10 +5,10 @@ use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 102960980..d1c19582b 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32g4-examples" 3name = "embassy-stm32g4-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -7,13 +7,13 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32g491re to your chip name, if necessary. 9# Change stm32g491re to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 15embassy-futures = { path = "../../embassy-futures" }
16usbd-hid = "0.8.1" 16usbd-hid = "0.9.0"
17 17
18defmt = "1.0.1" 18defmt = "1.0.1"
19defmt-rtt = "1.0.0" 19defmt-rtt = "1.0.0"
@@ -25,6 +25,7 @@ embedded-can = { version = "0.4" }
25panic-probe = { version = "1.0.0", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27static_cell = "2.0.0" 27static_cell = "2.0.0"
28critical-section = "1.1"
28 29
29[profile.release] 30[profile.release]
30debug = 2 31debug = 2
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs
index adca846d8..2149e0748 100644
--- a/examples/stm32g4/src/bin/adc.rs
+++ b/examples/stm32g4/src/bin/adc.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -28,12 +28,16 @@ async fn main(_spawner: Spawner) {
28 let mut p = embassy_stm32::init(config); 28 let mut p = embassy_stm32::init(config);
29 info!("Hello World!"); 29 info!("Hello World!");
30 30
31 let mut adc = Adc::new(p.ADC2); 31 let mut adc = Adc::new(p.ADC2, Default::default());
32 adc.set_sample_time(SampleTime::CYCLES24_5); 32
33 let mut adc_temp = Adc::new(p.ADC1, Default::default());
34 let mut temperature = adc_temp.enable_temperature();
33 35
34 loop { 36 loop {
35 let measured = adc.blocking_read(&mut p.PA7); 37 let measured = adc.blocking_read(&mut p.PA7, SampleTime::CYCLES24_5);
38 let temperature = adc_temp.blocking_read(&mut temperature, SampleTime::CYCLES24_5);
36 info!("measured: {}", measured); 39 info!("measured: {}", measured);
40 info!("temperature: {}", temperature);
37 Timer::after_millis(500).await; 41 Timer::after_millis(500).await;
38 } 42 }
39} 43}
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs
index 78d071d45..6dedf88d6 100644
--- a/examples/stm32g4/src/bin/adc_differential.rs
+++ b/examples/stm32g4/src/bin/adc_differential.rs
@@ -8,8 +8,8 @@
8 8
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::adc::{Adc, SampleTime};
12use embassy_stm32::Config; 11use embassy_stm32::Config;
12use embassy_stm32::adc::{Adc, SampleTime};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -30,17 +30,16 @@ async fn main(_spawner: Spawner) {
30 config.rcc.mux.adc12sel = mux::Adcsel::SYS; 30 config.rcc.mux.adc12sel = mux::Adcsel::SYS;
31 config.rcc.sys = Sysclk::PLL1_R; 31 config.rcc.sys = Sysclk::PLL1_R;
32 } 32 }
33 let mut p = embassy_stm32::init(config); 33 let p = embassy_stm32::init(config);
34 34
35 let mut adc = Adc::new(p.ADC1); 35 let mut adc = Adc::new(p.ADC1, Default::default());
36 adc.set_sample_time(SampleTime::CYCLES247_5); 36 let mut differential_channel = (p.PA0, p.PA1);
37 adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1
38 37
39 // can also use 38 // can also use
40 // adc.set_differential_channel(1, true); 39 // adc.set_differential_channel(1, true);
41 info!("adc initialized"); 40 info!("adc initialized");
42 loop { 41 loop {
43 let measured = adc.blocking_read(&mut p.PA0); 42 let measured = adc.blocking_read(&mut differential_channel, SampleTime::CYCLES247_5);
44 info!("data: {}", measured); 43 info!("data: {}", measured);
45 Timer::after_millis(500).await; 44 Timer::after_millis(500).await;
46 } 45 }
diff --git a/examples/stm32g4/src/bin/adc_dma.rs b/examples/stm32g4/src/bin/adc_dma.rs
index 202704085..478b6b2ca 100644
--- a/examples/stm32g4/src/bin/adc_dma.rs
+++ b/examples/stm32g4/src/bin/adc_dma.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -12,7 +12,7 @@ static mut DMA_BUF: [u16; 2] = [0; 2];
12 12
13#[embassy_executor::main] 13#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
15 let mut read_buffer = unsafe { &mut DMA_BUF[..] }; 15 let read_buffer = unsafe { &mut DMA_BUF[..] };
16 16
17 let mut config = Config::default(); 17 let mut config = Config::default();
18 { 18 {
@@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) {
33 33
34 info!("Hello World!"); 34 info!("Hello World!");
35 35
36 let mut adc = Adc::new(p.ADC1); 36 let mut adc = Adc::new(p.ADC1, Default::default());
37 37
38 let mut dma = p.DMA1_CH1; 38 let mut dma = p.DMA1_CH1;
39 let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); 39 let mut vrefint_channel = adc.enable_vrefint().degrade_adc();
@@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) {
47 (&mut pa0, SampleTime::CYCLES247_5), 47 (&mut pa0, SampleTime::CYCLES247_5),
48 ] 48 ]
49 .into_iter(), 49 .into_iter(),
50 &mut read_buffer, 50 read_buffer,
51 ) 51 )
52 .await; 52 .await;
53 53
diff --git a/examples/stm32g4/src/bin/adc_injected_and_regular.rs b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
new file mode 100644
index 000000000..1e97fa925
--- /dev/null
+++ b/examples/stm32g4/src/bin/adc_injected_and_regular.rs
@@ -0,0 +1,154 @@
1//! adc injected and regular conversions
2//!
3//! This example both regular and injected ADC conversions at the same time
4//! p:pa0 n:pa2
5
6#![no_std]
7#![no_main]
8
9use core::cell::RefCell;
10
11use defmt::info;
12use embassy_stm32::adc::{
13 Adc, AdcChannel as _, ConversionTrigger, Exten, InjectedAdc, RegularConversionMode, SampleTime,
14};
15use embassy_stm32::interrupt::typelevel::{ADC1_2, Interrupt};
16use embassy_stm32::peripherals::ADC1;
17use embassy_stm32::time::Hertz;
18use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, Mms2};
19use embassy_stm32::timer::low_level::CountingMode;
20use embassy_stm32::{Config, interrupt};
21use embassy_sync::blocking_mutex::CriticalSectionMutex;
22use {defmt_rtt as _, panic_probe as _};
23
24static ADC1_HANDLE: CriticalSectionMutex<RefCell<Option<InjectedAdc<ADC1, 1>>>> =
25 CriticalSectionMutex::new(RefCell::new(None));
26
27/// This example showcases how to use both regular ADC conversions with DMA and injected ADC
28/// conversions with ADC interrupt simultaneously. Both conversion types can be configured with
29/// different triggers and thanks to DMA it is possible to use the measurements in different task
30/// without needing to access the ADC peripheral.
31///
32/// If you don't need both regular and injected conversions the example code can easily be reworked
33/// to only include one of the ADC conversion types.
34#[embassy_executor::main]
35async fn main(_spawner: embassy_executor::Spawner) {
36 // See Table 166 and 167 in RM0440 Rev 9 for ADC1/2 External triggers
37 // Note: Regular and Injected channels use different tables!!
38 const ADC1_INJECTED_TRIGGER_TIM1_TRGO2: u8 = 8;
39 const ADC1_REGULAR_TRIGGER_TIM1_TRGO2: u8 = 10;
40
41 // --- RCC config ---
42 let mut config = Config::default();
43 {
44 use embassy_stm32::rcc::*;
45 config.rcc.pll = Some(Pll {
46 source: PllSource::HSI,
47 prediv: PllPreDiv::DIV4,
48 mul: PllMul::MUL85,
49 divp: None,
50 divq: None,
51 divr: Some(PllRDiv::DIV2),
52 });
53 config.rcc.mux.adc12sel = mux::Adcsel::SYS;
54 config.rcc.sys = Sysclk::PLL1_R;
55 }
56 let p = embassy_stm32::init(config);
57
58 // In this example we use tim1_trgo2 event to trigger the ADC conversions
59 let tim1 = p.TIM1;
60 let pwm_freq = 1;
61 let mut pwm = ComplementaryPwm::new(
62 tim1,
63 None,
64 None,
65 None,
66 None,
67 None,
68 None,
69 None,
70 None,
71 Hertz::hz(pwm_freq),
72 CountingMode::EdgeAlignedUp,
73 );
74 pwm.set_master_output_enable(false);
75 // Mms2 is used to configure which timer event that is connected to tim1_trgo2.
76 // In this case we use the update event of the timer.
77 pwm.set_mms2(Mms2::UPDATE);
78
79 // Configure regular conversions with DMA
80 let adc1 = Adc::new(p.ADC1, Default::default());
81
82 let vrefint_channel = adc1.enable_vrefint().degrade_adc();
83 let pa0 = p.PC1.degrade_adc();
84 let regular_sequence = [
85 (vrefint_channel, SampleTime::CYCLES247_5),
86 (pa0, SampleTime::CYCLES247_5),
87 ]
88 .into_iter();
89
90 // Configurations of Injected ADC measurements
91 let pa2 = p.PA2.degrade_adc();
92 let injected_sequence = [(pa2, SampleTime::CYCLES247_5)];
93
94 // Configure DMA for retrieving regular ADC measurements
95 let dma1_ch1 = p.DMA1_CH1;
96 // Using buffer of double size means the half-full interrupts will generate at the expected rate
97 let mut readings = [0u16; 4];
98
99 let injected_trigger = ConversionTrigger {
100 channel: ADC1_INJECTED_TRIGGER_TIM1_TRGO2,
101 edge: Exten::RISING_EDGE,
102 };
103 let regular_trigger = ConversionTrigger {
104 channel: ADC1_REGULAR_TRIGGER_TIM1_TRGO2,
105 edge: Exten::RISING_EDGE,
106 };
107
108 let (mut ring_buffered_adc, injected_adc) = adc1.into_ring_buffered_and_injected(
109 dma1_ch1,
110 &mut readings,
111 regular_sequence,
112 RegularConversionMode::Triggered(regular_trigger),
113 injected_sequence,
114 injected_trigger,
115 true,
116 );
117
118 // Store ADC globally to allow access from ADC interrupt
119 critical_section::with(|cs| {
120 ADC1_HANDLE.borrow(cs).replace(Some(injected_adc));
121 });
122 // Enable interrupt for ADC1_2
123 unsafe { ADC1_2::enable() };
124
125 // Main loop for reading regular ADC measurements periodically
126 let mut data = [0u16; 2];
127 loop {
128 {
129 match ring_buffered_adc.read(&mut data).await {
130 Ok(n) => {
131 defmt::info!("Regular ADC reading, VrefInt: {}, PA0: {}", data[0], data[1]);
132 defmt::info!("Remaining samples: {}", n,);
133 }
134 Err(e) => {
135 defmt::error!("DMA error: {:?}", e);
136 ring_buffered_adc.clear();
137 }
138 }
139 }
140 }
141}
142
143/// Use ADC1_2 interrupt to retrieve injected ADC measurements
144/// Interrupt must be unsafe as hardware can invoke it any-time. Critical sections ensure safety
145/// within the interrupt.
146#[interrupt]
147unsafe fn ADC1_2() {
148 critical_section::with(|cs| {
149 if let Some(injected_adc) = ADC1_HANDLE.borrow(cs).borrow_mut().as_mut() {
150 let injected_data = injected_adc.read_injected_samples();
151 info!("Injected reading of PA2: {}", injected_data[0]);
152 }
153 });
154}
diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs
index d31eb20f8..87ffea4be 100644
--- a/examples/stm32g4/src/bin/adc_oversampling.rs
+++ b/examples/stm32g4/src/bin/adc_oversampling.rs
@@ -7,9 +7,9 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::adc::vals::{Rovsm, Trovs};
11use embassy_stm32::adc::{Adc, SampleTime};
12use embassy_stm32::Config; 10use embassy_stm32::Config;
11use embassy_stm32::adc::vals::{Rovsm, Trovs};
12use embassy_stm32::adc::{Adc, AdcConfig, SampleTime};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
@@ -32,8 +32,8 @@ async fn main(_spawner: Spawner) {
32 } 32 }
33 let mut p = embassy_stm32::init(config); 33 let mut p = embassy_stm32::init(config);
34 34
35 let mut adc = Adc::new(p.ADC1); 35 let mut config = AdcConfig::default();
36 adc.set_sample_time(SampleTime::CYCLES6_5); 36
37 // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf 37 // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
38 // page652 Oversampler 38 // page652 Oversampler
39 // Table 172. Maximum output results vs N and M. Grayed values indicates truncation 39 // Table 172. Maximum output results vs N and M. Grayed values indicates truncation
@@ -45,12 +45,14 @@ async fn main(_spawner: Spawner) {
45 // 0x05 oversampling ratio X64 45 // 0x05 oversampling ratio X64
46 // 0x06 oversampling ratio X128 46 // 0x06 oversampling ratio X128
47 // 0x07 oversampling ratio X256 47 // 0x07 oversampling ratio X256
48 adc.set_oversampling_ratio(0x03); // ratio X3 48 config.oversampling_ratio = Some(0x03); // ratio X3
49 adc.set_oversampling_shift(0b0000); // no shift 49 config.oversampling_shift = Some(0b0000); // no shift
50 adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); 50 config.oversampling_mode = Some((Rovsm::RESUMED, Trovs::AUTOMATIC, true));
51
52 let mut adc = Adc::new(p.ADC1, config);
51 53
52 loop { 54 loop {
53 let measured = adc.blocking_read(&mut p.PA0); 55 let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES6_5);
54 info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 56 info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520
55 Timer::after_millis(500).await; 57 Timer::after_millis(500).await;
56 } 58 }
diff --git a/examples/stm32g4/src/bin/button_exti.rs b/examples/stm32g4/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32g4/src/bin/button_exti.rs
+++ b/examples/stm32g4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs
index 90004f874..7ff7bd7b4 100644
--- a/examples/stm32g4/src/bin/can.rs
+++ b/examples/stm32g4/src/bin/can.rs
@@ -4,7 +4,7 @@ use defmt::*;
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_stm32::peripherals::*; 5use embassy_stm32::peripherals::*;
6use embassy_stm32::time::Hertz; 6use embassy_stm32::time::Hertz;
7use embassy_stm32::{bind_interrupts, can, Config}; 7use embassy_stm32::{Config, bind_interrupts, can};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use static_cell::StaticCell; 9use static_cell::StaticCell;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs
index 2e87d3931..b23984b3a 100644
--- a/examples/stm32g4/src/bin/usb_c_pd.rs
+++ b/examples/stm32g4/src/bin/usb_c_pd.rs
@@ -1,11 +1,11 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use defmt::{error, info, Format}; 4use defmt::{Format, error, info};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; 6use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd};
7use embassy_stm32::{bind_interrupts, peripherals, Config}; 7use embassy_stm32::{Config, bind_interrupts, peripherals};
8use embassy_time::{with_timeout, Duration}; 8use embassy_time::{Duration, with_timeout};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs { 11bind_interrupts!(struct Irqs {
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs
index 9f66f0c53..a62da6d97 100644
--- a/examples/stm32g4/src/bin/usb_serial.rs
+++ b/examples/stm32g4/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{self, Driver, Instance}; 8use embassy_stm32::usb::{self, Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 66680c027..512186c3d 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h5-examples" 3name = "embassy-stm32h5-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35 35
diff --git a/examples/stm32h5/src/bin/adc.rs b/examples/stm32h5/src/bin/adc.rs
index c5d508ece..c919b1a95 100644
--- a/examples/stm32h5/src/bin/adc.rs
+++ b/examples/stm32h5/src/bin/adc.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -45,14 +45,12 @@ async fn main(_spawner: Spawner) {
45 45
46 let mut adc = Adc::new(p.ADC1); 46 let mut adc = Adc::new(p.ADC1);
47 47
48 adc.set_sample_time(SampleTime::CYCLES24_5);
49
50 let mut vrefint_channel = adc.enable_vrefint(); 48 let mut vrefint_channel = adc.enable_vrefint();
51 49
52 loop { 50 loop {
53 let vrefint = adc.blocking_read(&mut vrefint_channel); 51 let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES24_5);
54 info!("vrefint: {}", vrefint); 52 info!("vrefint: {}", vrefint);
55 let measured = adc.blocking_read(&mut p.PA0); 53 let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES24_5);
56 info!("measured: {}", measured); 54 info!("measured: {}", measured);
57 Timer::after_millis(500).await; 55 Timer::after_millis(500).await;
58 } 56 }
diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs
index fb9fcbc5c..e625e3a34 100644
--- a/examples/stm32h5/src/bin/adc_dma.rs
+++ b/examples/stm32h5/src/bin/adc_dma.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime}; 6use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime};
7use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3}; 7use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3};
8use embassy_stm32::{Config, Peri}; 8use embassy_stm32::{Config, Peri};
9use embassy_time::Instant; 9use embassy_time::{Duration, Instant, Ticker};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[embassy_executor::main] 12#[embassy_executor::main]
@@ -66,7 +66,7 @@ async fn adc2_task(
66 adc_task(adc, dma, pin1, pin2).await; 66 adc_task(adc, dma, pin1, pin2).await;
67} 67}
68 68
69async fn adc_task<'a, T: adc::Instance>( 69async fn adc_task<'a, T: adc::DefaultInstance>(
70 adc: Peri<'a, T>, 70 adc: Peri<'a, T>,
71 mut dma: Peri<'a, impl RxDma<T>>, 71 mut dma: Peri<'a, impl RxDma<T>>,
72 pin1: impl AdcChannel<T>, 72 pin1: impl AdcChannel<T>,
@@ -76,6 +76,9 @@ async fn adc_task<'a, T: adc::Instance>(
76 let mut pin1 = pin1.degrade_adc(); 76 let mut pin1 = pin1.degrade_adc();
77 let mut pin2 = pin2.degrade_adc(); 77 let mut pin2 = pin2.degrade_adc();
78 78
79 info!("adc init");
80
81 let mut ticker = Ticker::every(Duration::from_millis(500));
79 let mut tic = Instant::now(); 82 let mut tic = Instant::now();
80 let mut buffer = [0u16; 512]; 83 let mut buffer = [0u16; 512];
81 loop { 84 loop {
@@ -84,11 +87,13 @@ async fn adc_task<'a, T: adc::Instance>(
84 adc.read( 87 adc.read(
85 dma.reborrow(), 88 dma.reborrow(),
86 [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(), 89 [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(),
87 &mut buffer, 90 &mut buffer[0..2],
88 ) 91 )
89 .await; 92 .await;
90 let toc = Instant::now(); 93 let toc = Instant::now();
91 info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros()); 94 info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros());
92 tic = toc; 95 tic = toc;
96
97 ticker.next().await;
93 } 98 }
94} 99}
diff --git a/examples/stm32h5/src/bin/backup_sram.rs b/examples/stm32h5/src/bin/backup_sram.rs
new file mode 100644
index 000000000..f8db1853e
--- /dev/null
+++ b/examples/stm32h5/src/bin/backup_sram.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::backup_sram::BackupMemory;
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut config = Config::default();
14 config.rcc.ls.enable_backup_sram = true;
15
16 let p = embassy_stm32::init(config);
17 info!("Started!");
18
19 let (bytes, status) = BackupMemory::new(p.BKPSRAM);
20
21 match status {
22 false => info!("BKPSRAM just enabled"),
23 true => info!("BKPSRAM already enabled"),
24 }
25
26 loop {
27 info!("byte0: {}", bytes[0]);
28 bytes[0] = bytes[0].wrapping_add(1);
29 Timer::after_millis(500).await;
30 }
31}
diff --git a/examples/stm32h5/src/bin/button_exti.rs b/examples/stm32h5/src/bin/button_exti.rs
index 2a546dac5..220f89228 100644
--- a/examples/stm32h5/src/bin/button_exti.rs
+++ b/examples/stm32h5/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs
index 194239d47..b1923547e 100644
--- a/examples/stm32h5/src/bin/can.rs
+++ b/examples/stm32h5/src/bin/can.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::peripherals::*; 6use embassy_stm32::peripherals::*;
7use embassy_stm32::{bind_interrupts, can, rcc, Config}; 7use embassy_stm32::{Config, bind_interrupts, can, rcc};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32h5/src/bin/dts.rs b/examples/stm32h5/src/bin/dts.rs
index 8c18fafea..7c856b5b3 100644
--- a/examples/stm32h5/src/bin/dts.rs
+++ b/examples/stm32h5/src/bin/dts.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::dts::{Dts, InterruptHandler, SampleTime}; 6use embassy_stm32::dts::{Dts, InterruptHandler, SampleTime};
7use embassy_stm32::peripherals::DTS; 7use embassy_stm32::peripherals::DTS;
8use embassy_stm32::rcc::frequency; 8use embassy_stm32::rcc::frequency;
9use embassy_stm32::{bind_interrupts, dts, Config}; 9use embassy_stm32::{Config, bind_interrupts, dts};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index a84fe358b..6a3afb2d1 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -5,14 +5,14 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket; 6use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
9use embassy_stm32::peripherals::ETH; 9use embassy_stm32::peripherals::{ETH, ETH_SMA};
10use embassy_stm32::rcc::{ 10use embassy_stm32::rcc::{
11 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, 11 AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
12}; 12};
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
15use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 15use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
16use embassy_time::Timer; 16use embassy_time::Timer;
17use embedded_io_async::Write; 17use embedded_io_async::Write;
18use static_cell::StaticCell; 18use static_cell::StaticCell;
@@ -23,7 +23,7 @@ bind_interrupts!(struct Irqs {
23 RNG => rng::InterruptHandler<peripherals::RNG>; 23 RNG => rng::InterruptHandler<peripherals::RNG>;
24}); 24});
25 25
26type Device = Ethernet<'static, ETH, GenericPhy>; 26type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
27 27
28#[embassy_executor::task] 28#[embassy_executor::task]
29async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 29async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -70,16 +70,16 @@ async fn main(spawner: Spawner) -> ! {
70 p.ETH, 70 p.ETH,
71 Irqs, 71 Irqs,
72 p.PA1, 72 p.PA1,
73 p.PA2,
74 p.PC1,
75 p.PA7, 73 p.PA7,
76 p.PC4, 74 p.PC4,
77 p.PC5, 75 p.PC5,
78 p.PG13, 76 p.PG13,
79 p.PB15, 77 p.PB15,
80 p.PG11, 78 p.PG11,
81 GenericPhy::new_auto(),
82 mac_addr, 79 mac_addr,
80 p.ETH_SMA,
81 p.PA2,
82 p.PC1,
83 ); 83 );
84 84
85 let config = embassy_net::Config::dhcpv4(Default::default()); 85 let config = embassy_net::Config::dhcpv4(Default::default());
diff --git a/examples/stm32h5/src/bin/mco.rs b/examples/stm32h5/src/bin/mco.rs
new file mode 100644
index 000000000..1137ba25c
--- /dev/null
+++ b/examples/stm32h5/src/bin/mco.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::gpio::Speed;
7use embassy_stm32::rcc::{Mco, Mco2Source, McoConfig};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default());
13
14 /* Default "VeryHigh" drive strength and prescaler DIV1 */
15 // let _mco = Mco::new(p.MCO2, p.PC9, Mco2Source::SYS, McoConfig::default());
16
17 /* Choose Speed::Low drive strength */
18 let config = {
19 let mut config = McoConfig::default();
20 config.speed = Speed::Low;
21 config
22 };
23
24 let _mco = Mco::new(p.MCO2, p.PC9, Mco2Source::SYS, config);
25
26 info!("Clock out with low drive strength set on Master Clock Out 2 pin as AF on PC9");
27
28 loop {}
29}
diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs
index 0e182f9cf..6632a7f98 100644
--- a/examples/stm32h5/src/bin/sai.rs
+++ b/examples/stm32h5/src/bin/sai.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::{sai, Config}; 6use embassy_stm32::{Config, sai};
7use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
8 8
9#[embassy_executor::main] 9#[embassy_executor::main]
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index 3c4f49f64..8d5456b80 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -7,22 +7,12 @@
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 9use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
10use embassy_stm32::low_power::Executor;
11use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; 10use embassy_stm32::rcc::{HSIPrescaler, LsConfig};
12use embassy_stm32::rtc::{Rtc, RtcConfig}; 11use embassy_stm32::{Config, Peri, low_power};
13use embassy_stm32::{Config, Peri};
14use embassy_time::Timer; 12use embassy_time::Timer;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
17 14
18#[cortex_m_rt::entry] 15#[embassy_executor::main(executor = "low_power::Executor")]
19fn main() -> ! {
20 Executor::take().run(|spawner| {
21 spawner.spawn(unwrap!(async_main(spawner)));
22 })
23}
24
25#[embassy_executor::task]
26async fn async_main(spawner: Spawner) { 16async fn async_main(spawner: Spawner) {
27 defmt::info!("Program Start"); 17 defmt::info!("Program Start");
28 18
@@ -37,12 +27,6 @@ async fn async_main(spawner: Spawner) {
37 // config.enable_debug_during_sleep = false; 27 // config.enable_debug_during_sleep = false;
38 let p = embassy_stm32::init(config); 28 let p = embassy_stm32::init(config);
39 29
40 // give the RTC to the executor...
41 let rtc = Rtc::new(p.RTC, RtcConfig::default());
42 static RTC: StaticCell<Rtc> = StaticCell::new();
43 let rtc = RTC.init(rtc);
44 embassy_stm32::low_power::stop_with_rtc(rtc);
45
46 spawner.spawn(unwrap!(blinky(p.PB4.into()))); 30 spawner.spawn(unwrap!(blinky(p.PB4.into())));
47 spawner.spawn(unwrap!(timeout())); 31 spawner.spawn(unwrap!(timeout()));
48} 32}
diff --git a/examples/stm32h5/src/bin/usb_c_pd.rs b/examples/stm32h5/src/bin/usb_c_pd.rs
index acb03e498..ab6efff32 100644
--- a/examples/stm32h5/src/bin/usb_c_pd.rs
+++ b/examples/stm32h5/src/bin/usb_c_pd.rs
@@ -3,12 +3,12 @@
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5 5
6use defmt::{error, info, Format}; 6use defmt::{Format, error, info};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::Output; 8use embassy_stm32::gpio::Output;
9use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd}; 9use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, Ucpd};
10use embassy_stm32::{bind_interrupts, peripherals, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals};
11use embassy_time::{with_timeout, Duration}; 11use embassy_time::{Duration, with_timeout};
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index e8f536133..f72851ed7 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h5/src/bin/usb_uac_speaker.rs b/examples/stm32h5/src/bin/usb_uac_speaker.rs
index 86873cabd..f75b1fd8a 100644
--- a/examples/stm32h5/src/bin/usb_uac_speaker.rs
+++ b/examples/stm32h5/src/bin/usb_uac_speaker.rs
@@ -6,9 +6,9 @@ use core::cell::{Cell, RefCell};
6use defmt::{panic, *}; 6use defmt::{panic, *};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, interrupt, peripherals, timer, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, timer, usb};
10use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
11use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
12use embassy_sync::signal::Signal; 12use embassy_sync::signal::Signal;
13use embassy_sync::zerocopy_channel; 13use embassy_sync::zerocopy_channel;
14use embassy_usb::class::uac1; 14use embassy_usb::class::uac1;
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 9a2080013..09b734054 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h7-examples" 3name = "embassy-stm32h7-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs
index 98504ddf6..fc45541bf 100644
--- a/examples/stm32h7/src/bin/adc.rs
+++ b/examples/stm32h7/src/bin/adc.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -46,14 +46,12 @@ async fn main(_spawner: Spawner) {
46 46
47 let mut adc = Adc::new(p.ADC3); 47 let mut adc = Adc::new(p.ADC3);
48 48
49 adc.set_sample_time(SampleTime::CYCLES32_5);
50
51 let mut vrefint_channel = adc.enable_vrefint(); 49 let mut vrefint_channel = adc.enable_vrefint();
52 50
53 loop { 51 loop {
54 let vrefint = adc.blocking_read(&mut vrefint_channel); 52 let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES32_5);
55 info!("vrefint: {}", vrefint); 53 info!("vrefint: {}", vrefint);
56 let measured = adc.blocking_read(&mut p.PC0); 54 let measured = adc.blocking_read(&mut p.PC0, SampleTime::CYCLES32_5);
57 info!("measured: {}", measured); 55 info!("measured: {}", measured);
58 Timer::after_millis(500).await; 56 Timer::after_millis(500).await;
59 } 57 }
diff --git a/examples/stm32h7/src/bin/adc_dma.rs b/examples/stm32h7/src/bin/adc_dma.rs
index f06b5d06e..cedb32e47 100644
--- a/examples/stm32h7/src/bin/adc_dma.rs
+++ b/examples/stm32h7/src/bin/adc_dma.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32h7/src/bin/button_exti.rs b/examples/stm32h7/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32h7/src/bin/button_exti.rs
+++ b/examples/stm32h7/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 8f2e265d6..c593d5e0b 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -5,8 +5,8 @@ use embassy_executor::Spawner;
5use embassy_stm32::dcmi::{self, *}; 5use embassy_stm32::dcmi::{self, *};
6use embassy_stm32::gpio::{Level, Output, Speed}; 6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::i2c::I2c; 7use embassy_stm32::i2c::I2c;
8use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; 8use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler};
9use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; 9use embassy_stm32::{Config, bind_interrupts, i2c, peripherals};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use ov7725::*; 11use ov7725::*;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -48,7 +48,14 @@ async fn main(_spawner: Spawner) {
48 let p = embassy_stm32::init(config); 48 let p = embassy_stm32::init(config);
49 49
50 defmt::info!("Hello World!"); 50 defmt::info!("Hello World!");
51 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); 51
52 let mco_config = {
53 let mut config = McoConfig::default();
54 config.prescaler = McoPrescaler::DIV3;
55 config
56 };
57
58 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, mco_config);
52 59
53 let mut led = Output::new(p.PE3, Level::High, Speed::Low); 60 let mut led = Output::new(p.PE3, Level::High, Speed::Low);
54 let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default()); 61 let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default());
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs
index 0af11ef3e..49830f9b7 100644
--- a/examples/stm32h7/src/bin/can.rs
+++ b/examples/stm32h7/src/bin/can.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::peripherals::*; 6use embassy_stm32::peripherals::*;
7use embassy_stm32::{bind_interrupts, can, rcc, Config}; 7use embassy_stm32::{Config, bind_interrupts, can, rcc};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index 27df80336..fa22837c5 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -3,8 +3,8 @@
3 3
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dac::{DacCh1, Value};
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::dac::{DacCh1, Value};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[entry] 10#[entry]
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index df37e9d78..9ccefa761 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -3,6 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Peri;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 7use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async; 8use embassy_stm32::mode::Async;
8use embassy_stm32::pac::timer::vals::Mms; 9use embassy_stm32::pac::timer::vals::Mms;
@@ -10,7 +11,6 @@ use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
10use embassy_stm32::rcc::frequency; 11use embassy_stm32::rcc::frequency;
11use embassy_stm32::time::Hertz; 12use embassy_stm32::time::Hertz;
12use embassy_stm32::timer::low_level::Timer; 13use embassy_stm32::timer::low_level::Timer;
13use embassy_stm32::Peri;
14use micromath::F32Ext; 14use micromath::F32Ext;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 6c215362d..09915799b 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -5,10 +5,10 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket; 6use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
9use embassy_stm32::peripherals::ETH; 9use embassy_stm32::peripherals::{ETH, ETH_SMA};
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 11use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
12use embassy_time::Timer; 12use embassy_time::Timer;
13use embedded_io_async::Write; 13use embedded_io_async::Write;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
@@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs {
19 RNG => rng::InterruptHandler<peripherals::RNG>; 19 RNG => rng::InterruptHandler<peripherals::RNG>;
20}); 20});
21 21
22type Device = Ethernet<'static, ETH, GenericPhy>; 22type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
23 23
24#[embassy_executor::task] 24#[embassy_executor::task]
25async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 25async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -69,16 +69,16 @@ async fn main(spawner: Spawner) -> ! {
69 p.ETH, 69 p.ETH,
70 Irqs, 70 Irqs,
71 p.PA1, // ref_clk 71 p.PA1, // ref_clk
72 p.PA2, // mdio
73 p.PC1, // eth_mdc
74 p.PA7, // CRS_DV: Carrier Sense 72 p.PA7, // CRS_DV: Carrier Sense
75 p.PC4, // RX_D0: Received Bit 0 73 p.PC4, // RX_D0: Received Bit 0
76 p.PC5, // RX_D1: Received Bit 1 74 p.PC5, // RX_D1: Received Bit 1
77 p.PG13, // TX_D0: Transmit Bit 0 75 p.PG13, // TX_D0: Transmit Bit 0
78 p.PB13, // TX_D1: Transmit Bit 1 76 p.PB13, // TX_D1: Transmit Bit 1
79 p.PG11, // TX_EN: Transmit Enable 77 p.PG11, // TX_EN: Transmit Enable
80 GenericPhy::new_auto(),
81 mac_addr, 78 mac_addr,
79 p.ETH_SMA,
80 p.PA2, // mdio
81 p.PC1, // mdc
82 ); 82 );
83 83
84 let config = embassy_net::Config::dhcpv4(Default::default()); 84 let config = embassy_net::Config::dhcpv4(Default::default());
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 10ac57fc9..189c99686 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -5,12 +5,12 @@ use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_net::tcp::client::{TcpClient, TcpClientState};
9use embassy_net::StackResources; 8use embassy_net::StackResources;
10use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 9use embassy_net::tcp::client::{TcpClient, TcpClientState};
11use embassy_stm32::peripherals::ETH; 10use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
11use embassy_stm32::peripherals::{ETH, ETH_SMA};
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 13use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
14use embassy_time::Timer; 14use embassy_time::Timer;
15use embedded_io_async::Write; 15use embedded_io_async::Write;
16use embedded_nal_async::TcpConnect; 16use embedded_nal_async::TcpConnect;
@@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs {
22 RNG => rng::InterruptHandler<peripherals::RNG>; 22 RNG => rng::InterruptHandler<peripherals::RNG>;
23}); 23});
24 24
25type Device = Ethernet<'static, ETH, GenericPhy>; 25type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
26 26
27#[embassy_executor::task] 27#[embassy_executor::task]
28async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 28async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -71,16 +71,16 @@ async fn main(spawner: Spawner) -> ! {
71 p.ETH, 71 p.ETH,
72 Irqs, 72 Irqs,
73 p.PA1, 73 p.PA1,
74 p.PA2,
75 p.PC1,
76 p.PA7, 74 p.PA7,
77 p.PC4, 75 p.PC4,
78 p.PC5, 76 p.PC5,
79 p.PG13, 77 p.PG13,
80 p.PB13, 78 p.PB13,
81 p.PG11, 79 p.PG11,
82 GenericPhy::new_auto(),
83 mac_addr, 80 mac_addr,
81 p.ETH_SMA,
82 p.PA2,
83 p.PC1,
84 ); 84 );
85 85
86 let config = embassy_net::Config::dhcpv4(Default::default()); 86 let config = embassy_net::Config::dhcpv4(Default::default());
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs
index c6a108471..92c823567 100644
--- a/examples/stm32h7/src/bin/eth_client_mii.rs
+++ b/examples/stm32h7/src/bin/eth_client_mii.rs
@@ -5,12 +5,12 @@ use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_net::tcp::client::{TcpClient, TcpClientState};
9use embassy_net::StackResources; 8use embassy_net::StackResources;
10use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 9use embassy_net::tcp::client::{TcpClient, TcpClientState};
11use embassy_stm32::peripherals::ETH; 10use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
11use embassy_stm32::peripherals::{ETH, ETH_SMA};
12use embassy_stm32::rng::Rng; 12use embassy_stm32::rng::Rng;
13use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 13use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
14use embassy_time::Timer; 14use embassy_time::Timer;
15use embedded_io_async::Write; 15use embedded_io_async::Write;
16use embedded_nal_async::TcpConnect; 16use embedded_nal_async::TcpConnect;
@@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs {
22 RNG => rng::InterruptHandler<peripherals::RNG>; 22 RNG => rng::InterruptHandler<peripherals::RNG>;
23}); 23});
24 24
25type Device = Ethernet<'static, ETH, GenericPhy>; 25type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
26 26
27#[embassy_executor::task] 27#[embassy_executor::task]
28async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 28async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -72,8 +72,6 @@ async fn main(spawner: Spawner) -> ! {
72 Irqs, 72 Irqs,
73 p.PA1, 73 p.PA1,
74 p.PC3, 74 p.PC3,
75 p.PA2,
76 p.PC1,
77 p.PA7, 75 p.PA7,
78 p.PC4, 76 p.PC4,
79 p.PC5, 77 p.PC5,
@@ -84,8 +82,10 @@ async fn main(spawner: Spawner) -> ! {
84 p.PC2, 82 p.PC2,
85 p.PE2, 83 p.PE2,
86 p.PG11, 84 p.PG11,
87 GenericPhy::new_auto(),
88 mac_addr, 85 mac_addr,
86 p.ETH_SMA,
87 p.PA2,
88 p.PC1,
89 ); 89 );
90 info!("Device created"); 90 info!("Device created");
91 91
diff --git a/examples/stm32h7/src/bin/flash_async.rs b/examples/stm32h7/src/bin/flash_async.rs
new file mode 100644
index 000000000..96d1936f3
--- /dev/null
+++ b/examples/stm32h7/src/bin/flash_async.rs
@@ -0,0 +1,84 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, InterruptHandler};
7use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
8use embassy_stm32::{Peri, bind_interrupts};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 FLASH => InterruptHandler;
14});
15
16#[embassy_executor::main]
17async fn main(spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default());
19 info!("Hello Flash!");
20
21 let mut f = Flash::new(p.FLASH, Irqs);
22
23 // Led should blink uninterrupted during ~2sec erase operation
24 spawner.spawn(blinky(p.PB14.into()).unwrap());
25
26 // Test on bank 2 in order not to stall CPU.
27 test_flash(&mut f, 1024 * 1024, 128 * 1024).await;
28}
29
30#[embassy_executor::task]
31async fn blinky(p: Peri<'static, AnyPin>) {
32 let mut led = Output::new(p, Level::High, Speed::Low);
33
34 loop {
35 info!("high");
36 led.set_high();
37 Timer::after_millis(300).await;
38
39 info!("low");
40 led.set_low();
41 Timer::after_millis(300).await;
42 }
43}
44
45async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) {
46 info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size);
47
48 info!("Reading...");
49 let mut buf = [0u8; 32];
50 unwrap!(f.blocking_read(offset, &mut buf));
51 info!("Read: {=[u8]:x}", buf);
52
53 info!("Erasing...");
54 unwrap!(f.erase(offset, offset + size).await);
55
56 info!("Reading...");
57 let mut buf = [0u8; 32];
58 unwrap!(f.blocking_read(offset, &mut buf));
59 info!("Read after erase: {=[u8]:x}", buf);
60
61 info!("Writing...");
62 unwrap!(
63 f.write(
64 offset,
65 &[
66 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
67 29, 30, 31, 32
68 ]
69 )
70 .await
71 );
72
73 info!("Reading...");
74 let mut buf = [0u8; 32];
75 unwrap!(f.blocking_read(offset, &mut buf));
76 info!("Read: {=[u8]:x}", buf);
77 assert_eq!(
78 &buf[..],
79 &[
80 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
81 30, 31, 32
82 ]
83 );
84}
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs
index 5e5e6ccc8..b65d50443 100644
--- a/examples/stm32h7/src/bin/fmc.rs
+++ b/examples/stm32h7/src/bin/fmc.rs
@@ -3,8 +3,8 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::fmc::Fmc;
7use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_stm32::fmc::Fmc;
8use embassy_time::{Delay, Timer}; 8use embassy_time::{Delay, Timer};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs
index 9e45d845f..08ff812f2 100644
--- a/examples/stm32h7/src/bin/i2c_shared.rs
+++ b/examples/stm32h7/src/bin/i2c_shared.rs
@@ -9,8 +9,8 @@ use embassy_executor::Spawner;
9use embassy_stm32::i2c::{self, I2c}; 9use embassy_stm32::i2c::{self, I2c};
10use embassy_stm32::mode::Async; 10use embassy_stm32::mode::Async;
11use embassy_stm32::{bind_interrupts, peripherals}; 11use embassy_stm32::{bind_interrupts, peripherals};
12use embassy_sync::blocking_mutex::raw::NoopRawMutex;
13use embassy_sync::blocking_mutex::NoopMutex; 12use embassy_sync::blocking_mutex::NoopMutex;
13use embassy_sync::blocking_mutex::raw::NoopRawMutex;
14use embassy_time::{Duration, Timer}; 14use embassy_time::{Duration, Timer};
15use embedded_hal_1::i2c::I2c as _; 15use embedded_hal_1::i2c::I2c as _;
16use static_cell::StaticCell; 16use static_cell::StaticCell;
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 12abb8693..f17fb2aaa 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed}; 6use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed};
7use embassy_stm32::time::{khz, Hertz}; 7use embassy_stm32::time::{Hertz, khz};
8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; 8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
9use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin}; 9use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin};
10use embassy_stm32::{Config, Peri}; 10use embassy_stm32::{Config, Peri};
diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs
index a6ee27625..cafcb90f6 100644
--- a/examples/stm32h7/src/bin/mco.rs
+++ b/examples/stm32h7/src/bin/mco.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; 7use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -15,7 +15,13 @@ async fn main(_spawner: Spawner) {
15 15
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 17
18 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); 18 let config = {
19 let mut config = McoConfig::default();
20 config.prescaler = McoPrescaler::DIV8;
21 config
22 };
23
24 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config);
19 25
20 loop { 26 loop {
21 info!("high"); 27 info!("high");
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs
index 2f2ffdea2..8375e0e8e 100644
--- a/examples/stm32h7/src/bin/multiprio.rs
+++ b/examples/stm32h7/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn UART4() { 115unsafe fn UART4() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn UART5() { 120unsafe fn UART5() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index 73b43be69..ffd117580 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -3,10 +3,10 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config;
6use embassy_stm32::gpio::OutputType; 7use embassy_stm32::gpio::OutputType;
7use embassy_stm32::time::khz; 8use embassy_stm32::time::khz;
8use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 9use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
9use embassy_stm32::Config;
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs
index a9ef7200d..489747678 100644
--- a/examples/stm32h7/src/bin/rng.rs
+++ b/examples/stm32h7/src/bin/rng.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rng::Rng; 6use embassy_stm32::rng::Rng;
7use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 7use embassy_stm32::{Config, bind_interrupts, peripherals, rng};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10bind_interrupts!(struct Irqs { 10bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs
index 0adb48877..965716d23 100644
--- a/examples/stm32h7/src/bin/rtc.rs
+++ b/examples/stm32h7/src/bin/rtc.rs
@@ -4,9 +4,9 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config;
7use embassy_stm32::rcc::LsConfig; 8use embassy_stm32::rcc::LsConfig;
8use embassy_stm32::rtc::{Rtc, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_stm32::Config;
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs
index 847b70c85..0300f83bf 100644
--- a/examples/stm32h7/src/bin/sai.rs
+++ b/examples/stm32h7/src/bin/sai.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 tx_config.tx_rx = TxRx::Transmitter; 63 tx_config.tx_rx = TxRx::Transmitter;
64 tx_config.sync_output = true; 64 tx_config.sync_output = true;
65 tx_config.clock_strobe = ClockStrobe::Falling; 65 tx_config.clock_strobe = ClockStrobe::Falling;
66 tx_config.master_clock_divider = Some(mclk_div); 66 tx_config.master_clock_divider = mclk_div;
67 tx_config.stereo_mono = StereoMono::Stereo; 67 tx_config.stereo_mono = StereoMono::Stereo;
68 tx_config.data_size = DataSize::Data24; 68 tx_config.data_size = DataSize::Data24;
69 tx_config.bit_order = BitOrder::MsbFirst; 69 tx_config.bit_order = BitOrder::MsbFirst;
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index 96840d8ff..f2e5bedeb 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -4,8 +4,9 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::sdmmc::Sdmmc; 6use embassy_stm32::sdmmc::Sdmmc;
7use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice};
7use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
11bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -13,7 +14,7 @@ bind_interrupts!(struct Irqs {
13}); 14});
14 15
15#[embassy_executor::main] 16#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! { 17async fn main(_spawner: Spawner) {
17 let mut config = Config::default(); 18 let mut config = Config::default();
18 { 19 {
19 use embassy_stm32::rcc::*; 20 use embassy_stm32::rcc::*;
@@ -53,11 +54,13 @@ async fn main(_spawner: Spawner) -> ! {
53 // Should print 400kHz for initialization 54 // Should print 400kHz for initialization
54 info!("Configured clock: {}", sdmmc.clock().0); 55 info!("Configured clock: {}", sdmmc.clock().0);
55 56
56 unwrap!(sdmmc.init_sd_card(mhz(25)).await); 57 let mut cmd_block = CmdBlock::new();
57 58
58 let card = unwrap!(sdmmc.card()); 59 let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25))
60 .await
61 .unwrap();
59 62
60 info!("Card: {:#?}", Debug2Format(card)); 63 let card = storage.card();
61 64
62 loop {} 65 info!("Card: {:#?}", Debug2Format(&card));
63} 66}
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index dce30a4a7..f7ab20cdd 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -9,13 +9,13 @@ use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::mode::Blocking; 10use embassy_stm32::mode::Blocking;
11use embassy_stm32::time::mhz; 11use embassy_stm32::time::mhz;
12use embassy_stm32::{spi, Config}; 12use embassy_stm32::{Config, spi};
13use heapless::String; 13use heapless::String;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
index 828f687b8..cd9d6c789 100644
--- a/examples/stm32h7/src/bin/spi_bdma.rs
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -9,7 +9,7 @@ use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::mode::Async; 10use embassy_stm32::mode::Async;
11use embassy_stm32::time::mhz; 11use embassy_stm32::time::mhz;
12use embassy_stm32::{spi, Config}; 12use embassy_stm32::{Config, spi};
13use grounded::uninit::GroundedArrayCell; 13use grounded::uninit::GroundedArrayCell;
14use heapless::String; 14use heapless::String;
15use static_cell::StaticCell; 15use static_cell::StaticCell;
@@ -20,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _};
20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); 20static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit();
21 21
22#[embassy_executor::task] 22#[embassy_executor::task]
23async fn main_task(mut spi: spi::Spi<'static, Async>) { 23async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
24 let (read_buffer, write_buffer) = unsafe { 24 let (read_buffer, write_buffer) = unsafe {
25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); 25 let ram = &mut *core::ptr::addr_of_mut!(RAM_D3);
26 ram.initialize_all_copied(0); 26 ram.initialize_all_copied(0);
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 2197fabce..3d3c2f43e 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -9,13 +9,13 @@ use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::mode::Async; 10use embassy_stm32::mode::Async;
11use embassy_stm32::time::mhz; 11use embassy_stm32::time::mhz;
12use embassy_stm32::{spi, Config}; 12use embassy_stm32::{Config, spi};
13use heapless::String; 13use heapless::String;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index 50bb964da..d0470101b 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -5,10 +5,10 @@ use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml
index 7e4ccc528..93a5109e2 100644
--- a/examples/stm32h723/Cargo.toml
+++ b/examples/stm32h723/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h723-examples" 3name = "embassy-stm32h723-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs
index b75a03ae8..959e2aa18 100644
--- a/examples/stm32h723/src/bin/spdifrx.rs
+++ b/examples/stm32h723/src/bin/spdifrx.rs
@@ -7,9 +7,9 @@
7 7
8use defmt::{info, trace}; 8use defmt::{info, trace};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_futures::select::{select, Either}; 10use embassy_futures::select::{Either, select};
11use embassy_stm32::spdifrx::{self, Spdifrx}; 11use embassy_stm32::spdifrx::{self, Spdifrx};
12use embassy_stm32::{bind_interrupts, peripherals, sai, Peri}; 12use embassy_stm32::{Peri, bind_interrupts, peripherals, sai};
13use grounded::uninit::GroundedArrayCell; 13use grounded::uninit::GroundedArrayCell;
14use hal::sai::*; 14use hal::sai::*;
15use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _}; 15use {defmt_rtt as _, embassy_stm32 as hal, panic_probe as _};
@@ -167,8 +167,7 @@ fn new_sai_transmitter<'d>(
167 sai_config.slot_count = hal::sai::word::U4(CHANNEL_COUNT as u8); 167 sai_config.slot_count = hal::sai::word::U4(CHANNEL_COUNT as u8);
168 sai_config.slot_enable = 0xFFFF; // All slots 168 sai_config.slot_enable = 0xFFFF; // All slots
169 sai_config.data_size = sai::DataSize::Data32; 169 sai_config.data_size = sai::DataSize::Data32;
170 sai_config.frame_length = (CHANNEL_COUNT * 32) as u8; 170 sai_config.frame_length = (CHANNEL_COUNT * 32) as u16;
171 sai_config.master_clock_divider = None;
172 171
173 let (sub_block_tx, _) = hal::sai::split_subblocks(sai); 172 let (sub_block_tx, _) = hal::sai::split_subblocks(sai);
174 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) 173 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config)
diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml
index 22b7ad96a..1ad2eeb2e 100644
--- a/examples/stm32h735/Cargo.toml
+++ b/examples/stm32h735/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h735-examples" 3name = "embassy-stm32h735-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32h735/src/bin/ltdc.rs b/examples/stm32h735/src/bin/ltdc.rs
index 8a99f745d..f042e04c2 100644
--- a/examples/stm32h735/src/bin/ltdc.rs
+++ b/examples/stm32h735/src/bin/ltdc.rs
@@ -15,14 +15,14 @@ use embassy_stm32::gpio::{Level, Output, Speed};
15use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; 15use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge};
16use embassy_stm32::{bind_interrupts, peripherals}; 16use embassy_stm32::{bind_interrupts, peripherals};
17use embassy_time::{Duration, Timer}; 17use embassy_time::{Duration, Timer};
18use embedded_graphics::Pixel;
18use embedded_graphics::draw_target::DrawTarget; 19use embedded_graphics::draw_target::DrawTarget;
19use embedded_graphics::geometry::{OriginDimensions, Point, Size}; 20use embedded_graphics::geometry::{OriginDimensions, Point, Size};
20use embedded_graphics::image::Image; 21use embedded_graphics::image::Image;
21use embedded_graphics::pixelcolor::raw::RawU24;
22use embedded_graphics::pixelcolor::Rgb888; 22use embedded_graphics::pixelcolor::Rgb888;
23use embedded_graphics::pixelcolor::raw::RawU24;
23use embedded_graphics::prelude::*; 24use embedded_graphics::prelude::*;
24use embedded_graphics::primitives::Rectangle; 25use embedded_graphics::primitives::Rectangle;
25use embedded_graphics::Pixel;
26use heapless::{Entry, FnvIndexMap}; 26use heapless::{Entry, FnvIndexMap};
27use tinybmp::Bmp; 27use tinybmp::Bmp;
28use {defmt_rtt as _, panic_probe as _}; 28use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml
index c76340b5f..9b5e5d93d 100644
--- a/examples/stm32h742/Cargo.toml
+++ b/examples/stm32h742/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h742-examples" 3name = "embassy-stm32h742-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs
index 9e79d7089..a88c8f249 100644
--- a/examples/stm32h742/src/bin/qspi.rs
+++ b/examples/stm32h742/src/bin/qspi.rs
@@ -4,10 +4,10 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config as StmCfg;
7use embassy_stm32::mode::Blocking; 8use embassy_stm32::mode::Blocking;
8use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *}; 9use embassy_stm32::qspi::enums::{AddressSize, ChipSelectHighTime, FIFOThresholdLevel, MemorySize, *};
9use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig}; 10use embassy_stm32::qspi::{Config as QspiCfg, Instance, Qspi, TransferConfig};
10use embassy_stm32::Config as StmCfg;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13const MEMORY_PAGE_SIZE: usize = 256; 13const MEMORY_PAGE_SIZE: usize = 256;
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index c73f9df79..d69f0228e 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h755cm4-examples" 3name = "embassy-stm32h755cm4-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h755cm4/src/bin/blinky.rs b/examples/stm32h755cm4/src/bin/blinky.rs
index 39112c1f5..0ee3c68dc 100644
--- a/examples/stm32h755cm4/src/bin/blinky.rs
+++ b/examples/stm32h755cm4/src/bin/blinky.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs
index f584e31e9..c0db8cdd3 100644
--- a/examples/stm32h755cm4/src/bin/intercore.rs
+++ b/examples/stm32h755cm4/src/bin/intercore.rs
@@ -85,7 +85,7 @@ mod shared {
85 } 85 }
86 } 86 }
87 87
88 #[link_section = ".ram_d3"] 88 #[unsafe(link_section = ".ram_d3")]
89 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); 89 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
90} 90}
91 91
@@ -93,13 +93,13 @@ use core::mem::MaybeUninit;
93 93
94use defmt::*; 94use defmt::*;
95use embassy_executor::Spawner; 95use embassy_executor::Spawner;
96use embassy_stm32::gpio::{Level, Output, Speed};
97use embassy_stm32::SharedData; 96use embassy_stm32::SharedData;
97use embassy_stm32::gpio::{Level, Output, Speed};
98use embassy_time::Timer; 98use embassy_time::Timer;
99use shared::SHARED_LED_STATE; 99use shared::SHARED_LED_STATE;
100use {defmt_rtt as _, panic_probe as _}; 100use {defmt_rtt as _, panic_probe as _};
101 101
102#[link_section = ".ram_d3"] 102#[unsafe(link_section = ".ram_d3")]
103static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 103static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
104 104
105/// Task that continuously blinks the red LED as a heartbeat indicator 105/// Task that continuously blinks the red LED as a heartbeat indicator
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml
index c34d4e45c..f4e1e53b7 100644
--- a/examples/stm32h755cm7/Cargo.toml
+++ b/examples/stm32h755cm7/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h755cm7-examples" 3name = "embassy-stm32h755cm7-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -30,7 +30,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.4.0"
34embedded-storage = "0.3.1" 34embedded-storage = "0.3.1"
35static_cell = "2" 35static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h755cm7/src/bin/blinky.rs b/examples/stm32h755cm7/src/bin/blinky.rs
index b30bf4de8..e8f5a1c43 100644
--- a/examples/stm32h755cm7/src/bin/blinky.rs
+++ b/examples/stm32h755cm7/src/bin/blinky.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs
index a4e1b5ff4..3df0b26d7 100644
--- a/examples/stm32h755cm7/src/bin/intercore.rs
+++ b/examples/stm32h755cm7/src/bin/intercore.rs
@@ -97,7 +97,7 @@ mod shared {
97 } 97 }
98 } 98 }
99 99
100 #[link_section = ".ram_d3"] 100 #[unsafe(link_section = ".ram_d3")]
101 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new(); 101 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
102 102
103 // Memory region constants for MPU configuration 103 // Memory region constants for MPU configuration
@@ -106,7 +106,7 @@ mod shared {
106 pub const SRAM4_REGION_NUMBER: u8 = 0; 106 pub const SRAM4_REGION_NUMBER: u8 = 0;
107} 107}
108 108
109#[link_section = ".ram_d3"] 109#[unsafe(link_section = ".ram_d3")]
110static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 110static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
111 111
112/// Configure MPU to make SRAM4 region non-cacheable 112/// Configure MPU to make SRAM4 region non-cacheable
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml
index 1917749c5..0509d394d 100644
--- a/examples/stm32h7b0/Cargo.toml
+++ b/examples/stm32h7b0/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h7b0-examples" 3name = "embassy-stm32h7b0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs b/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs
index dffb740a9..865062f4b 100644
--- a/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs
+++ b/examples/stm32h7b0/src/bin/ospi_memory_mapped.rs
@@ -5,6 +5,7 @@
5 5
6use defmt::info; 6use defmt::info;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::Config;
8use embassy_stm32::gpio::{Level, Output, Speed}; 9use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::mode::Blocking; 10use embassy_stm32::mode::Blocking;
10use embassy_stm32::ospi::{ 11use embassy_stm32::ospi::{
@@ -12,7 +13,6 @@ use embassy_stm32::ospi::{
12 OspiWidth, TransferConfig, WrapSize, 13 OspiWidth, TransferConfig, WrapSize,
13}; 14};
14use embassy_stm32::time::Hertz; 15use embassy_stm32::time::Hertz;
15use embassy_stm32::Config;
16use embassy_time::Timer; 16use embassy_time::Timer;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml
index bfe59b68d..ab525ad91 100644
--- a/examples/stm32h7rs/Cargo.toml
+++ b/examples/stm32h7rs/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32h7rs-examples" 3name = "embassy-stm32h7rs-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -29,7 +29,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.4.0"
33embedded-storage = "0.3.1" 33embedded-storage = "0.3.1"
34static_cell = "2" 34static_cell = "2"
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs
index 5fd50fb15..4c0864ff6 100644
--- a/examples/stm32h7rs/src/bin/blinky.rs
+++ b/examples/stm32h7rs/src/bin/blinky.rs
@@ -3,9 +3,9 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config;
6use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::time::Hertz; 8use embassy_stm32::time::Hertz;
8use embassy_stm32::Config;
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
diff --git a/examples/stm32h7rs/src/bin/button_exti.rs b/examples/stm32h7rs/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32h7rs/src/bin/button_exti.rs
+++ b/examples/stm32h7rs/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h7rs/src/bin/can.rs b/examples/stm32h7rs/src/bin/can.rs
index 0af11ef3e..49830f9b7 100644
--- a/examples/stm32h7rs/src/bin/can.rs
+++ b/examples/stm32h7rs/src/bin/can.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::peripherals::*; 6use embassy_stm32::peripherals::*;
7use embassy_stm32::{bind_interrupts, can, rcc, Config}; 7use embassy_stm32::{Config, bind_interrupts, can, rcc};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs
index 67f541564..8e07d0a67 100644
--- a/examples/stm32h7rs/src/bin/eth.rs
+++ b/examples/stm32h7rs/src/bin/eth.rs
@@ -5,10 +5,10 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::udp::{PacketMetadata, UdpSocket}; 6use embassy_net::udp::{PacketMetadata, UdpSocket};
7use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; 7use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources};
8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; 8use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue, Sma};
9use embassy_stm32::peripherals::ETH; 9use embassy_stm32::peripherals::{ETH, ETH_SMA};
10use embassy_stm32::rng::Rng; 10use embassy_stm32::rng::Rng;
11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 11use embassy_stm32::{Config, bind_interrupts, eth, peripherals, rng};
12use embassy_time::Timer; 12use embassy_time::Timer;
13use heapless::Vec; 13use heapless::Vec;
14use static_cell::StaticCell; 14use static_cell::StaticCell;
@@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs {
19 RNG => rng::InterruptHandler<peripherals::RNG>; 19 RNG => rng::InterruptHandler<peripherals::RNG>;
20}); 20});
21 21
22type Device = Ethernet<'static, ETH, GenericPhy>; 22type Device = Ethernet<'static, ETH, GenericPhy<Sma<'static, ETH_SMA>>>;
23 23
24#[embassy_executor::task] 24#[embassy_executor::task]
25async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { 25async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! {
@@ -69,16 +69,16 @@ async fn main(spawner: Spawner) -> ! {
69 p.ETH, 69 p.ETH,
70 Irqs, 70 Irqs,
71 p.PB6, 71 p.PB6,
72 p.PA2,
73 p.PG6,
74 p.PA7, 72 p.PA7,
75 p.PG4, 73 p.PG4,
76 p.PG5, 74 p.PG5,
77 p.PG13, 75 p.PG13,
78 p.PG12, 76 p.PG12,
79 p.PG11, 77 p.PG11,
80 GenericPhy::new(0),
81 mac_addr, 78 mac_addr,
79 p.ETH_SMA,
80 p.PA2,
81 p.PG6,
82 ); 82 );
83 83
84 // Have to use UDP w/ static config to fit in internal flash 84 // Have to use UDP w/ static config to fit in internal flash
diff --git a/examples/stm32h7rs/src/bin/mco.rs b/examples/stm32h7rs/src/bin/mco.rs
index a6ee27625..cafcb90f6 100644
--- a/examples/stm32h7rs/src/bin/mco.rs
+++ b/examples/stm32h7rs/src/bin/mco.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; 7use embassy_stm32::rcc::{Mco, Mco1Source, McoConfig, McoPrescaler};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -15,7 +15,13 @@ async fn main(_spawner: Spawner) {
15 15
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 17
18 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); 18 let config = {
19 let mut config = McoConfig::default();
20 config.prescaler = McoPrescaler::DIV8;
21 config
22 };
23
24 let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, config);
19 25
20 loop { 26 loop {
21 info!("high"); 27 info!("high");
diff --git a/examples/stm32h7rs/src/bin/multiprio.rs b/examples/stm32h7rs/src/bin/multiprio.rs
index 2f2ffdea2..8375e0e8e 100644
--- a/examples/stm32h7rs/src/bin/multiprio.rs
+++ b/examples/stm32h7rs/src/bin/multiprio.rs
@@ -113,12 +113,12 @@ static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
113 113
114#[interrupt] 114#[interrupt]
115unsafe fn UART4() { 115unsafe fn UART4() {
116 EXECUTOR_HIGH.on_interrupt() 116 unsafe { EXECUTOR_HIGH.on_interrupt() }
117} 117}
118 118
119#[interrupt] 119#[interrupt]
120unsafe fn UART5() { 120unsafe fn UART5() {
121 EXECUTOR_MED.on_interrupt() 121 unsafe { EXECUTOR_MED.on_interrupt() }
122} 122}
123 123
124#[entry] 124#[entry]
diff --git a/examples/stm32h7rs/src/bin/rng.rs b/examples/stm32h7rs/src/bin/rng.rs
index a9ef7200d..489747678 100644
--- a/examples/stm32h7rs/src/bin/rng.rs
+++ b/examples/stm32h7rs/src/bin/rng.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rng::Rng; 6use embassy_stm32::rng::Rng;
7use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 7use embassy_stm32::{Config, bind_interrupts, peripherals, rng};
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10bind_interrupts!(struct Irqs { 10bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h7rs/src/bin/rtc.rs b/examples/stm32h7rs/src/bin/rtc.rs
index 0adb48877..965716d23 100644
--- a/examples/stm32h7rs/src/bin/rtc.rs
+++ b/examples/stm32h7rs/src/bin/rtc.rs
@@ -4,9 +4,9 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config;
7use embassy_stm32::rcc::LsConfig; 8use embassy_stm32::rcc::LsConfig;
8use embassy_stm32::rtc::{Rtc, RtcConfig}; 9use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_stm32::Config;
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) {
23 .and_hms_opt(10, 30, 15) 23 .and_hms_opt(10, 30, 15)
24 .unwrap(); 24 .unwrap();
25 25
26 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 26 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
27 info!("Got RTC! {:?}", now.and_utc().timestamp()); 27 info!("Got RTC! {:?}", now.and_utc().timestamp());
28 28
29 rtc.set_datetime(now.into()).expect("datetime not set"); 29 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -31,6 +31,6 @@ async fn main(_spawner: Spawner) {
31 // In reality the delay would be much longer 31 // In reality the delay would be much longer
32 Timer::after_millis(20000).await; 32 Timer::after_millis(20000).await;
33 33
34 let then: NaiveDateTime = rtc.now().unwrap().into(); 34 let then: NaiveDateTime = time_provider.now().unwrap().into();
35 info!("Got RTC! {:?}", then.and_utc().timestamp()); 35 info!("Got RTC! {:?}", then.and_utc().timestamp());
36} 36}
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs
index 8c280fdae..3253304eb 100644
--- a/examples/stm32h7rs/src/bin/spi.rs
+++ b/examples/stm32h7rs/src/bin/spi.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Blocking>) { 18async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 21 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs
index 3fa69fd15..ca644c6a8 100644
--- a/examples/stm32h7rs/src/bin/spi_dma.rs
+++ b/examples/stm32h7rs/src/bin/spi_dma.rs
@@ -15,7 +15,7 @@ use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
18async fn main_task(mut spi: spi::Spi<'static, Async>) { 18async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) {
19 for n in 0u32.. { 19 for n in 0u32.. {
20 let mut write: String<128> = String::new(); 20 let mut write: String<128> = String::new();
21 let mut read = [0; 128]; 21 let mut read = [0; 128];
diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs
index 23abc3e2f..3e295dd51 100644
--- a/examples/stm32h7rs/src/bin/usb_serial.rs
+++ b/examples/stm32h7rs/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz; 7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
index 4c1b450b4..d91ae9de0 100644
--- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
+++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
@@ -8,6 +8,7 @@ use core::cmp::min;
8 8
9use defmt::info; 9use defmt::info;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::Config;
11use embassy_stm32::gpio::{Level, Output, Speed}; 12use embassy_stm32::gpio::{Level, Output, Speed};
12use embassy_stm32::mode::Blocking; 13use embassy_stm32::mode::Blocking;
13use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
@@ -15,7 +16,6 @@ use embassy_stm32::xspi::{
15 AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, Instance, MemorySize, MemoryType, TransferConfig, 16 AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, Instance, MemorySize, MemoryType, TransferConfig,
16 WrapSize, Xspi, XspiWidth, 17 WrapSize, Xspi, XspiWidth,
17}; 18};
18use embassy_stm32::Config;
19use embassy_time::Timer; 19use embassy_time::Timer;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
21 21
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index d42cdac15..a9c71d655 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32l0-examples" 3name = "embassy-stm32l0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs
index 9dd09bc45..83be74ed9 100644
--- a/examples/stm32l0/src/bin/adc.rs
+++ b/examples/stm32l0/src/bin/adc.rs
@@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) {
19 info!("Hello World!"); 19 info!("Hello World!");
20 20
21 let mut adc = Adc::new(p.ADC1, Irqs); 21 let mut adc = Adc::new(p.ADC1, Irqs);
22 adc.set_sample_time(SampleTime::CYCLES79_5);
23 let mut pin = p.PA1; 22 let mut pin = p.PA1;
24 23
25 let mut vrefint = adc.enable_vref(); 24 let mut vrefint = adc.enable_vref();
26 let vrefint_sample = adc.read(&mut vrefint).await; 25 let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES79_5).await;
27 let convert_to_millivolts = |sample| { 26 let convert_to_millivolts = |sample| {
28 // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf 27 // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf
29 // 6.3.3 Embedded internal reference voltage 28 // 6.3.3 Embedded internal reference voltage
@@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) {
33 }; 32 };
34 33
35 loop { 34 loop {
36 let v = adc.read(&mut pin).await; 35 let v = adc.read(&mut pin, SampleTime::CYCLES79_5).await;
37 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 36 info!("--> {} - {} mV", v, convert_to_millivolts(v));
38 Timer::after_millis(100).await; 37 Timer::after_millis(100).await;
39 } 38 }
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index 4945da7ce..a118c7a5a 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -3,17 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::Config; 8use embassy_stm32::{Config, bind_interrupts, interrupt};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>;
14});
15
11#[embassy_executor::main] 16#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
13 let config = Config::default(); 18 let config = Config::default();
14 let p = embassy_stm32::init(config); 19 let p = embassy_stm32::init(config);
15 20
16 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 21 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
17 22
18 info!("Press the USER button..."); 23 info!("Press the USER button...");
19 24
diff --git a/examples/stm32l0/src/bin/dds.rs b/examples/stm32l0/src/bin/dds.rs
index eaa7a61a8..d8f9020d4 100644
--- a/examples/stm32l0/src/bin/dds.rs
+++ b/examples/stm32l0/src/bin/dds.rs
@@ -12,7 +12,7 @@ use embassy_stm32::time::hz;
12use embassy_stm32::timer::low_level::{Timer as LLTimer, *}; 12use embassy_stm32::timer::low_level::{Timer as LLTimer, *};
13use embassy_stm32::timer::simple_pwm::PwmPin; 13use embassy_stm32::timer::simple_pwm::PwmPin;
14use embassy_stm32::timer::{Ch3, Channel}; 14use embassy_stm32::timer::{Ch3, Channel};
15use embassy_stm32::{interrupt, pac, Config}; 15use embassy_stm32::{Config, interrupt, pac};
16use panic_probe as _; 16use panic_probe as _;
17 17
18const DDS_SINE_DATA: [u8; 256] = [ 18const DDS_SINE_DATA: [u8; 256] = [
diff --git a/examples/stm32l0/src/bin/eeprom.rs b/examples/stm32l0/src/bin/eeprom.rs
index 370246644..a33088f36 100644
--- a/examples/stm32l0/src/bin/eeprom.rs
+++ b/examples/stm32l0/src/bin/eeprom.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; 6use embassy_stm32::flash::{EEPROM_BASE, EEPROM_SIZE, Flash};
7use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
8 8
9#[embassy_executor::main] 9#[embassy_executor::main]
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs
index 6385e3c8f..8e8fe0240 100644
--- a/examples/stm32l0/src/bin/raw_spawn.rs
+++ b/examples/stm32l0/src/bin/raw_spawn.rs
@@ -5,8 +5,8 @@ use core::mem;
5 5
6use cortex_m_rt::entry; 6use cortex_m_rt::entry;
7use defmt::*; 7use defmt::*;
8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 8use embassy_executor::Executor;
9use embassy_executor::raw::TaskStorage;
10use embassy_time::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 _};
@@ -48,5 +48,5 @@ fn main() -> ! {
48} 48}
49 49
50unsafe fn make_static<T>(t: &T) -> &'static T { 50unsafe fn make_static<T>(t: &T) -> &'static T {
51 mem::transmute(t) 51 unsafe { mem::transmute(t) }
52} 52}
diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs
index fdb1aeb59..612082f29 100644
--- a/examples/stm32l0/src/bin/usb_serial.rs
+++ b/examples/stm32l0/src/bin/usb_serial.rs
@@ -6,9 +6,9 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{self, Driver, Instance}; 7use embassy_stm32::usb::{self, Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals}; 8use embassy_stm32::{bind_interrupts, peripherals};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index 76ceade9c..7f6b31ed5 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32l1-examples" 3name = "embassy-stm32l1-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32l1/src/bin/eeprom.rs b/examples/stm32l1/src/bin/eeprom.rs
index 370246644..a33088f36 100644
--- a/examples/stm32l1/src/bin/eeprom.rs
+++ b/examples/stm32l1/src/bin/eeprom.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE}; 6use embassy_stm32::flash::{EEPROM_BASE, EEPROM_SIZE, Flash};
7use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
8 8
9#[embassy_executor::main] 9#[embassy_executor::main]
diff --git a/examples/stm32l1/src/bin/usb_serial.rs b/examples/stm32l1/src/bin/usb_serial.rs
index a35f1d7a7..c54d37f9d 100644
--- a/examples/stm32l1/src/bin/usb_serial.rs
+++ b/examples/stm32l1/src/bin/usb_serial.rs
@@ -6,9 +6,9 @@ use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{self, Driver, Instance}; 7use embassy_stm32::usb::{self, Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals}; 8use embassy_stm32::{bind_interrupts, peripherals};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 1b7f15b1d..936472199 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32l4-examples" 3name = "embassy-stm32l4-examples"
4version = "0.1.1" 4version = "0.1.1"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs
index c557ac6d7..42766a5e3 100644
--- a/examples/stm32l4/src/bin/adc.rs
+++ b/examples/stm32l4/src/bin/adc.rs
@@ -2,8 +2,8 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{Adc, Resolution};
6use embassy_stm32::Config; 5use embassy_stm32::Config;
6use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime};
7use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
8 8
9#[cortex_m_rt::entry] 9#[cortex_m_rt::entry]
@@ -17,13 +17,16 @@ fn main() -> ! {
17 } 17 }
18 let p = embassy_stm32::init(config); 18 let p = embassy_stm32::init(config);
19 19
20 let mut adc = Adc::new(p.ADC1); 20 let mut config = AdcConfig::default();
21 config.resolution = Some(Resolution::BITS8);
22
23 let mut adc = Adc::new_with_config(p.ADC1, config);
21 //adc.enable_vref(); 24 //adc.enable_vref();
22 adc.set_resolution(Resolution::BITS8); 25
23 let mut channel = p.PC0; 26 let mut channel = p.PC0;
24 27
25 loop { 28 loop {
26 let v = adc.blocking_read(&mut channel); 29 let v = adc.blocking_read(&mut channel, SampleTime::from_bits(0));
27 info!("--> {}", v); 30 info!("--> {}", v);
28 } 31 }
29} 32}
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs
new file mode 100644
index 000000000..550da95a4
--- /dev/null
+++ b/examples/stm32l4/src/bin/adc_dma.rs
@@ -0,0 +1,48 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::adc::{Adc, AdcChannel, RegularConversionMode, SampleTime};
8use {defmt_rtt as _, panic_probe as _};
9
10const DMA_BUF_LEN: usize = 512;
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 info!("Hello World!");
15
16 let mut config = Config::default();
17 {
18 use embassy_stm32::rcc::*;
19 config.rcc.mux.adcsel = mux::Adcsel::SYS;
20 }
21 let p = embassy_stm32::init(config);
22
23 let adc = Adc::new(p.ADC1);
24 let adc_pin0 = p.PA0.degrade_adc();
25 let adc_pin1 = p.PA1.degrade_adc();
26 let mut adc_dma_buf = [0u16; DMA_BUF_LEN];
27 let mut measurements = [0u16; DMA_BUF_LEN / 2];
28 let mut ring_buffered_adc = adc.into_ring_buffered(
29 p.DMA1_CH1,
30 &mut adc_dma_buf,
31 [(adc_pin0, SampleTime::CYCLES640_5), (adc_pin1, SampleTime::CYCLES640_5)].into_iter(),
32 RegularConversionMode::Continuous,
33 );
34
35 info!("starting measurement loop");
36 loop {
37 match ring_buffered_adc.read(&mut measurements).await {
38 Ok(_) => {
39 //note: originally there was a print here showing all the samples,
40 //but even that takes too much time and would cause adc overruns
41 info!("adc1 first 10 samples: {}", measurements[0..10]);
42 }
43 Err(e) => {
44 warn!("Error: {:?}", e);
45 }
46 }
47 }
48}
diff --git a/examples/stm32l4/src/bin/button_exti.rs b/examples/stm32l4/src/bin/button_exti.rs
index 34a08bbc6..c84b11dab 100644
--- a/examples/stm32l4/src/bin/button_exti.rs
+++ b/examples/stm32l4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32l4/src/bin/can.rs b/examples/stm32l4/src/bin/can.rs
index 3c4cdac24..bd361417e 100644
--- a/examples/stm32l4/src/bin/can.rs
+++ b/examples/stm32l4/src/bin/can.rs
@@ -8,7 +8,7 @@ use embassy_stm32::can::{
8 Can, Fifo, Frame, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, 8 Can, Fifo, Frame, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler,
9}; 9};
10use embassy_stm32::peripherals::CAN1; 10use embassy_stm32::peripherals::CAN1;
11use embassy_stm32::{bind_interrupts, Config}; 11use embassy_stm32::{Config, bind_interrupts};
12use embassy_time::Timer; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index 44edec728..bfdf858c5 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -3,6 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Peri;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 7use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async; 8use embassy_stm32::mode::Async;
8use embassy_stm32::pac::timer::vals::Mms; 9use embassy_stm32::pac::timer::vals::Mms;
@@ -10,7 +11,6 @@ use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
10use embassy_stm32::rcc::frequency; 11use embassy_stm32::rcc::frequency;
11use embassy_stm32::time::Hertz; 12use embassy_stm32::time::Hertz;
12use embassy_stm32::timer::low_level::Timer; 13use embassy_stm32::timer::low_level::Timer;
13use embassy_stm32::Peri;
14use micromath::F32Ext; 14use micromath::F32Ext;
15use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
16 16
diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs
index 36c002952..4cdeaa440 100644
--- a/examples/stm32l4/src/bin/mco.rs
+++ b/examples/stm32l4/src/bin/mco.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource}; 7use embassy_stm32::rcc::{Mco, McoConfig, McoPrescaler, McoSource};
8use embassy_time::Timer; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
@@ -13,7 +13,13 @@ async fn main(_spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
14 info!("Hello World!"); 14 info!("Hello World!");
15 15
16 let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI, McoPrescaler::DIV1); 16 let config = {
17 let mut config = McoConfig::default();
18 config.prescaler = McoPrescaler::DIV1;
19 config
20 };
21
22 let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI, config);
17 23
18 let mut led = Output::new(p.PB14, Level::High, Speed::Low); 24 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
19 25
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs
index 14d0e3c1e..4d9f83ad8 100644
--- a/examples/stm32l4/src/bin/rng.rs
+++ b/examples/stm32l4/src/bin/rng.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk}; 6use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource, Sysclk};
7use embassy_stm32::rng::Rng; 7use embassy_stm32::rng::Rng;
8use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, rng};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs { 11bind_interrupts!(struct Irqs {
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index f554f0f78..8b92075cc 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -4,9 +4,9 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config;
7use embassy_stm32::rtc::{Rtc, RtcConfig}; 8use embassy_stm32::rtc::{Rtc, RtcConfig};
8use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
9use embassy_stm32::Config;
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
@@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) {
39 .and_hms_opt(10, 30, 15) 39 .and_hms_opt(10, 30, 15)
40 .unwrap(); 40 .unwrap();
41 41
42 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 42 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
43 info!("Got RTC! {:?}", now.and_utc().timestamp()); 43 info!("Got RTC! {:?}", now.and_utc().timestamp());
44 44
45 rtc.set_datetime(now.into()).expect("datetime not set"); 45 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -47,6 +47,6 @@ async fn main(_spawner: Spawner) {
47 // In reality the delay would be much longer 47 // In reality the delay would be much longer
48 Timer::after_millis(20000).await; 48 Timer::after_millis(20000).await;
49 49
50 let then: NaiveDateTime = rtc.now().unwrap().into(); 50 let then: NaiveDateTime = time_provider.now().unwrap().into();
51 info!("Got RTC! {:?}", then.and_utc().timestamp()); 51 info!("Got RTC! {:?}", then.and_utc().timestamp());
52} 52}
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 24efe526f..8f2510cdc 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -16,21 +16,23 @@
16use core::marker::PhantomData; 16use core::marker::PhantomData;
17use core::sync::atomic::{AtomicI32, Ordering}; 17use core::sync::atomic::{AtomicI32, Ordering};
18 18
19use defmt::{error, info, println, unwrap, Format}; 19use defmt::{Format, error, info, println, unwrap};
20use defmt_rtt as _; // global logger 20use defmt_rtt as _; // global logger
21use embassy_executor::Spawner; 21use embassy_executor::Spawner;
22use embassy_futures::select::{select, Either}; 22use embassy_futures::select::{Either, select};
23use embassy_futures::yield_now; 23use embassy_futures::yield_now;
24use embassy_net::tcp::TcpSocket; 24use embassy_net::tcp::TcpSocket;
25use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; 25use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4};
26use embassy_net_adin1110::{Device, Runner, ADIN1110}; 26use embassy_net_adin1110::{ADIN1110, Device, Runner};
27use embassy_stm32::exti::ExtiInput;
27use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; 28use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; 29use embassy_stm32::i2c::{self, Config as I2C_Config, I2c};
29use embassy_stm32::mode::Async; 30use embassy_stm32::mode::Async;
30use embassy_stm32::rng::{self, Rng}; 31use embassy_stm32::rng::{self, Rng};
32use embassy_stm32::spi::mode::Master;
31use embassy_stm32::spi::{Config as SPI_Config, Spi}; 33use embassy_stm32::spi::{Config as SPI_Config, Spi};
32use embassy_stm32::time::Hertz; 34use embassy_stm32::time::Hertz;
33use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; 35use embassy_stm32::{bind_interrupts, exti, interrupt, pac, peripherals};
34use embassy_time::{Delay, Duration, Ticker, Timer}; 36use embassy_time::{Delay, Duration, Ticker, Timer};
35use embedded_hal_async::i2c::I2c as I2cBus; 37use embedded_hal_async::i2c::I2c as I2cBus;
36use embedded_hal_bus::spi::ExclusiveDevice; 38use embedded_hal_bus::spi::ExclusiveDevice;
@@ -44,6 +46,7 @@ bind_interrupts!(struct Irqs {
44 I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; 46 I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>;
45 I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; 47 I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>;
46 RNG => rng::InterruptHandler<peripherals::RNG>; 48 RNG => rng::InterruptHandler<peripherals::RNG>;
49 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
47}); 50});
48 51
49// Basic settings 52// Basic settings
@@ -54,7 +57,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 5), 24)
54// Listen port for the webserver 57// Listen port for the webserver
55const HTTP_LISTEN_PORT: u16 = 80; 58const HTTP_LISTEN_PORT: u16 = 80;
56 59
57pub type SpeSpi = Spi<'static, Async>; 60pub type SpeSpi = Spi<'static, Async, Master>;
58pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; 61pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
59pub type SpeInt = exti::ExtiInput<'static>; 62pub type SpeInt = exti::ExtiInput<'static>;
60pub type SpeRst = Output<'static>; 63pub type SpeRst = Output<'static>;
@@ -124,7 +127,7 @@ async fn main(spawner: Spawner) {
124 let spe_cfg1 = Input::new(dp.PC9, Pull::None); 127 let spe_cfg1 = Input::new(dp.PC9, Pull::None);
125 let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); 128 let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low);
126 129
127 let spe_int = exti::ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None); 130 let spe_int = ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None, Irqs);
128 131
129 let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); 132 let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High);
130 let spe_spi_sclk = dp.PB13; 133 let spe_spi_sclk = dp.PB13;
@@ -159,7 +162,9 @@ async fn main(spawner: Spawner) {
159 162
160 // Check the SPI mode selected with the "HW CFG" dip-switch 163 // Check the SPI mode selected with the "HW CFG" dip-switch
161 if !cfg1_spi_mode { 164 if !cfg1_spi_mode {
162 error!("Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\""); 165 error!(
166 "Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\""
167 );
163 loop { 168 loop {
164 led_uc2_red.toggle(); 169 led_uc2_red.toggle();
165 Timer::after(Duration::from_hz(10)).await; 170 Timer::after(Duration::from_hz(10)).await;
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs
index 946a759b1..970a0c608 100644
--- a/examples/stm32l4/src/bin/spi_dma.rs
+++ b/examples/stm32l4/src/bin/spi_dma.rs
@@ -34,8 +34,8 @@ async fn main(_spawner: Spawner) {
34 info!("waiting for ready"); 34 info!("waiting for ready");
35 } 35 }
36 36
37 let write = [0x0A; 10]; 37 let write = [0x0Au8; 10];
38 let mut read = [0; 10]; 38 let mut read = [0u8; 10];
39 cs.set_low(); 39 cs.set_low();
40 spi.transfer(&mut read, &write).await.ok(); 40 spi.transfer(&mut read, &write).await.ok();
41 cs.set_high(); 41 cs.set_high();
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index af90e297e..17cd107f6 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use panic_probe as _; 13use panic_probe as _;
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml
index f173c651e..14f41992d 100644
--- a/examples/stm32l432/Cargo.toml
+++ b/examples/stm32l432/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32l432-examples" 3name = "embassy-stm32l432-examples"
4version = "0.1.1" 4version = "0.1.1"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 9999300b8..586b00836 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32l5-examples" 3name = "embassy-stm32l5-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -14,7 +14,7 @@ embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["de
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17usbd-hid = "0.8.1" 17usbd-hid = "0.9.0"
18 18
19defmt = "1.0.1" 19defmt = "1.0.1"
20defmt-rtt = "1.0.0" 20defmt-rtt = "1.0.0"
diff --git a/examples/stm32l5/src/bin/button_exti.rs b/examples/stm32l5/src/bin/button_exti.rs
index e6639d22b..225a7b3fd 100644
--- a/examples/stm32l5/src/bin/button_exti.rs
+++ b/examples/stm32l5/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs
index 0a644e73d..d6302e106 100644
--- a/examples/stm32l5/src/bin/rng.rs
+++ b/examples/stm32l5/src/bin/rng.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, PllSource, Sysclk}; 6use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, PllSource, Sysclk};
7use embassy_stm32::rng::Rng; 7use embassy_stm32::rng::Rng;
8use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, rng};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs { 11bind_interrupts!(struct Irqs {
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index c34053190..fde804fb7 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -4,22 +4,12 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; 6use embassy_stm32::gpio::{AnyPin, Level, Output, Speed};
7use embassy_stm32::low_power::Executor;
8use embassy_stm32::rcc::LsConfig; 7use embassy_stm32::rcc::LsConfig;
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 8use embassy_stm32::{Config, Peri, low_power};
10use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 9use embassy_time::Timer;
12use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
14 11
15#[cortex_m_rt::entry] 12#[embassy_executor::main(executor = "low_power::Executor")]
16fn main() -> ! {
17 Executor::take().run(|spawner| {
18 spawner.spawn(unwrap!(async_main(spawner)));
19 })
20}
21
22#[embassy_executor::task]
23async fn async_main(spawner: Spawner) { 13async fn async_main(spawner: Spawner) {
24 let mut config = Config::default(); 14 let mut config = Config::default();
25 config.rcc.ls = LsConfig::default_lsi(); 15 config.rcc.ls = LsConfig::default_lsi();
@@ -28,12 +18,6 @@ async fn async_main(spawner: Spawner) {
28 // config.enable_debug_during_sleep = false; 18 // config.enable_debug_during_sleep = false;
29 let p = embassy_stm32::init(config); 19 let p = embassy_stm32::init(config);
30 20
31 // give the RTC to the executor...
32 let rtc = Rtc::new(p.RTC, RtcConfig::default());
33 static RTC: StaticCell<Rtc> = StaticCell::new();
34 let rtc = RTC.init(rtc);
35 embassy_stm32::low_power::stop_with_rtc(rtc);
36
37 spawner.spawn(unwrap!(blinky(p.PC7.into()))); 21 spawner.spawn(unwrap!(blinky(p.PC7.into())));
38 spawner.spawn(unwrap!(timeout())); 22 spawner.spawn(unwrap!(timeout()));
39} 23}
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 25aa9ef69..d2cbeb550 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -3,11 +3,11 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_net::tcp::TcpSocket;
7use embassy_net::StackResources; 6use embassy_net::StackResources;
7use embassy_net::tcp::TcpSocket;
8use embassy_stm32::rng::Rng; 8use embassy_stm32::rng::Rng;
9use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
10use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals, rng, usb};
11use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 11use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
12use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 12use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
13use embassy_usb::{Builder, UsbDevice}; 13use embassy_usb::{Builder, UsbDevice};
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index 3f8c52b82..d8f2de941 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -1,15 +1,19 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::sync::atomic::{AtomicU8, Ordering};
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_futures::join::join; 8use embassy_futures::join::join;
7use embassy_stm32::usb::Driver; 9use embassy_stm32::usb::Driver;
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 10use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_time::Timer; 11use embassy_time::Timer;
10use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
11use embassy_usb::control::OutResponse;
12use embassy_usb::Builder; 12use embassy_usb::Builder;
13use embassy_usb::class::hid::{
14 HidBootProtocol, HidProtocolMode, HidSubclass, HidWriter, ReportId, RequestHandler, State,
15};
16use embassy_usb::control::OutResponse;
13use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; 17use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
14use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
15 19
@@ -17,6 +21,8 @@ bind_interrupts!(struct Irqs {
17 USB_FS => usb::InterruptHandler<peripherals::USB>; 21 USB_FS => usb::InterruptHandler<peripherals::USB>;
18}); 22});
19 23
24static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
25
20#[embassy_executor::main] 26#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
22 let mut config = Config::default(); 28 let mut config = Config::default();
@@ -48,6 +54,10 @@ async fn main(_spawner: Spawner) {
48 config.serial_number = Some("12345678"); 54 config.serial_number = Some("12345678");
49 config.max_power = 100; 55 config.max_power = 100;
50 config.max_packet_size_0 = 64; 56 config.max_packet_size_0 = 64;
57 config.composite_with_iads = false;
58 config.device_class = 0;
59 config.device_sub_class = 0;
60 config.device_protocol = 0;
51 61
52 // Create embassy-usb DeviceBuilder using the driver and config. 62 // Create embassy-usb DeviceBuilder using the driver and config.
53 // It needs some buffers for building the descriptors. 63 // It needs some buffers for building the descriptors.
@@ -73,6 +83,8 @@ async fn main(_spawner: Spawner) {
73 request_handler: Some(&mut request_handler), 83 request_handler: Some(&mut request_handler),
74 poll_ms: 60, 84 poll_ms: 60,
75 max_packet_size: 8, 85 max_packet_size: 8,
86 hid_subclass: HidSubclass::Boot,
87 hid_boot_protocol: HidBootProtocol::Mouse,
76 }; 88 };
77 89
78 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config); 90 let mut writer = HidWriter::<_, 5>::new(&mut builder, &mut state, config);
@@ -90,16 +102,26 @@ async fn main(_spawner: Spawner) {
90 Timer::after_millis(500).await; 102 Timer::after_millis(500).await;
91 103
92 y = -y; 104 y = -y;
93 let report = MouseReport { 105
94 buttons: 0, 106 if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
95 x: 0, 107 let buttons = 0u8;
96 y, 108 let x = 0i8;
97 wheel: 0, 109 match writer.write(&[buttons, x as u8, y as u8]).await {
98 pan: 0, 110 Ok(()) => {}
99 }; 111 Err(e) => warn!("Failed to send boot report: {:?}", e),
100 match writer.write_serialize(&report).await { 112 }
101 Ok(()) => {} 113 } else {
102 Err(e) => warn!("Failed to send report: {:?}", e), 114 let report = MouseReport {
115 buttons: 0,
116 x: 0,
117 y,
118 wheel: 0,
119 pan: 0,
120 };
121 match writer.write_serialize(&report).await {
122 Ok(()) => {}
123 Err(e) => warn!("Failed to send report: {:?}", e),
124 }
103 } 125 }
104 } 126 }
105 }; 127 };
@@ -122,6 +144,18 @@ impl RequestHandler for MyRequestHandler {
122 OutResponse::Accepted 144 OutResponse::Accepted
123 } 145 }
124 146
147 fn get_protocol(&self) -> HidProtocolMode {
148 let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
149 info!("The current HID protocol mode is: {}", protocol);
150 protocol
151 }
152
153 fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
154 info!("Switching to HID protocol mode: {}", protocol);
155 HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
156 OutResponse::Accepted
157 }
158
125 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) { 159 fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
126 info!("Set idle rate for {:?} to {:?}", id, dur); 160 info!("Set idle rate for {:?} to {:?}", id, dur);
127 } 161 }
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index a64bda31b..4f77fc1d7 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -5,10 +5,10 @@ use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32n6/.cargo/config.toml b/examples/stm32n6/.cargo/config.toml
new file mode 100644
index 000000000..2fdd70649
--- /dev/null
+++ b/examples/stm32n6/.cargo/config.toml
@@ -0,0 +1,8 @@
1[target.thumbv8m.main-none-eabihf]
2runner = 'probe-rs run --chip STM32N657'
3
4[build]
5target = "thumbv8m.main-none-eabihf"
6
7[env]
8DEFMT_LOG = "trace"
diff --git a/examples/stm32n6/Cargo.toml b/examples/stm32n6/Cargo.toml
new file mode 100644
index 000000000..5ad5b97ce
--- /dev/null
+++ b/examples/stm32n6/Cargo.toml
@@ -0,0 +1,80 @@
1[package]
2edition = "2021"
3name = "embassy-stm32n6-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# Change stm32h563zi to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32n657x0", "time-driver-any", "exti", "unstable-pac"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17
18defmt = "1.0.1"
19defmt-rtt = "1.0.0"
20
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" }
26embedded-io-async = { version = "0.6.1" }
27embedded-nal-async = "0.8.0"
28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1"
31micromath = "2.0.0"
32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.1"
34static_cell = "2"
35hmac = "0.12.1"
36sha2 = { version = "0.10.9", default-features = false }
37
38
39# cargo build/run
40[profile.dev]
41codegen-units = 1
42debug = 2
43debug-assertions = true # <-
44incremental = false
45opt-level = 3 # <-
46overflow-checks = true # <-
47
48# cargo test
49[profile.test]
50codegen-units = 1
51debug = 2
52debug-assertions = true # <-
53incremental = false
54opt-level = 3 # <-
55overflow-checks = true # <-
56
57# cargo build/run --release
58[profile.release]
59codegen-units = 1
60debug = 2
61debug-assertions = false # <-
62incremental = false
63lto = 'fat'
64opt-level = 3 # <-
65overflow-checks = false # <-
66
67# cargo test --release
68[profile.bench]
69codegen-units = 1
70debug = 2
71debug-assertions = false # <-
72incremental = false
73lto = 'fat'
74opt-level = 3 # <-
75overflow-checks = false # <-
76
77[package.metadata.embassy]
78build = [
79 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32n6" }
80]
diff --git a/examples/stm32n6/build.rs b/examples/stm32n6/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32n6/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32n6/memory.x b/examples/stm32n6/memory.x
new file mode 100644
index 000000000..59f127adc
--- /dev/null
+++ b/examples/stm32n6/memory.x
@@ -0,0 +1,5 @@
1MEMORY
2{
3 FLASH : ORIGIN = 0x34180400, LENGTH = 255K
4 RAM : ORIGIN = 0x341C0000, LENGTH = 256K
5}
diff --git a/examples/stm32n6/src/bin/blinky.rs b/examples/stm32n6/src/bin/blinky.rs
new file mode 100644
index 000000000..a8baf16af
--- /dev/null
+++ b/examples/stm32n6/src/bin/blinky.rs
@@ -0,0 +1,42 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::{Level, Output, Pull, Speed};
8use embassy_stm32::{bind_interrupts, interrupt};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(
13 pub struct Irqs{
14 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
15});
16
17#[embassy_executor::task]
18async fn button_task(mut p: ExtiInput<'static>) {
19 loop {
20 p.wait_for_any_edge().await;
21 info!("button pressed!");
22 }
23}
24
25#[embassy_executor::main]
26async fn main(spawner: Spawner) {
27 let p = embassy_stm32::init(Default::default());
28 info!("Hello World!");
29
30 let mut led = Output::new(p.PG10, Level::High, Speed::Low);
31 let button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
32
33 spawner.spawn(button_task(button).unwrap());
34
35 loop {
36 led.set_high();
37 Timer::after_millis(500).await;
38
39 led.set_low();
40 Timer::after_millis(500).await;
41 }
42}
diff --git a/examples/stm32n6/src/bin/crc.rs b/examples/stm32n6/src/bin/crc.rs
new file mode 100644
index 000000000..d1b545d5b
--- /dev/null
+++ b/examples/stm32n6/src/bin/crc.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::crc::{Config, Crc, InputReverseConfig, PolySize};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_stm32::init(Default::default());
12 info!("Hello World!");
13
14 // Setup for: https://crccalc.com/?crc=Life, it never dieWomen are my favorite guy&method=crc32&datatype=ascii&outtype=0
15 let mut crc = Crc::new(
16 p.CRC,
17 unwrap!(Config::new(
18 InputReverseConfig::Byte,
19 true,
20 PolySize::Width32,
21 0xFFFFFFFF,
22 0x04C11DB7
23 )),
24 );
25
26 let output = crc.feed_bytes(b"Life, it never die\nWomen are my favorite guy") ^ 0xFFFFFFFF;
27
28 defmt::assert_eq!(output, 0x33F0E26B);
29
30 cortex_m::asm::bkpt();
31}
diff --git a/examples/stm32n6/src/bin/hash.rs b/examples/stm32n6/src/bin/hash.rs
new file mode 100644
index 000000000..9f248318f
--- /dev/null
+++ b/examples/stm32n6/src/bin/hash.rs
@@ -0,0 +1,78 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_stm32::hash::*;
7use embassy_stm32::{Config, bind_interrupts, hash, peripherals};
8use embassy_time::Instant;
9use hmac::{Hmac, Mac};
10use sha2::{Digest, Sha256};
11use {defmt_rtt as _, panic_probe as _};
12
13type HmacSha256 = Hmac<Sha256>;
14
15bind_interrupts!(struct Irqs {
16 HASH => hash::InterruptHandler<peripherals::HASH>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) -> ! {
21 let config = Config::default();
22 let p = embassy_stm32::init(config);
23
24 let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh";
25 let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr";
26
27 let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs);
28
29 let hw_start_time = Instant::now();
30
31 // Compute a digest in hardware.
32 let mut context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, None);
33 hw_hasher.update_blocking(&mut context, test_1);
34 hw_hasher.update_blocking(&mut context, test_2);
35 let mut hw_digest: [u8; 32] = [0; 32];
36 hw_hasher.finish_blocking(context, &mut hw_digest);
37
38 let hw_end_time = Instant::now();
39 let hw_execution_time = hw_end_time - hw_start_time;
40
41 let sw_start_time = Instant::now();
42
43 // Compute a digest in software.
44 let mut sw_hasher = Sha256::new();
45 sw_hasher.update(test_1);
46 sw_hasher.update(test_2);
47 let sw_digest = sw_hasher.finalize();
48
49 let sw_end_time = Instant::now();
50 let sw_execution_time = sw_end_time - sw_start_time;
51
52 info!("Hardware Digest: {:?}", hw_digest);
53 info!("Software Digest: {:?}", sw_digest[..]);
54 info!("Hardware Execution Time: {:?}", hw_execution_time);
55 info!("Software Execution Time: {:?}", sw_execution_time);
56 assert_eq!(hw_digest, sw_digest[..]);
57
58 let hmac_key: [u8; 64] = [0x55; 64];
59
60 // Compute HMAC in hardware.
61 let mut sha256hmac_context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, Some(&hmac_key));
62 hw_hasher.update_blocking(&mut sha256hmac_context, test_1);
63 hw_hasher.update_blocking(&mut sha256hmac_context, test_2);
64 let mut hw_hmac: [u8; 32] = [0; 32];
65 hw_hasher.finish_blocking(sha256hmac_context, &mut hw_hmac);
66
67 // Compute HMAC in software.
68 let mut sw_mac = HmacSha256::new_from_slice(&hmac_key).unwrap();
69 sw_mac.update(test_1);
70 sw_mac.update(test_2);
71 let sw_hmac = sw_mac.finalize().into_bytes();
72
73 info!("Hardware HMAC: {:?}", hw_hmac);
74 info!("Software HMAC: {:?}", sw_hmac[..]);
75 assert_eq!(hw_hmac, sw_hmac[..]);
76
77 loop {}
78}
diff --git a/examples/stm32u0/.cargo/config.toml b/examples/stm32u0/.cargo/config.toml
index 688347084..e9212cacb 100644
--- a/examples/stm32u0/.cargo/config.toml
+++ b/examples/stm32u0/.cargo/config.toml
@@ -1,6 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))'] 1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace stm32u083rctx with your chip as listed in `probe-rs chip list` 2# replace stm32u083mctx with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip stm32u083rctx" 3runner = "probe-rs run --chip stm32u083mctx"
4 4
5[build] 5[build]
6target = "thumbv6m-none-eabi" 6target = "thumbv6m-none-eabi"
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml
index 9318414a5..8cc894cb3 100644
--- a/examples/stm32u0/Cargo.toml
+++ b/examples/stm32u0/Cargo.toml
@@ -1,13 +1,13 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32u0-examples" 3name = "embassy-stm32u0-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32u083rc to your chip name, if necessary. 9# Change stm32u083mc to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083mc", "memory-x", "unstable-pac", "exti", "chrono"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
@@ -19,9 +19,7 @@ defmt-rtt = "1.0.0"
19 19
20cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
22embedded-hal = "0.2.6"
23panic-probe = { version = "1.0.0", features = ["print-defmt"] } 22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24heapless = { version = "0.8", default-features = false }
25 23
26micromath = "2.0.0" 24micromath = "2.0.0"
27chrono = { version = "0.4.38", default-features = false } 25chrono = { version = "0.4.38", default-features = false }
diff --git a/examples/stm32u0/src/bin/adc.rs b/examples/stm32u0/src/bin/adc.rs
index c8252e4e1..53bd37303 100644
--- a/examples/stm32u0/src/bin/adc.rs
+++ b/examples/stm32u0/src/bin/adc.rs
@@ -2,8 +2,8 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{Adc, Resolution};
6use embassy_stm32::Config; 5use embassy_stm32::Config;
6use embassy_stm32::adc::{Adc, AdcConfig, Resolution, SampleTime};
7use embassy_time::Duration; 7use embassy_time::Duration;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
@@ -18,12 +18,13 @@ fn main() -> ! {
18 } 18 }
19 let p = embassy_stm32::init(config); 19 let p = embassy_stm32::init(config);
20 20
21 let mut adc = Adc::new(p.ADC1); 21 let mut config = AdcConfig::default();
22 adc.set_resolution(Resolution::BITS8); 22 config.resolution = Some(Resolution::BITS8);
23 let mut adc = Adc::new_with_config(p.ADC1, config);
23 let mut channel = p.PC0; 24 let mut channel = p.PC0;
24 25
25 loop { 26 loop {
26 let v = adc.blocking_read(&mut channel); 27 let v = adc.blocking_read(&mut channel, SampleTime::CYCLES12_5);
27 info!("--> {}", v); 28 info!("--> {}", v);
28 embassy_time::block_for(Duration::from_millis(200)); 29 embassy_time::block_for(Duration::from_millis(200));
29 } 30 }
diff --git a/examples/stm32u0/src/bin/button_exti.rs b/examples/stm32u0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32u0/src/bin/button_exti.rs
+++ b/examples/stm32u0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32u0/src/bin/lcd.rs b/examples/stm32u0/src/bin/lcd.rs
new file mode 100644
index 000000000..2b34d4ef1
--- /dev/null
+++ b/examples/stm32u0/src/bin/lcd.rs
@@ -0,0 +1,412 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::lcd::{Bias, BlinkFreq, BlinkSelector, Config, Duty, Lcd, LcdPin};
7use embassy_stm32::peripherals::LCD;
8use embassy_stm32::time::Hertz;
9use embassy_time::Duration;
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let mut config = embassy_stm32::Config::default();
15 // The RTC clock = the LCD clock and must be running
16 {
17 use embassy_stm32::rcc::*;
18 config.rcc.sys = Sysclk::PLL1_R;
19 config.rcc.hsi = true;
20 config.rcc.pll = Some(Pll {
21 source: PllSource::HSI, // 16 MHz
22 prediv: PllPreDiv::DIV1,
23 mul: PllMul::MUL7, // 16 * 7 = 112 MHz
24 divp: None,
25 divq: None,
26 divr: Some(PllRDiv::DIV2), // 112 / 2 = 56 MHz
27 });
28 config.rcc.ls = LsConfig::default_lsi();
29 }
30
31 let p = embassy_stm32::init(config);
32 info!("Hello World!");
33
34 let mut config = Config::default();
35 config.bias = Bias::Third;
36 config.duty = Duty::Quarter;
37 config.target_fps = Hertz(100);
38
39 let mut lcd = Lcd::new(
40 p.LCD,
41 config,
42 p.PC3,
43 [
44 LcdPin::new_com(p.PA8),
45 LcdPin::new_com(p.PA9),
46 LcdPin::new_com(p.PA10),
47 LcdPin::new_seg(p.PB1),
48 LcdPin::new_com(p.PB9),
49 LcdPin::new_seg(p.PB11),
50 LcdPin::new_seg(p.PB14),
51 LcdPin::new_seg(p.PB15),
52 LcdPin::new_seg(p.PC4),
53 LcdPin::new_seg(p.PC5),
54 LcdPin::new_seg(p.PC6),
55 LcdPin::new_seg(p.PC8),
56 LcdPin::new_seg(p.PC9),
57 LcdPin::new_seg(p.PC10),
58 LcdPin::new_seg(p.PC11),
59 LcdPin::new_seg(p.PD8),
60 LcdPin::new_seg(p.PD9),
61 LcdPin::new_seg(p.PD12),
62 LcdPin::new_seg(p.PD13),
63 LcdPin::new_seg(p.PD0),
64 LcdPin::new_seg(p.PD1),
65 LcdPin::new_seg(p.PD3),
66 LcdPin::new_seg(p.PD4),
67 LcdPin::new_seg(p.PD5),
68 LcdPin::new_seg(p.PD6),
69 LcdPin::new_seg(p.PE7),
70 LcdPin::new_seg(p.PE8),
71 LcdPin::new_seg(p.PE9),
72 ],
73 );
74
75 lcd.set_blink(BlinkSelector::All, BlinkFreq::Hz4);
76 {
77 let mut buffer = DisplayBuffer::new();
78 for i in 0..4 {
79 buffer.write_colon(i);
80 buffer.write(&mut lcd);
81 embassy_time::Timer::after_millis(200).await;
82 buffer.write_dot(i);
83 buffer.write(&mut lcd);
84 embassy_time::Timer::after_millis(200).await;
85 }
86 for i in 0..4 {
87 buffer.write_bar(i);
88 buffer.write(&mut lcd);
89 embassy_time::Timer::after_millis(200).await;
90 }
91 }
92
93 embassy_time::Timer::after_millis(1000).await;
94
95 lcd.set_blink(BlinkSelector::None, BlinkFreq::Hz4);
96
97 const MESSAGE: &str = "Hello embassy people. Hope you like this LCD demo :} ";
98 loop {
99 print_message(MESSAGE, &mut lcd, Duration::from_millis(250)).await;
100 print_message(characters::ALL_CHARS, &mut lcd, Duration::from_millis(500)).await;
101 }
102}
103
104async fn print_message(message: &str, lcd: &mut Lcd<'_, LCD>, delay: Duration) {
105 let mut display_buffer = DisplayBuffer::new();
106
107 let mut char_buffer = [' '; 6];
108 for char in message.chars() {
109 char_buffer.copy_within(1.., 0);
110 char_buffer[5] = char;
111
112 display_buffer.clear();
113 for (i, char) in char_buffer.iter().enumerate() {
114 display_buffer.write_char(i, *char);
115 }
116 display_buffer.write(lcd);
117
118 embassy_time::Timer::after(delay).await;
119 }
120}
121
122/// Display layout for the U0-DK
123mod display_layout {
124 // Character layout. There are 6 characters, left-to-right
125 // T
126 // ─────────
127 // │ N │
128 // │ │ │ │ │
129 // TL │ └┐ │ ┌┘ │ TR
130 // │NW│ │ │NE│
131 // │ │ │
132 // W─── ───E
133 // │ │ │
134 // │SW│ │ │SE│
135 // BL │ ┌┘ │ └┐ │ BR
136 // │ │ │ │ │
137 // │ S │
138 // ─────────
139 // B
140
141 pub const CHAR_N_COM: u8 = 3;
142 pub const CHAR_N_SEG: [u8; 6] = [39, 37, 35, 48, 26, 33];
143 pub const CHAR_NW_COM: u8 = 3;
144 pub const CHAR_NW_SEG: [u8; 6] = [49, 38, 36, 34, 27, 24];
145 pub const CHAR_W_COM: u8 = 0;
146 pub const CHAR_W_SEG: [u8; 6] = CHAR_NW_SEG;
147 pub const CHAR_SW_COM: u8 = 2;
148 pub const CHAR_SW_SEG: [u8; 6] = CHAR_NW_SEG;
149 pub const CHAR_S_COM: u8 = 2;
150 pub const CHAR_S_SEG: [u8; 6] = [22, 6, 46, 11, 15, 29];
151 pub const CHAR_SE_COM: u8 = 3;
152 pub const CHAR_SE_SEG: [u8; 6] = CHAR_S_SEG;
153 pub const CHAR_E_COM: u8 = 0;
154 pub const CHAR_E_SEG: [u8; 6] = [23, 45, 47, 14, 28, 32];
155 pub const CHAR_NE_COM: u8 = 2;
156 pub const CHAR_NE_SEG: [u8; 6] = CHAR_N_SEG;
157 pub const CHAR_T_COM: u8 = 1;
158 pub const CHAR_T_SEG: [u8; 6] = CHAR_N_SEG;
159 pub const CHAR_TL_COM: u8 = 1;
160 pub const CHAR_TL_SEG: [u8; 6] = CHAR_NW_SEG;
161 pub const CHAR_BL_COM: u8 = 0;
162 pub const CHAR_BL_SEG: [u8; 6] = CHAR_S_SEG;
163 pub const CHAR_B_COM: u8 = 1;
164 pub const CHAR_B_SEG: [u8; 6] = CHAR_S_SEG;
165 pub const CHAR_BR_COM: u8 = 1;
166 pub const CHAR_BR_SEG: [u8; 6] = CHAR_E_SEG;
167 pub const CHAR_TR_COM: u8 = 0;
168 pub const CHAR_TR_SEG: [u8; 6] = CHAR_N_SEG;
169
170 pub const COLON_COM: u8 = 2;
171 pub const COLON_SEG: [u8; 4] = [23, 45, 47, 14];
172 pub const DOT_COM: u8 = 3;
173 pub const DOT_SEG: [u8; 4] = COLON_SEG;
174 /// COM + SEG, bar from top to bottom
175 pub const BAR: [(u8, u8); 4] = [(2, 28), (3, 28), (2, 32), (3, 32)];
176}
177
178mod characters {
179 use super::CharSegment::{self, *};
180
181 pub const CHAR_0: &[CharSegment] = &[T, TL, BL, B, BR, TR, NW, SE];
182 pub const CHAR_1: &[CharSegment] = &[NE, TR, BR];
183 pub const CHAR_2: &[CharSegment] = &[T, BL, B, TR, E, W];
184 pub const CHAR_3: &[CharSegment] = &[T, B, BR, TR, E];
185 pub const CHAR_4: &[CharSegment] = &[TL, BR, TR, E, W];
186 pub const CHAR_5: &[CharSegment] = &[T, TL, B, BR, E, W];
187 pub const CHAR_6: &[CharSegment] = &[T, TL, BL, B, BR, E, W];
188 pub const CHAR_7: &[CharSegment] = &[T, NE, S];
189 pub const CHAR_8: &[CharSegment] = &[T, TL, BL, B, BR, TR, E, W];
190 pub const CHAR_9: &[CharSegment] = &[T, TL, BR, TR, E, W];
191
192 pub const CHAR_COLON: &[CharSegment] = &[N, S];
193 pub const CHAR_SEMICOLON: &[CharSegment] = &[N, SW];
194 pub const CHAR_EQUALS: &[CharSegment] = &[E, W, B];
195 pub const CHAR_SLASH: &[CharSegment] = &[SW, NE];
196 pub const CHAR_BACKSLASH: &[CharSegment] = &[SE, NW];
197 pub const CHAR_PLUS: &[CharSegment] = &[N, E, S, W];
198 pub const CHAR_STAR: &[CharSegment] = &[NE, N, NW, SE, S, SW];
199 pub const CHAR_QUOTE: &[CharSegment] = &[N];
200 pub const CHAR_BACKTICK: &[CharSegment] = &[NW];
201 pub const CHAR_DASH: &[CharSegment] = &[W, E];
202 pub const CHAR_COMMA: &[CharSegment] = &[SW];
203 pub const CHAR_DOT: &[CharSegment] = &[S];
204 pub const CHAR_CURLYOPEN: &[CharSegment] = &[T, NW, W, SW, B];
205 pub const CHAR_CURLYCLOSE: &[CharSegment] = &[T, NE, E, SE, B];
206 pub const CHAR_AMPERSAND: &[CharSegment] = &[T, NE, NW, W, BL, B, SE];
207
208 pub const CHAR_A: &[CharSegment] = &[T, TL, TR, E, W, BL, BR];
209 pub const CHAR_B: &[CharSegment] = &[T, TR, BR, B, N, S, E];
210 pub const CHAR_C: &[CharSegment] = &[T, TL, BL, B];
211 pub const CHAR_D: &[CharSegment] = &[T, TR, BR, B, N, S];
212 pub const CHAR_E: &[CharSegment] = &[T, TL, BL, B, W];
213 pub const CHAR_F: &[CharSegment] = &[T, TL, BL, W];
214 pub const CHAR_G: &[CharSegment] = &[T, TL, BL, B, BR, E];
215 pub const CHAR_H: &[CharSegment] = &[TL, BL, E, W, TR, BR];
216 pub const CHAR_I: &[CharSegment] = &[T, N, S, B];
217 pub const CHAR_J: &[CharSegment] = &[TR, BR, B, BL];
218 pub const CHAR_K: &[CharSegment] = &[TL, BL, W, NE, SE];
219 pub const CHAR_L: &[CharSegment] = &[TL, BL, B];
220 pub const CHAR_M: &[CharSegment] = &[BL, TL, NW, NE, TR, BR];
221 pub const CHAR_N: &[CharSegment] = &[BL, TL, NW, SE, BR, TR];
222 pub const CHAR_O: &[CharSegment] = &[T, TL, BL, B, BR, TR];
223 pub const CHAR_P: &[CharSegment] = &[BL, TL, T, TR, E, W];
224 pub const CHAR_Q: &[CharSegment] = &[T, TL, BL, B, BR, TR, SE];
225 pub const CHAR_R: &[CharSegment] = &[BL, TL, T, TR, E, W, SE];
226 pub const CHAR_S: &[CharSegment] = &[T, NW, E, BR, B];
227 pub const CHAR_T: &[CharSegment] = &[T, N, S];
228 pub const CHAR_U: &[CharSegment] = &[TL, BL, B, BR, TR];
229 pub const CHAR_V: &[CharSegment] = &[TL, BL, SW, NE];
230 pub const CHAR_W: &[CharSegment] = &[TL, BL, SW, SE, BR, TR];
231 pub const CHAR_X: &[CharSegment] = &[NE, NW, SE, SW];
232 pub const CHAR_Y: &[CharSegment] = &[NE, NW, S];
233 pub const CHAR_Z: &[CharSegment] = &[T, NE, SW, B];
234
235 pub const CHAR_UNKNOWN: &[CharSegment] = &[N, NW, W, SW, S, SE, E, NE, T, TL, BL, B, BR, TR];
236
237 pub const ALL_CHARS: &str =
238 "0 1 2 3 4 5 6 7 8 9 : ; = / \\ + * ' ` - , . { } & A B C D E F G H I J K L M N O P Q R S T U V W X Y Z � ";
239
240 pub fn get_char_segments(val: char) -> &'static [CharSegment] {
241 match val {
242 val if val.is_whitespace() => &[],
243
244 '0' => CHAR_0,
245 '1' => CHAR_1,
246 '2' => CHAR_2,
247 '3' => CHAR_3,
248 '4' => CHAR_4,
249 '5' => CHAR_5,
250 '6' => CHAR_6,
251 '7' => CHAR_7,
252 '8' => CHAR_8,
253 '9' => CHAR_9,
254
255 ':' => CHAR_COLON,
256 ';' => CHAR_SEMICOLON,
257 '=' => CHAR_EQUALS,
258 '/' => CHAR_SLASH,
259 '\\' => CHAR_BACKSLASH,
260 '+' => CHAR_PLUS,
261 '*' => CHAR_STAR,
262 '\'' => CHAR_QUOTE,
263 '`' => CHAR_BACKTICK,
264 '-' => CHAR_DASH,
265 ',' => CHAR_COMMA,
266 '.' => CHAR_DOT,
267 '{' => CHAR_CURLYOPEN,
268 '}' => CHAR_CURLYCLOSE,
269 '&' => CHAR_AMPERSAND,
270
271 'A' | 'a' => CHAR_A,
272 'B' | 'b' => CHAR_B,
273 'C' | 'c' => CHAR_C,
274 'D' | 'd' => CHAR_D,
275 'E' | 'e' => CHAR_E,
276 'F' | 'f' => CHAR_F,
277 'G' | 'g' => CHAR_G,
278 'H' | 'h' => CHAR_H,
279 'I' | 'i' => CHAR_I,
280 'J' | 'j' => CHAR_J,
281 'K' | 'k' => CHAR_K,
282 'L' | 'l' => CHAR_L,
283 'M' | 'm' => CHAR_M,
284 'N' | 'n' => CHAR_N,
285 'O' | 'o' => CHAR_O,
286 'P' | 'p' => CHAR_P,
287 'Q' | 'q' => CHAR_Q,
288 'R' | 'r' => CHAR_R,
289 'S' | 's' => CHAR_S,
290 'T' | 't' => CHAR_T,
291 'U' | 'u' => CHAR_U,
292 'V' | 'v' => CHAR_V,
293 'W' | 'w' => CHAR_W,
294 'X' | 'x' => CHAR_X,
295 'Y' | 'y' => CHAR_Y,
296 'Z' | 'z' => CHAR_Z,
297
298 _ => CHAR_UNKNOWN,
299 }
300 }
301}
302
303pub struct DisplayBuffer {
304 pixels: [u64; 4],
305}
306
307impl DisplayBuffer {
308 pub const fn new() -> Self {
309 Self { pixels: [0; 4] }
310 }
311
312 pub fn clear(&mut self) {
313 *self = Self::new();
314 }
315
316 fn write_char_segment(&mut self, index: usize, value: CharSegment) {
317 defmt::assert!(index < 6);
318 let (com, segments) = value.get_com_seg();
319 self.pixels[com as usize] |= 1 << segments[index];
320 }
321
322 pub fn write_char(&mut self, index: usize, val: char) {
323 let segments = characters::get_char_segments(val);
324
325 for segment in segments {
326 self.write_char_segment(index, *segment);
327 }
328 }
329
330 pub fn write(&self, lcd: &mut Lcd<'_, LCD>) {
331 lcd.write_com_segments(0, self.pixels[0]);
332 lcd.write_com_segments(1, self.pixels[1]);
333 lcd.write_com_segments(2, self.pixels[2]);
334 lcd.write_com_segments(3, self.pixels[3]);
335 lcd.submit_frame();
336 }
337
338 pub fn write_colon(&mut self, index: usize) {
339 defmt::assert!(index < 4);
340 self.pixels[display_layout::COLON_COM as usize] |= 1 << display_layout::COLON_SEG[index];
341 }
342
343 pub fn write_dot(&mut self, index: usize) {
344 defmt::assert!(index < 4);
345 self.pixels[display_layout::DOT_COM as usize] |= 1 << display_layout::DOT_SEG[index];
346 }
347
348 pub fn write_bar(&mut self, index: usize) {
349 defmt::assert!(index < 4);
350 let (bar_com, bar_seg) = display_layout::BAR[index];
351 self.pixels[bar_com as usize] |= 1 << bar_seg;
352 }
353}
354
355impl Default for DisplayBuffer {
356 fn default() -> Self {
357 Self::new()
358 }
359}
360
361#[derive(Debug, Clone, Copy)]
362enum CharSegment {
363 /// North
364 N,
365 /// North west
366 NW,
367 /// West
368 W,
369 /// South west
370 SW,
371 /// South
372 S,
373 /// South East
374 SE,
375 /// East
376 E,
377 /// North East
378 NE,
379 /// Top
380 T,
381 /// Top left
382 TL,
383 /// Bottom left
384 BL,
385 /// Bottom
386 B,
387 /// Bottom right
388 BR,
389 /// Top right
390 TR,
391}
392
393impl CharSegment {
394 fn get_com_seg(&self) -> (u8, [u8; 6]) {
395 match self {
396 CharSegment::N => (display_layout::CHAR_N_COM, display_layout::CHAR_N_SEG),
397 CharSegment::NW => (display_layout::CHAR_NW_COM, display_layout::CHAR_NW_SEG),
398 CharSegment::W => (display_layout::CHAR_W_COM, display_layout::CHAR_W_SEG),
399 CharSegment::SW => (display_layout::CHAR_SW_COM, display_layout::CHAR_SW_SEG),
400 CharSegment::S => (display_layout::CHAR_S_COM, display_layout::CHAR_S_SEG),
401 CharSegment::SE => (display_layout::CHAR_SE_COM, display_layout::CHAR_SE_SEG),
402 CharSegment::E => (display_layout::CHAR_E_COM, display_layout::CHAR_E_SEG),
403 CharSegment::NE => (display_layout::CHAR_NE_COM, display_layout::CHAR_NE_SEG),
404 CharSegment::T => (display_layout::CHAR_T_COM, display_layout::CHAR_T_SEG),
405 CharSegment::TL => (display_layout::CHAR_TL_COM, display_layout::CHAR_TL_SEG),
406 CharSegment::BL => (display_layout::CHAR_BL_COM, display_layout::CHAR_BL_SEG),
407 CharSegment::B => (display_layout::CHAR_B_COM, display_layout::CHAR_B_SEG),
408 CharSegment::BR => (display_layout::CHAR_BR_COM, display_layout::CHAR_BR_SEG),
409 CharSegment::TR => (display_layout::CHAR_TR_COM, display_layout::CHAR_TR_SEG),
410 }
411 }
412}
diff --git a/examples/stm32u0/src/bin/rng.rs b/examples/stm32u0/src/bin/rng.rs
index 89445b042..07deda94c 100644
--- a/examples/stm32u0/src/bin/rng.rs
+++ b/examples/stm32u0/src/bin/rng.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::rcc::mux::Clk48sel; 6use embassy_stm32::rcc::mux::Clk48sel;
7use embassy_stm32::rng::Rng; 7use embassy_stm32::rng::Rng;
8use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, rng};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs { 11bind_interrupts!(struct Irqs {
diff --git a/examples/stm32u0/src/bin/rtc.rs b/examples/stm32u0/src/bin/rtc.rs
index 72fa0fde4..56d16ccf7 100644
--- a/examples/stm32u0/src/bin/rtc.rs
+++ b/examples/stm32u0/src/bin/rtc.rs
@@ -4,8 +4,8 @@
4use chrono::{NaiveDate, NaiveDateTime}; 4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rtc::{Rtc, RtcConfig};
8use embassy_stm32::Config; 7use embassy_stm32::Config;
8use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_time::Timer; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
36 .and_hms_opt(10, 30, 15) 36 .and_hms_opt(10, 30, 15)
37 .unwrap(); 37 .unwrap();
38 38
39 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 39 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
40 info!("Got RTC! {:?}", now.and_utc().timestamp()); 40 info!("Got RTC! {:?}", now.and_utc().timestamp());
41 41
42 rtc.set_datetime(now.into()).expect("datetime not set"); 42 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -44,6 +44,6 @@ async fn main(_spawner: Spawner) {
44 // In reality the delay would be much longer 44 // In reality the delay would be much longer
45 Timer::after_millis(20000).await; 45 Timer::after_millis(20000).await;
46 46
47 let then: NaiveDateTime = rtc.now().unwrap().into(); 47 let then: NaiveDateTime = time_provider.now().unwrap().into();
48 info!("Got RTC! {:?}", then.and_utc().timestamp()); 48 info!("Got RTC! {:?}", then.and_utc().timestamp());
49} 49}
diff --git a/examples/stm32u0/src/bin/usb_serial.rs b/examples/stm32u0/src/bin/usb_serial.rs
index 273f40643..77d0640f6 100644
--- a/examples/stm32u0/src/bin/usb_serial.rs
+++ b/examples/stm32u0/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use panic_probe as _; 13use panic_probe as _;
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index f2ffe52c5..7a1e62406 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32u5-examples" 3name = "embassy-stm32u5-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs
index d2aa28087..4d2d93aa2 100644
--- a/examples/stm32u5/src/bin/adc.rs
+++ b/examples/stm32u5/src/bin/adc.rs
@@ -2,8 +2,7 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc; 5use embassy_stm32::adc::{self, Adc, AdcChannel, AdcConfig, SampleTime, adc4};
6use embassy_stm32::adc::{adc4, AdcChannel};
7use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
8 7
9#[embassy_executor::main] 8#[embassy_executor::main]
@@ -13,56 +12,55 @@ async fn main(_spawner: embassy_executor::Spawner) {
13 let mut p = embassy_stm32::init(config); 12 let mut p = embassy_stm32::init(config);
14 13
15 // **** ADC1 init **** 14 // **** ADC1 init ****
16 let mut adc1 = adc::Adc::new(p.ADC1); 15 let mut config = AdcConfig::default();
16 config.averaging = Some(adc::Averaging::Samples1024);
17 config.resolution = Some(adc::Resolution::BITS14);
18 let mut adc1 = Adc::new_with_config(p.ADC1, config);
17 let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 19 let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5
18 let mut adc1_pin2 = p.PA2; // A1 20 let mut adc1_pin2 = p.PA2; // A1
19 adc1.set_resolution(adc::Resolution::BITS14);
20 adc1.set_averaging(adc::Averaging::Samples1024);
21 adc1.set_sample_time(adc::SampleTime::CYCLES160_5);
22 let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); 21 let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14);
23 22
24 // **** ADC2 init **** 23 // **** ADC2 init ****
25 let mut adc2 = adc::Adc::new(p.ADC2); 24 let mut config = AdcConfig::default();
25 config.averaging = Some(adc::Averaging::Samples1024);
26 config.resolution = Some(adc::Resolution::BITS14);
27 let mut adc2 = Adc::new_with_config(p.ADC2, config);
26 let mut adc2_pin1 = p.PC3; // A2 28 let mut adc2_pin1 = p.PC3; // A2
27 let mut adc2_pin2 = p.PB0; // A3 29 let mut adc2_pin2 = p.PB0; // A3
28 adc2.set_resolution(adc::Resolution::BITS14);
29 adc2.set_averaging(adc::Averaging::Samples1024);
30 adc2.set_sample_time(adc::SampleTime::CYCLES160_5);
31 let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); 30 let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14);
32 31
33 // **** ADC4 init **** 32 // **** ADC4 init ****
34 let mut adc4 = adc4::Adc4::new(p.ADC4); 33 let mut adc4 = Adc::new_adc4(p.ADC4);
35 let mut adc4_pin1 = p.PC1; // A4 34 let mut adc4_pin1 = p.PC1.degrade_adc(); // A4
36 let mut adc4_pin2 = p.PC0; // A5 35 let mut adc4_pin2 = p.PC0; // A5
37 adc4.set_resolution(adc4::Resolution::BITS12); 36 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
38 adc4.set_averaging(adc4::Averaging::Samples256); 37 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
39 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5);
40 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 38 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
41 39
42 // **** ADC1 blocking read **** 40 // **** ADC1 blocking read ****
43 let raw: u16 = adc1.blocking_read(&mut adc1_pin1); 41 let raw: u16 = adc1.blocking_read(&mut adc1_pin1, SampleTime::CYCLES160_5);
44 let volt: f32 = 3.3 * raw as f32 / max1 as f32; 42 let volt: f32 = 3.3 * raw as f32 / max1 as f32;
45 info!("Read adc1 pin 1 {}", volt); 43 info!("Read adc1 pin 1 {}", volt);
46 44
47 let raw: u16 = adc1.blocking_read(&mut adc1_pin2); 45 let raw: u16 = adc1.blocking_read(&mut adc1_pin2, SampleTime::CYCLES160_5);
48 let volt: f32 = 3.3 * raw as f32 / max1 as f32; 46 let volt: f32 = 3.3 * raw as f32 / max1 as f32;
49 info!("Read adc1 pin 2 {}", volt); 47 info!("Read adc1 pin 2 {}", volt);
50 48
51 // **** ADC2 blocking read **** 49 // **** ADC2 blocking read ****
52 let raw: u16 = adc2.blocking_read(&mut adc2_pin1); 50 let raw: u16 = adc2.blocking_read(&mut adc2_pin1, SampleTime::CYCLES160_5);
53 let volt: f32 = 3.3 * raw as f32 / max2 as f32; 51 let volt: f32 = 3.3 * raw as f32 / max2 as f32;
54 info!("Read adc2 pin 1 {}", volt); 52 info!("Read adc2 pin 1 {}", volt);
55 53
56 let raw: u16 = adc2.blocking_read(&mut adc2_pin2); 54 let raw: u16 = adc2.blocking_read(&mut adc2_pin2, SampleTime::CYCLES160_5);
57 let volt: f32 = 3.3 * raw as f32 / max2 as f32; 55 let volt: f32 = 3.3 * raw as f32 / max2 as f32;
58 info!("Read adc2 pin 2 {}", volt); 56 info!("Read adc2 pin 2 {}", volt);
59 57
60 // **** ADC4 blocking read **** 58 // **** ADC4 blocking read ****
61 let raw: u16 = adc4.blocking_read(&mut adc4_pin1); 59 let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5);
62 let volt: f32 = 3.3 * raw as f32 / max4 as f32; 60 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
63 info!("Read adc4 pin 1 {}", volt); 61 info!("Read adc4 pin 1 {}", volt);
64 62
65 let raw: u16 = adc4.blocking_read(&mut adc4_pin2); 63 let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5);
66 let volt: f32 = 3.3 * raw as f32 / max4 as f32; 64 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
67 info!("Read adc4 pin 2 {}", volt); 65 info!("Read adc4 pin 2 {}", volt);
68 66
@@ -97,11 +95,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
97 // The channels must be in ascending order and can't repeat for ADC4 95 // The channels must be in ascending order and can't repeat for ADC4
98 adc4.read( 96 adc4.read(
99 p.GPDMA1_CH1.reborrow(), 97 p.GPDMA1_CH1.reborrow(),
100 [&mut degraded42, &mut degraded41].into_iter(), 98 [
99 (&mut degraded42, adc4::SampleTime::CYCLES1_5),
100 (&mut degraded41, adc4::SampleTime::CYCLES1_5),
101 ]
102 .into_iter(),
101 &mut measurements, 103 &mut measurements,
102 ) 104 )
103 .await 105 .await;
104 .unwrap();
105 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 106 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
106 let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; 107 let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32;
107 info!("Async read 4 pin 1 {}", volt1); 108 info!("Async read 4 pin 1 {}", volt1);
diff --git a/examples/stm32u5/src/bin/ltdc.rs b/examples/stm32u5/src/bin/ltdc.rs
index 46d1c120f..d1fddb679 100644
--- a/examples/stm32u5/src/bin/ltdc.rs
+++ b/examples/stm32u5/src/bin/ltdc.rs
@@ -13,14 +13,14 @@ use embassy_stm32::gpio::{Level, Output, Speed};
13use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge}; 13use embassy_stm32::ltdc::{self, Ltdc, LtdcConfiguration, LtdcLayer, LtdcLayerConfig, PolarityActive, PolarityEdge};
14use embassy_stm32::{bind_interrupts, peripherals}; 14use embassy_stm32::{bind_interrupts, peripherals};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embedded_graphics::Pixel;
16use embedded_graphics::draw_target::DrawTarget; 17use embedded_graphics::draw_target::DrawTarget;
17use embedded_graphics::geometry::{OriginDimensions, Point, Size}; 18use embedded_graphics::geometry::{OriginDimensions, Point, Size};
18use embedded_graphics::image::Image; 19use embedded_graphics::image::Image;
19use embedded_graphics::pixelcolor::raw::RawU24;
20use embedded_graphics::pixelcolor::Rgb888; 20use embedded_graphics::pixelcolor::Rgb888;
21use embedded_graphics::pixelcolor::raw::RawU24;
21use embedded_graphics::prelude::*; 22use embedded_graphics::prelude::*;
22use embedded_graphics::primitives::Rectangle; 23use embedded_graphics::primitives::Rectangle;
23use embedded_graphics::Pixel;
24use heapless::{Entry, FnvIndexMap}; 24use heapless::{Entry, FnvIndexMap};
25use tinybmp::Bmp; 25use tinybmp::Bmp;
26use {defmt_rtt as _, panic_probe as _}; 26use {defmt_rtt as _, panic_probe as _};
@@ -317,7 +317,7 @@ impl OriginDimensions for DoubleBuffer {
317mod rcc_setup { 317mod rcc_setup {
318 318
319 use embassy_stm32::time::Hertz; 319 use embassy_stm32::time::Hertz;
320 use embassy_stm32::{rcc, Config, Peripherals}; 320 use embassy_stm32::{Config, Peripherals, rcc};
321 321
322 /// Sets up clocks for the stm32u5g9zj mcu 322 /// Sets up clocks for the stm32u5g9zj mcu
323 /// change this if you plan to use a different microcontroller 323 /// change this if you plan to use a different microcontroller
diff --git a/examples/stm32u5/src/bin/usb_hs_serial.rs b/examples/stm32u5/src/bin/usb_hs_serial.rs
index d37e7777b..c444d3479 100644
--- a/examples/stm32u5/src/bin/usb_hs_serial.rs
+++ b/examples/stm32u5/src/bin/usb_hs_serial.rs
@@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use panic_probe as _; 13use panic_probe as _;
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index ff7f4e5be..c0a768cbb 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -6,10 +6,10 @@ use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_stm32::usb::{Driver, Instance}; 8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 9use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
10use embassy_usb::Builder;
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use panic_probe as _; 13use panic_probe as _;
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 7ab13c290..83f7cb56b 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32wb-examples" 3name = "embassy-stm32wb-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
@@ -7,7 +7,7 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32wb55rg to your chip name in both dependencies, if necessary. 9# Change stm32wb55rg to your chip name in both dependencies, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power"] }
11embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } 11embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
@@ -26,8 +26,8 @@ static_cell = "2"
26 26
27[features] 27[features]
28default = ["ble", "mac"] 28default = ["ble", "mac"]
29mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"] 29mac = ["embassy-stm32-wpan/wb55_mac", "dep:embassy-net"]
30ble = ["embassy-stm32-wpan/ble"] 30ble = ["embassy-stm32-wpan/wb55_ble"]
31 31
32[[bin]] 32[[bin]]
33name = "tl_mbox_ble" 33name = "tl_mbox_ble"
diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs
index 2871fd55f..3c58eb556 100644
--- a/examples/stm32wb/src/bin/button_exti.rs
+++ b/examples/stm32wb/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4 => exti::InterruptHandler<interrupt::typelevel::EXTI4>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up); 21 let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs
index 3bd8b4a63..413b1ac8f 100644
--- a/examples/stm32wb/src/bin/eddystone_beacon.rs
+++ b/examples/stm32wb/src/bin/eddystone_beacon.rs
@@ -8,15 +8,15 @@ use embassy_executor::Spawner;
8use embassy_stm32::bind_interrupts; 8use embassy_stm32::bind_interrupts;
9use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 9use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
10use embassy_stm32::rcc::WPAN_DEFAULT; 10use embassy_stm32::rcc::WPAN_DEFAULT;
11use embassy_stm32_wpan::TlMbox;
12use embassy_stm32_wpan::hci::BdAddr;
11use embassy_stm32_wpan::hci::host::uart::UartHci; 13use embassy_stm32_wpan::hci::host::uart::UartHci;
12use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; 14use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType};
13use embassy_stm32_wpan::hci::types::AdvertisingType; 15use embassy_stm32_wpan::hci::types::AdvertisingType;
14use embassy_stm32_wpan::hci::vendor::command::gap::{AdvertisingDataType, DiscoverableParameters, GapCommands, Role}; 16use embassy_stm32_wpan::hci::vendor::command::gap::{AdvertisingDataType, DiscoverableParameters, GapCommands, Role};
15use embassy_stm32_wpan::hci::vendor::command::gatt::GattCommands; 17use embassy_stm32_wpan::hci::vendor::command::gatt::GattCommands;
16use embassy_stm32_wpan::hci::vendor::command::hal::{ConfigData, HalCommands, PowerLevel}; 18use embassy_stm32_wpan::hci::vendor::command::hal::{ConfigData, HalCommands, PowerLevel};
17use embassy_stm32_wpan::hci::BdAddr;
18use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; 19use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp;
19use embassy_stm32_wpan::TlMbox;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
21 21
22bind_interrupts!(struct Irqs{ 22bind_interrupts!(struct Irqs{
@@ -57,126 +57,112 @@ async fn main(_spawner: Spawner) {
57 info!("Hello World!"); 57 info!("Hello World!");
58 58
59 let config = Config::default(); 59 let config = Config::default();
60 let mut mbox = TlMbox::init(p.IPCC, Irqs, config); 60 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
61 61 let mut sys = mbox.sys_subsystem;
62 let sys_event = mbox.sys_subsystem.read().await; 62 let mut ble = mbox.ble_subsystem;
63 info!("sys event: {}", sys_event.payload());
64 63
65 let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; 64 let _ = sys.shci_c2_ble_init(Default::default()).await;
66 65
67 info!("resetting BLE..."); 66 info!("resetting BLE...");
68 mbox.ble_subsystem.reset().await; 67 ble.reset().await;
69 let response = mbox.ble_subsystem.read().await.unwrap(); 68 let response = ble.read().await.unwrap();
70 defmt::info!("{}", response); 69 defmt::info!("{}", response);
71 70
72 info!("config public address..."); 71 info!("config public address...");
73 mbox.ble_subsystem 72 ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build())
74 .write_config_data(&ConfigData::public_address(get_bd_addr()).build())
75 .await; 73 .await;
76 let response = mbox.ble_subsystem.read().await.unwrap(); 74 let response = ble.read().await.unwrap();
77 defmt::info!("{}", response); 75 defmt::info!("{}", response);
78 76
79 info!("config random address..."); 77 info!("config random address...");
80 mbox.ble_subsystem 78 ble.write_config_data(&ConfigData::random_address(get_random_addr()).build())
81 .write_config_data(&ConfigData::random_address(get_random_addr()).build())
82 .await; 79 .await;
83 let response = mbox.ble_subsystem.read().await.unwrap(); 80 let response = ble.read().await.unwrap();
84 defmt::info!("{}", response); 81 defmt::info!("{}", response);
85 82
86 info!("config identity root..."); 83 info!("config identity root...");
87 mbox.ble_subsystem 84 ble.write_config_data(&ConfigData::identity_root(&get_irk()).build())
88 .write_config_data(&ConfigData::identity_root(&get_irk()).build())
89 .await; 85 .await;
90 let response = mbox.ble_subsystem.read().await.unwrap(); 86 let response = ble.read().await.unwrap();
91 defmt::info!("{}", response); 87 defmt::info!("{}", response);
92 88
93 info!("config encryption root..."); 89 info!("config encryption root...");
94 mbox.ble_subsystem 90 ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build())
95 .write_config_data(&ConfigData::encryption_root(&get_erk()).build())
96 .await; 91 .await;
97 let response = mbox.ble_subsystem.read().await.unwrap(); 92 let response = ble.read().await.unwrap();
98 defmt::info!("{}", response); 93 defmt::info!("{}", response);
99 94
100 info!("config tx power level..."); 95 info!("config tx power level...");
101 mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; 96 ble.set_tx_power_level(PowerLevel::ZerodBm).await;
102 let response = mbox.ble_subsystem.read().await.unwrap(); 97 let response = ble.read().await.unwrap();
103 defmt::info!("{}", response); 98 defmt::info!("{}", response);
104 99
105 info!("GATT init..."); 100 info!("GATT init...");
106 mbox.ble_subsystem.init_gatt().await; 101 ble.init_gatt().await;
107 let response = mbox.ble_subsystem.read().await.unwrap(); 102 let response = ble.read().await.unwrap();
108 defmt::info!("{}", response); 103 defmt::info!("{}", response);
109 104
110 info!("GAP init..."); 105 info!("GAP init...");
111 mbox.ble_subsystem 106 ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await;
112 .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) 107 let response = ble.read().await.unwrap();
113 .await;
114 let response = mbox.ble_subsystem.read().await.unwrap();
115 defmt::info!("{}", response); 108 defmt::info!("{}", response);
116 109
117 // info!("set scan response..."); 110 // info!("set scan response...");
118 // mbox.ble_subsystem.le_set_scan_response_data(&[]).await.unwrap(); 111 // ble.le_set_scan_response_data(&[]).await.unwrap();
119 // let response = mbox.ble_subsystem.read().await.unwrap(); 112 // let response = ble.read().await.unwrap();
120 // defmt::info!("{}", response); 113 // defmt::info!("{}", response);
121 114
122 info!("set discoverable..."); 115 info!("set discoverable...");
123 mbox.ble_subsystem 116 ble.set_discoverable(&DiscoverableParameters {
124 .set_discoverable(&DiscoverableParameters { 117 advertising_type: AdvertisingType::NonConnectableUndirected,
125 advertising_type: AdvertisingType::NonConnectableUndirected, 118 advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))),
126 advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), 119 address_type: OwnAddressType::Public,
127 address_type: OwnAddressType::Public, 120 filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
128 filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, 121 local_name: None,
129 local_name: None, 122 advertising_data: &[],
130 advertising_data: &[], 123 conn_interval: (None, None),
131 conn_interval: (None, None), 124 })
132 }) 125 .await
133 .await 126 .unwrap();
134 .unwrap(); 127
135 128 let response = ble.read().await;
136 let response = mbox.ble_subsystem.read().await;
137 defmt::info!("{}", response); 129 defmt::info!("{}", response);
138 130
139 // remove some advertisement to decrease the packet size 131 // remove some advertisement to decrease the packet size
140 info!("delete tx power ad type..."); 132 info!("delete tx power ad type...");
141 mbox.ble_subsystem 133 ble.delete_ad_type(AdvertisingDataType::TxPowerLevel).await;
142 .delete_ad_type(AdvertisingDataType::TxPowerLevel) 134 let response = ble.read().await.unwrap();
143 .await;
144 let response = mbox.ble_subsystem.read().await.unwrap();
145 defmt::info!("{}", response); 135 defmt::info!("{}", response);
146 136
147 info!("delete conn interval ad type..."); 137 info!("delete conn interval ad type...");
148 mbox.ble_subsystem 138 ble.delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval)
149 .delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval)
150 .await; 139 .await;
151 let response = mbox.ble_subsystem.read().await.unwrap(); 140 let response = ble.read().await.unwrap();
152 defmt::info!("{}", response); 141 defmt::info!("{}", response);
153 142
154 info!("update advertising data..."); 143 info!("update advertising data...");
155 mbox.ble_subsystem 144 ble.update_advertising_data(&eddystone_advertising_data())
156 .update_advertising_data(&eddystone_advertising_data())
157 .await 145 .await
158 .unwrap(); 146 .unwrap();
159 let response = mbox.ble_subsystem.read().await.unwrap(); 147 let response = ble.read().await.unwrap();
160 defmt::info!("{}", response); 148 defmt::info!("{}", response);
161 149
162 info!("update advertising data type..."); 150 info!("update advertising data type...");
163 mbox.ble_subsystem 151 ble.update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe])
164 .update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe])
165 .await 152 .await
166 .unwrap(); 153 .unwrap();
167 let response = mbox.ble_subsystem.read().await.unwrap(); 154 let response = ble.read().await.unwrap();
168 defmt::info!("{}", response); 155 defmt::info!("{}", response);
169 156
170 info!("update advertising data flags..."); 157 info!("update advertising data flags...");
171 mbox.ble_subsystem 158 ble.update_advertising_data(&[
172 .update_advertising_data(&[ 159 2,
173 2, 160 AdvertisingDataType::Flags as u8,
174 AdvertisingDataType::Flags as u8, 161 (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support
175 (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support 162 ])
176 ]) 163 .await
177 .await 164 .unwrap();
178 .unwrap(); 165 let response = ble.read().await.unwrap();
179 let response = mbox.ble_subsystem.read().await.unwrap();
180 defmt::info!("{}", response); 166 defmt::info!("{}", response);
181 167
182 cortex_m::asm::wfi(); 168 cortex_m::asm::wfi();
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs
index 5d927bc00..3484f1844 100644
--- a/examples/stm32wb/src/bin/gatt_server.rs
+++ b/examples/stm32wb/src/bin/gatt_server.rs
@@ -8,6 +8,7 @@ use embassy_executor::Spawner;
8use embassy_stm32::bind_interrupts; 8use embassy_stm32::bind_interrupts;
9use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 9use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
10use embassy_stm32::rcc::WPAN_DEFAULT; 10use embassy_stm32::rcc::WPAN_DEFAULT;
11use embassy_stm32_wpan::TlMbox;
11use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; 12use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters};
12use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; 13use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci};
13use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; 14use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType};
@@ -28,7 +29,6 @@ use embassy_stm32_wpan::hci::{BdAddr, Event};
28use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; 29use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp;
29use embassy_stm32_wpan::sub::ble::Ble; 30use embassy_stm32_wpan::sub::ble::Ble;
30use embassy_stm32_wpan::sub::mm; 31use embassy_stm32_wpan::sub::mm;
31use embassy_stm32_wpan::TlMbox;
32use {defmt_rtt as _, panic_probe as _}; 32use {defmt_rtt as _, panic_probe as _};
33 33
34bind_interrupts!(struct Irqs{ 34bind_interrupts!(struct Irqs{
@@ -69,92 +69,85 @@ async fn main(spawner: Spawner) {
69 info!("Hello World!"); 69 info!("Hello World!");
70 70
71 let config = Config::default(); 71 let config = Config::default();
72 let mut mbox = TlMbox::init(p.IPCC, Irqs, config); 72 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
73 let mut sys = mbox.sys_subsystem;
74 let mut ble = mbox.ble_subsystem;
73 75
74 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); 76 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
75 let sys_event = mbox.sys_subsystem.read().await;
76 info!("sys event: {}", sys_event.payload());
77 77
78 let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; 78 let _ = sys.shci_c2_ble_init(Default::default()).await;
79 79
80 info!("resetting BLE..."); 80 info!("resetting BLE...");
81 mbox.ble_subsystem.reset().await; 81 ble.reset().await;
82 let response = mbox.ble_subsystem.read().await; 82 let response = ble.read().await;
83 defmt::debug!("{}", response); 83 defmt::debug!("{}", response);
84 84
85 info!("config public address..."); 85 info!("config public address...");
86 mbox.ble_subsystem 86 ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build())
87 .write_config_data(&ConfigData::public_address(get_bd_addr()).build())
88 .await; 87 .await;
89 let response = mbox.ble_subsystem.read().await; 88 let response = ble.read().await;
90 defmt::debug!("{}", response); 89 defmt::debug!("{}", response);
91 90
92 info!("config random address..."); 91 info!("config random address...");
93 mbox.ble_subsystem 92 ble.write_config_data(&ConfigData::random_address(get_random_addr()).build())
94 .write_config_data(&ConfigData::random_address(get_random_addr()).build())
95 .await; 93 .await;
96 let response = mbox.ble_subsystem.read().await; 94 let response = ble.read().await;
97 defmt::debug!("{}", response); 95 defmt::debug!("{}", response);
98 96
99 info!("config identity root..."); 97 info!("config identity root...");
100 mbox.ble_subsystem 98 ble.write_config_data(&ConfigData::identity_root(&get_irk()).build())
101 .write_config_data(&ConfigData::identity_root(&get_irk()).build())
102 .await; 99 .await;
103 let response = mbox.ble_subsystem.read().await; 100 let response = ble.read().await;
104 defmt::debug!("{}", response); 101 defmt::debug!("{}", response);
105 102
106 info!("config encryption root..."); 103 info!("config encryption root...");
107 mbox.ble_subsystem 104 ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build())
108 .write_config_data(&ConfigData::encryption_root(&get_erk()).build())
109 .await; 105 .await;
110 let response = mbox.ble_subsystem.read().await; 106 let response = ble.read().await;
111 defmt::debug!("{}", response); 107 defmt::debug!("{}", response);
112 108
113 info!("config tx power level..."); 109 info!("config tx power level...");
114 mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; 110 ble.set_tx_power_level(PowerLevel::ZerodBm).await;
115 let response = mbox.ble_subsystem.read().await; 111 let response = ble.read().await;
116 defmt::debug!("{}", response); 112 defmt::debug!("{}", response);
117 113
118 info!("GATT init..."); 114 info!("GATT init...");
119 mbox.ble_subsystem.init_gatt().await; 115 ble.init_gatt().await;
120 let response = mbox.ble_subsystem.read().await; 116 let response = ble.read().await;
121 defmt::debug!("{}", response); 117 defmt::debug!("{}", response);
122 118
123 info!("GAP init..."); 119 info!("GAP init...");
124 mbox.ble_subsystem 120 ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await;
125 .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) 121 let response = ble.read().await;
126 .await;
127 let response = mbox.ble_subsystem.read().await;
128 defmt::debug!("{}", response); 122 defmt::debug!("{}", response);
129 123
130 info!("set IO capabilities..."); 124 info!("set IO capabilities...");
131 mbox.ble_subsystem.set_io_capability(IoCapability::DisplayConfirm).await; 125 ble.set_io_capability(IoCapability::DisplayConfirm).await;
132 let response = mbox.ble_subsystem.read().await; 126 let response = ble.read().await;
133 defmt::debug!("{}", response); 127 defmt::debug!("{}", response);
134 128
135 info!("set authentication requirements..."); 129 info!("set authentication requirements...");
136 mbox.ble_subsystem 130 ble.set_authentication_requirement(&AuthenticationRequirements {
137 .set_authentication_requirement(&AuthenticationRequirements { 131 bonding_required: false,
138 bonding_required: false, 132 keypress_notification_support: false,
139 keypress_notification_support: false, 133 mitm_protection_required: false,
140 mitm_protection_required: false, 134 encryption_key_size_range: (8, 16),
141 encryption_key_size_range: (8, 16), 135 fixed_pin: Pin::Requested,
142 fixed_pin: Pin::Requested, 136 identity_address_type: AddressType::Public,
143 identity_address_type: AddressType::Public, 137 secure_connection_support: SecureConnectionSupport::Optional,
144 secure_connection_support: SecureConnectionSupport::Optional, 138 })
145 }) 139 .await
146 .await 140 .unwrap();
147 .unwrap(); 141 let response = ble.read().await;
148 let response = mbox.ble_subsystem.read().await;
149 defmt::debug!("{}", response); 142 defmt::debug!("{}", response);
150 143
151 info!("set scan response data..."); 144 info!("set scan response data...");
152 mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); 145 ble.le_set_scan_response_data(b"TXTX").await.unwrap();
153 let response = mbox.ble_subsystem.read().await; 146 let response = ble.read().await;
154 defmt::debug!("{}", response); 147 defmt::debug!("{}", response);
155 148
156 defmt::info!("initializing services and characteristics..."); 149 defmt::info!("initializing services and characteristics...");
157 let mut ble_context = init_gatt_services(&mut mbox.ble_subsystem).await.unwrap(); 150 let mut ble_context = init_gatt_services(&mut ble).await.unwrap();
158 defmt::info!("{}", ble_context); 151 defmt::info!("{}", ble_context);
159 152
160 let discovery_params = DiscoverableParameters { 153 let discovery_params = DiscoverableParameters {
@@ -168,12 +161,12 @@ async fn main(spawner: Spawner) {
168 }; 161 };
169 162
170 info!("set discoverable..."); 163 info!("set discoverable...");
171 mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); 164 ble.set_discoverable(&discovery_params).await.unwrap();
172 let response = mbox.ble_subsystem.read().await; 165 let response = ble.read().await;
173 defmt::debug!("{}", response); 166 defmt::debug!("{}", response);
174 167
175 loop { 168 loop {
176 let response = mbox.ble_subsystem.read().await; 169 let response = ble.read().await;
177 defmt::debug!("{}", response); 170 defmt::debug!("{}", response);
178 171
179 if let Ok(Packet::Event(event)) = response { 172 if let Ok(Packet::Event(event)) = response {
@@ -184,24 +177,23 @@ async fn main(spawner: Spawner) {
184 Event::DisconnectionComplete(_) => { 177 Event::DisconnectionComplete(_) => {
185 defmt::info!("disconnected"); 178 defmt::info!("disconnected");
186 ble_context.is_subscribed = false; 179 ble_context.is_subscribed = false;
187 mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); 180 ble.set_discoverable(&discovery_params).await.unwrap();
188 } 181 }
189 Event::Vendor(vendor_event) => match vendor_event { 182 Event::Vendor(vendor_event) => match vendor_event {
190 VendorEvent::AttReadPermitRequest(read_req) => { 183 VendorEvent::AttReadPermitRequest(read_req) => {
191 defmt::info!("read request received {}, allowing", read_req); 184 defmt::info!("read request received {}, allowing", read_req);
192 mbox.ble_subsystem.allow_read(read_req.conn_handle).await 185 ble.allow_read(read_req.conn_handle).await
193 } 186 }
194 VendorEvent::AttWritePermitRequest(write_req) => { 187 VendorEvent::AttWritePermitRequest(write_req) => {
195 defmt::info!("write request received {}, allowing", write_req); 188 defmt::info!("write request received {}, allowing", write_req);
196 mbox.ble_subsystem 189 ble.write_response(&WriteResponseParameters {
197 .write_response(&WriteResponseParameters { 190 conn_handle: write_req.conn_handle,
198 conn_handle: write_req.conn_handle, 191 attribute_handle: write_req.attribute_handle,
199 attribute_handle: write_req.attribute_handle, 192 status: Ok(()),
200 status: Ok(()), 193 value: write_req.value(),
201 value: write_req.value(), 194 })
202 }) 195 .await
203 .await 196 .unwrap()
204 .unwrap()
205 } 197 }
206 VendorEvent::GattAttributeModified(attribute) => { 198 VendorEvent::GattAttributeModified(attribute) => {
207 defmt::info!("{}", ble_context); 199 defmt::info!("{}", ble_context);
@@ -224,7 +216,7 @@ async fn main(spawner: Spawner) {
224} 216}
225 217
226#[embassy_executor::task] 218#[embassy_executor::task]
227async fn run_mm_queue(memory_manager: mm::MemoryManager) { 219async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
228 memory_manager.run_queue().await; 220 memory_manager.run_queue().await;
229} 221}
230 222
@@ -285,7 +277,7 @@ pub struct CharHandles {
285 pub notify: AttributeHandle, 277 pub notify: AttributeHandle,
286} 278}
287 279
288pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result<BleContext, ()> { 280pub async fn init_gatt_services<'a>(ble_subsystem: &mut Ble<'a>) -> Result<BleContext, ()> {
289 let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; 281 let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?;
290 282
291 let read = gatt_add_char( 283 let read = gatt_add_char(
@@ -322,7 +314,7 @@ pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result<BleContext, (
322 }) 314 })
323} 315}
324 316
325async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result<AttributeHandle, ()> { 317async fn gatt_add_service<'a>(ble_subsystem: &mut Ble<'a>, uuid: Uuid) -> Result<AttributeHandle, ()> {
326 ble_subsystem 318 ble_subsystem
327 .add_service(&AddServiceParameters { 319 .add_service(&AddServiceParameters {
328 uuid, 320 uuid,
@@ -348,8 +340,8 @@ async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result<Attribu
348 } 340 }
349} 341}
350 342
351async fn gatt_add_char( 343async fn gatt_add_char<'a>(
352 ble_subsystem: &mut Ble, 344 ble_subsystem: &mut Ble<'a>,
353 service_handle: AttributeHandle, 345 service_handle: AttributeHandle,
354 characteristic_uuid: Uuid, 346 characteristic_uuid: Uuid,
355 characteristic_properties: CharacteristicProperty, 347 characteristic_properties: CharacteristicProperty,
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index ede6cf4b9..4bab6ea9f 100644
--- a/examples/stm32wb/src/bin/mac_ffd.rs
+++ b/examples/stm32wb/src/bin/mac_ffd.rs
@@ -6,11 +6,11 @@ use embassy_executor::Spawner;
6use embassy_stm32::bind_interrupts; 6use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
8use embassy_stm32::rcc::WPAN_DEFAULT; 8use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox;
9use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; 10use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest};
10use embassy_stm32_wpan::mac::event::MacEvent; 11use embassy_stm32_wpan::mac::event::MacEvent;
11use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; 12use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel};
12use embassy_stm32_wpan::sub::mm; 13use embassy_stm32_wpan::sub::mm;
13use embassy_stm32_wpan::TlMbox;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs{ 16bind_interrupts!(struct Irqs{
@@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs{
19}); 19});
20 20
21#[embassy_executor::task] 21#[embassy_executor::task]
22async fn run_mm_queue(memory_manager: mm::MemoryManager) { 22async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
23 memory_manager.run_queue().await; 23 memory_manager.run_queue().await;
24} 24}
25 25
@@ -54,74 +54,72 @@ async fn main(spawner: Spawner) {
54 info!("Hello World!"); 54 info!("Hello World!");
55 55
56 let config = Config::default(); 56 let config = Config::default();
57 let mbox = TlMbox::init(p.IPCC, Irqs, config); 57 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
58 let mut sys = mbox.sys_subsystem;
58 59
59 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); 60 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
60 61
61 let sys_event = mbox.sys_subsystem.read().await; 62 let result = sys.shci_c2_mac_802_15_4_init().await;
62 info!("sys event: {}", sys_event.payload());
63
64 core::mem::drop(sys_event);
65
66 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
67 info!("initialized mac: {}", result); 63 info!("initialized mac: {}", result);
68 64
65 let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split();
66
69 info!("resetting"); 67 info!("resetting");
70 mbox.mac_subsystem 68 mac_tx
71 .send_command(&ResetRequest { 69 .send_command(&ResetRequest {
72 set_default_pib: true, 70 set_default_pib: true,
73 ..Default::default() 71 ..Default::default()
74 }) 72 })
75 .await 73 .await
76 .unwrap(); 74 .unwrap();
77 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 75 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
78 76
79 info!("setting extended address"); 77 info!("setting extended address");
80 let extended_address: u64 = 0xACDE480000000001; 78 let extended_address: u64 = 0xACDE480000000001;
81 mbox.mac_subsystem 79 mac_tx
82 .send_command(&SetRequest { 80 .send_command(&SetRequest {
83 pib_attribute_ptr: &extended_address as *const _ as *const u8, 81 pib_attribute_ptr: &extended_address as *const _ as *const u8,
84 pib_attribute: PibId::ExtendedAddress, 82 pib_attribute: PibId::ExtendedAddress,
85 }) 83 })
86 .await 84 .await
87 .unwrap(); 85 .unwrap();
88 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 86 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
89 87
90 info!("setting short address"); 88 info!("setting short address");
91 let short_address: u16 = 0x1122; 89 let short_address: u16 = 0x1122;
92 mbox.mac_subsystem 90 mac_tx
93 .send_command(&SetRequest { 91 .send_command(&SetRequest {
94 pib_attribute_ptr: &short_address as *const _ as *const u8, 92 pib_attribute_ptr: &short_address as *const _ as *const u8,
95 pib_attribute: PibId::ShortAddress, 93 pib_attribute: PibId::ShortAddress,
96 }) 94 })
97 .await 95 .await
98 .unwrap(); 96 .unwrap();
99 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 97 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
100 98
101 info!("setting association permit"); 99 info!("setting association permit");
102 let association_permit: bool = true; 100 let association_permit: bool = true;
103 mbox.mac_subsystem 101 mac_tx
104 .send_command(&SetRequest { 102 .send_command(&SetRequest {
105 pib_attribute_ptr: &association_permit as *const _ as *const u8, 103 pib_attribute_ptr: &association_permit as *const _ as *const u8,
106 pib_attribute: PibId::AssociationPermit, 104 pib_attribute: PibId::AssociationPermit,
107 }) 105 })
108 .await 106 .await
109 .unwrap(); 107 .unwrap();
110 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 108 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
111 109
112 info!("setting TX power"); 110 info!("setting TX power");
113 let transmit_power: i8 = 2; 111 let transmit_power: i8 = 2;
114 mbox.mac_subsystem 112 mac_tx
115 .send_command(&SetRequest { 113 .send_command(&SetRequest {
116 pib_attribute_ptr: &transmit_power as *const _ as *const u8, 114 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
117 pib_attribute: PibId::TransmitPower, 115 pib_attribute: PibId::TransmitPower,
118 }) 116 })
119 .await 117 .await
120 .unwrap(); 118 .unwrap();
121 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 119 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
122 120
123 info!("starting FFD device"); 121 info!("starting FFD device");
124 mbox.mac_subsystem 122 mac_tx
125 .send_command(&StartRequest { 123 .send_command(&StartRequest {
126 pan_id: PanId([0x1A, 0xAA]), 124 pan_id: PanId([0x1A, 0xAA]),
127 channel_number: MacChannel::Channel16, 125 channel_number: MacChannel::Channel16,
@@ -133,28 +131,27 @@ async fn main(spawner: Spawner) {
133 }) 131 })
134 .await 132 .await
135 .unwrap(); 133 .unwrap();
136 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 134 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
137 135
138 info!("setting RX on when idle"); 136 info!("setting RX on when idle");
139 let rx_on_while_idle: bool = true; 137 let rx_on_while_idle: bool = true;
140 mbox.mac_subsystem 138 mac_tx
141 .send_command(&SetRequest { 139 .send_command(&SetRequest {
142 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, 140 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
143 pib_attribute: PibId::RxOnWhenIdle, 141 pib_attribute: PibId::RxOnWhenIdle,
144 }) 142 })
145 .await 143 .await
146 .unwrap(); 144 .unwrap();
147 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 145 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
148 146
149 loop { 147 loop {
150 let evt = mbox.mac_subsystem.read().await; 148 let evt = mac_rx.read().await;
151 if let Ok(evt) = evt { 149 if let Ok(evt) = evt {
152 defmt::info!("parsed mac event"); 150 defmt::info!("parsed mac event");
153 defmt::info!("{:#x}", evt); 151 defmt::info!("{:#x}", evt);
154 152
155 match evt { 153 match evt {
156 MacEvent::MlmeAssociateInd(association) => mbox 154 MacEvent::MlmeAssociateInd(association) => mac_tx
157 .mac_subsystem
158 .send_command(&AssociateResponse { 155 .send_command(&AssociateResponse {
159 device_address: association.device_address, 156 device_address: association.device_address,
160 assoc_short_address: [0x33, 0x44], 157 assoc_short_address: [0x33, 0x44],
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index cc3b21e2e..b4789e3ee 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -1,32 +1,44 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::net::Ipv6Addr;
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_net::udp::{PacketMetadata, UdpSocket};
9use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6};
6use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 11use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
12use embassy_stm32::peripherals::RNG;
8use embassy_stm32::rcc::WPAN_DEFAULT; 13use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; 14use embassy_stm32::rng::InterruptHandler as RngInterruptHandler;
10use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
11use embassy_stm32_wpan::mac::{self, Runner};
12use embassy_stm32_wpan::sub::mm;
13use embassy_stm32_wpan::TlMbox; 15use embassy_stm32_wpan::TlMbox;
16use embassy_stm32_wpan::mac::{Driver, DriverState, Runner};
17use embassy_stm32_wpan::sub::mm;
18use embassy_time::{Duration, Timer};
19use heapless::Vec;
14use static_cell::StaticCell; 20use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
16 22
17bind_interrupts!(struct Irqs{ 23bind_interrupts!(struct Irqs{
18 IPCC_C1_RX => ReceiveInterruptHandler; 24 IPCC_C1_RX => ReceiveInterruptHandler;
19 IPCC_C1_TX => TransmitInterruptHandler; 25 IPCC_C1_TX => TransmitInterruptHandler;
26 RNG => RngInterruptHandler<RNG>;
20}); 27});
21 28
22#[embassy_executor::task] 29#[embassy_executor::task]
23async fn run_mm_queue(memory_manager: mm::MemoryManager) { 30async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) -> ! {
24 memory_manager.run_queue().await; 31 memory_manager.run_queue().await
25} 32}
26 33
27#[embassy_executor::task] 34#[embassy_executor::task]
28async fn run_mac(runner: &'static Runner<'static>) { 35async fn run_mac(runner: &'static Runner<'static>) -> ! {
29 runner.run().await; 36 runner.run().await
37}
38
39#[embassy_executor::task]
40async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! {
41 runner.run().await
30} 42}
31 43
32#[embassy_executor::main] 44#[embassy_executor::main]
@@ -60,118 +72,76 @@ async fn main(spawner: Spawner) {
60 info!("Hello World!"); 72 info!("Hello World!");
61 73
62 let config = Config::default(); 74 let config = Config::default();
63 let mbox = TlMbox::init(p.IPCC, Irqs, config); 75 let mut mbox = TlMbox::init(p.IPCC, Irqs, config).await;
64 76
65 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); 77 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
66 78
67 let sys_event = mbox.sys_subsystem.read().await;
68 info!("sys event: {}", sys_event.payload());
69
70 core::mem::drop(sys_event);
71
72 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; 79 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
73 info!("initialized mac: {}", result); 80 info!("initialized mac: {}", result);
74 81
75 info!("resetting"); 82 static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new();
76 mbox.mac_subsystem
77 .send_command(&ResetRequest {
78 set_default_pib: true,
79 ..Default::default()
80 })
81 .await
82 .unwrap();
83 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
84
85 info!("setting extended address");
86 let extended_address: u64 = 0xACDE480000000001;
87 mbox.mac_subsystem
88 .send_command(&SetRequest {
89 pib_attribute_ptr: &extended_address as *const _ as *const u8,
90 pib_attribute: PibId::ExtendedAddress,
91 })
92 .await
93 .unwrap();
94 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
95
96 info!("setting short address");
97 let short_address: u16 = 0x1122;
98 mbox.mac_subsystem
99 .send_command(&SetRequest {
100 pib_attribute_ptr: &short_address as *const _ as *const u8,
101 pib_attribute: PibId::ShortAddress,
102 })
103 .await
104 .unwrap();
105 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
106
107 info!("setting association permit");
108 let association_permit: bool = true;
109 mbox.mac_subsystem
110 .send_command(&SetRequest {
111 pib_attribute_ptr: &association_permit as *const _ as *const u8,
112 pib_attribute: PibId::AssociationPermit,
113 })
114 .await
115 .unwrap();
116 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
117
118 info!("setting TX power");
119 let transmit_power: i8 = 2;
120 mbox.mac_subsystem
121 .send_command(&SetRequest {
122 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
123 pib_attribute: PibId::TransmitPower,
124 })
125 .await
126 .unwrap();
127 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
128
129 info!("starting FFD device");
130 mbox.mac_subsystem
131 .send_command(&StartRequest {
132 pan_id: PanId([0x1A, 0xAA]),
133 channel_number: MacChannel::Channel16,
134 beacon_order: 0x0F,
135 superframe_order: 0x0F,
136 pan_coordinator: true,
137 battery_life_extension: false,
138 ..Default::default()
139 })
140 .await
141 .unwrap();
142 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
143
144 info!("setting RX on when idle");
145 let rx_on_while_idle: bool = true;
146 mbox.mac_subsystem
147 .send_command(&SetRequest {
148 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
149 pib_attribute: PibId::RxOnWhenIdle,
150 })
151 .await
152 .unwrap();
153 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
154
155 static TX1: StaticCell<[u8; 127]> = StaticCell::new();
156 static TX2: StaticCell<[u8; 127]> = StaticCell::new();
157 static TX3: StaticCell<[u8; 127]> = StaticCell::new();
158 static TX4: StaticCell<[u8; 127]> = StaticCell::new();
159 static TX5: StaticCell<[u8; 127]> = StaticCell::new();
160 let tx_queue = [
161 TX1.init([0u8; 127]),
162 TX2.init([0u8; 127]),
163 TX3.init([0u8; 127]),
164 TX4.init([0u8; 127]),
165 TX5.init([0u8; 127]),
166 ];
167
168 static RUNNER: StaticCell<Runner> = StaticCell::new(); 83 static RUNNER: StaticCell<Runner> = StaticCell::new();
169 let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); 84 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
85
86 let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem));
87
88 let (driver, mac_runner, mut control) = Driver::new(
89 driver_state,
90 0x1122u16.to_be_bytes().try_into().unwrap(),
91 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(),
92 );
93
94 // TODO: rng does not work for some reason
95 // Generate random seed.
96 // let mut rng = Rng::new(p.RNG, Irqs);
97 let seed = [0; 8];
98 // let _ = rng.async_fill_bytes(&mut seed).await;
99 let seed = u64::from_le_bytes(seed);
100
101 info!("seed generated");
102
103 // Init network stack
104 let ipv6_addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
105
106 let config = embassy_net::Config::ipv6_static(StaticConfigV6 {
107 address: Ipv6Cidr::new(ipv6_addr, 104),
108 gateway: None,
109 dns_servers: Vec::new(),
110 });
111
112 let (stack, eth_runner) = embassy_net::new(driver, config, RESOURCES.init(StackResources::new()), seed);
113
114 // wpan runner
115 spawner.spawn(run_mac(RUNNER.init(mac_runner)).unwrap());
116
117 // Launch network task
118 spawner.spawn(unwrap!(run_net(eth_runner)));
119
120 info!("Network task initialized");
121
122 control.init_link([0x1A, 0xAA]).await;
123
124 // Ensure DHCP configuration is up before trying connect
125 stack.wait_config_up().await;
126
127 info!("Network up");
128
129 // Then we can use it!
130 let mut rx_meta = [PacketMetadata::EMPTY];
131 let mut rx_buffer = [0; 4096];
132 let mut tx_meta = [PacketMetadata::EMPTY];
133 let mut tx_buffer = [0; 4096];
134
135 let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
136
137 let remote_endpoint = (Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2fb), 8000);
138
139 let send_buf = [0u8; 20];
170 140
171 spawner.spawn(run_mac(runner).unwrap()); 141 socket.bind((ipv6_addr, 8000)).unwrap();
142 socket.send_to(&send_buf, remote_endpoint).await.unwrap();
172 143
173 let (driver, control) = mac::new(runner).await; 144 Timer::after(Duration::from_secs(2)).await;
174 145
175 let _ = driver; 146 cortex_m::asm::bkpt();
176 let _ = control;
177} 147}
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index d872104a8..dae3c5200 100644
--- a/examples/stm32wb/src/bin/mac_rfd.rs
+++ b/examples/stm32wb/src/bin/mac_rfd.rs
@@ -6,13 +6,13 @@ use embassy_executor::Spawner;
6use embassy_stm32::bind_interrupts; 6use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
8use embassy_stm32::rcc::WPAN_DEFAULT; 8use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox;
9use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; 10use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest};
10use embassy_stm32_wpan::mac::event::MacEvent; 11use embassy_stm32_wpan::mac::event::MacEvent;
11use embassy_stm32_wpan::mac::typedefs::{ 12use embassy_stm32_wpan::mac::typedefs::{
12 AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, 13 AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel,
13}; 14};
14use embassy_stm32_wpan::sub::mm; 15use embassy_stm32_wpan::sub::mm;
15use embassy_stm32_wpan::TlMbox;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18bind_interrupts!(struct Irqs{ 18bind_interrupts!(struct Irqs{
@@ -21,7 +21,7 @@ bind_interrupts!(struct Irqs{
21}); 21});
22 22
23#[embassy_executor::task] 23#[embassy_executor::task]
24async fn run_mm_queue(memory_manager: mm::MemoryManager) { 24async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
25 memory_manager.run_queue().await; 25 memory_manager.run_queue().await;
26} 26}
27 27
@@ -56,41 +56,39 @@ async fn main(spawner: Spawner) {
56 info!("Hello World!"); 56 info!("Hello World!");
57 57
58 let config = Config::default(); 58 let config = Config::default();
59 let mbox = TlMbox::init(p.IPCC, Irqs, config); 59 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
60 let mut sys = mbox.sys_subsystem;
60 61
61 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); 62 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
62 63
63 let sys_event = mbox.sys_subsystem.read().await; 64 let result = sys.shci_c2_mac_802_15_4_init().await;
64 info!("sys event: {}", sys_event.payload());
65
66 core::mem::drop(sys_event);
67
68 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
69 info!("initialized mac: {}", result); 65 info!("initialized mac: {}", result);
70 66
67 let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split();
68
71 info!("resetting"); 69 info!("resetting");
72 mbox.mac_subsystem 70 mac_tx
73 .send_command(&ResetRequest { 71 .send_command(&ResetRequest {
74 set_default_pib: true, 72 set_default_pib: true,
75 ..Default::default() 73 ..Default::default()
76 }) 74 })
77 .await 75 .await
78 .unwrap(); 76 .unwrap();
79 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 77 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
80 78
81 info!("setting extended address"); 79 info!("setting extended address");
82 let extended_address: u64 = 0xACDE480000000002; 80 let extended_address: u64 = 0xACDE480000000002;
83 mbox.mac_subsystem 81 mac_tx
84 .send_command(&SetRequest { 82 .send_command(&SetRequest {
85 pib_attribute_ptr: &extended_address as *const _ as *const u8, 83 pib_attribute_ptr: &extended_address as *const _ as *const u8,
86 pib_attribute: PibId::ExtendedAddress, 84 pib_attribute: PibId::ExtendedAddress,
87 }) 85 })
88 .await 86 .await
89 .unwrap(); 87 .unwrap();
90 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); 88 defmt::info!("{:#x}", mac_rx.read().await.unwrap());
91 89
92 info!("getting extended address"); 90 info!("getting extended address");
93 mbox.mac_subsystem 91 mac_tx
94 .send_command(&GetRequest { 92 .send_command(&GetRequest {
95 pib_attribute: PibId::ExtendedAddress, 93 pib_attribute: PibId::ExtendedAddress,
96 ..Default::default() 94 ..Default::default()
@@ -99,7 +97,7 @@ async fn main(spawner: Spawner) {
99 .unwrap(); 97 .unwrap();
100 98
101 { 99 {
102 let evt = mbox.mac_subsystem.read().await.unwrap(); 100 let evt = mac_rx.read().await.unwrap();
103 info!("{:#x}", evt); 101 info!("{:#x}", evt);
104 102
105 if let MacEvent::MlmeGetCnf(evt) = evt { 103 if let MacEvent::MlmeGetCnf(evt) = evt {
@@ -125,9 +123,9 @@ async fn main(spawner: Spawner) {
125 key_index: 152, 123 key_index: 152,
126 }; 124 };
127 info!("{}", a); 125 info!("{}", a);
128 mbox.mac_subsystem.send_command(&a).await.unwrap(); 126 mac_tx.send_command(&a).await.unwrap();
129 let short_addr = { 127 let short_addr = {
130 let evt = mbox.mac_subsystem.read().await.unwrap(); 128 let evt = mac_rx.read().await.unwrap();
131 info!("{:#x}", evt); 129 info!("{:#x}", evt);
132 130
133 if let MacEvent::MlmeAssociateCnf(conf) = evt { 131 if let MacEvent::MlmeAssociateCnf(conf) = evt {
@@ -138,7 +136,7 @@ async fn main(spawner: Spawner) {
138 }; 136 };
139 137
140 info!("setting short address"); 138 info!("setting short address");
141 mbox.mac_subsystem 139 mac_tx
142 .send_command(&SetRequest { 140 .send_command(&SetRequest {
143 pib_attribute_ptr: &short_addr as *const _ as *const u8, 141 pib_attribute_ptr: &short_addr as *const _ as *const u8,
144 pib_attribute: PibId::ShortAddress, 142 pib_attribute: PibId::ShortAddress,
@@ -146,13 +144,13 @@ async fn main(spawner: Spawner) {
146 .await 144 .await
147 .unwrap(); 145 .unwrap();
148 { 146 {
149 let evt = mbox.mac_subsystem.read().await.unwrap(); 147 let evt = mac_rx.read().await.unwrap();
150 info!("{:#x}", evt); 148 info!("{:#x}", evt);
151 } 149 }
152 150
153 info!("sending data"); 151 info!("sending data");
154 let data = b"Hello from embassy!"; 152 let data = b"Hello from embassy!";
155 mbox.mac_subsystem 153 mac_tx
156 .send_command( 154 .send_command(
157 DataRequest { 155 DataRequest {
158 src_addr_mode: AddressMode::Short, 156 src_addr_mode: AddressMode::Short,
@@ -170,12 +168,12 @@ async fn main(spawner: Spawner) {
170 .await 168 .await
171 .unwrap(); 169 .unwrap();
172 { 170 {
173 let evt = mbox.mac_subsystem.read().await.unwrap(); 171 let evt = mac_rx.read().await.unwrap();
174 info!("{:#x}", evt); 172 info!("{:#x}", evt);
175 } 173 }
176 174
177 loop { 175 loop {
178 match mbox.mac_subsystem.read().await { 176 match mac_rx.read().await {
179 Ok(evt) => info!("{:#x}", evt), 177 Ok(evt) => info!("{:#x}", evt),
180 _ => continue, 178 _ => continue,
181 }; 179 };
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 4e7f2304d..0902e28e8 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) {
46 info!("Hello World!"); 46 info!("Hello World!");
47 47
48 let config = Config::default(); 48 let config = Config::default();
49 let mbox = TlMbox::init(p.IPCC, Irqs, config); 49 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
50 50
51 loop { 51 loop {
52 let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); 52 let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info();
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs
index 72a4c18e6..763dc32cd 100644
--- a/examples/stm32wb/src/bin/tl_mbox_ble.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs
@@ -7,6 +7,7 @@ use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
8use embassy_stm32::rcc::WPAN_DEFAULT; 8use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox; 9use embassy_stm32_wpan::TlMbox;
10use embassy_stm32_wpan::sub::mm;
10use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
11 12
12bind_interrupts!(struct Irqs{ 13bind_interrupts!(struct Irqs{
@@ -14,8 +15,13 @@ bind_interrupts!(struct Irqs{
14 IPCC_C1_TX => TransmitInterruptHandler; 15 IPCC_C1_TX => TransmitInterruptHandler;
15}); 16});
16 17
18#[embassy_executor::task]
19async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
20 memory_manager.run_queue().await;
21}
22
17#[embassy_executor::main] 23#[embassy_executor::main]
18async fn main(_spawner: Spawner) { 24async fn main(spawner: Spawner) {
19 /* 25 /*
20 How to make this work: 26 How to make this work:
21 27
@@ -45,18 +51,19 @@ async fn main(_spawner: Spawner) {
45 info!("Hello World!"); 51 info!("Hello World!");
46 52
47 let config = Config::default(); 53 let config = Config::default();
48 let mbox = TlMbox::init(p.IPCC, Irqs, config); 54 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
55 let mut sys = mbox.sys_subsystem;
56 let mut ble = mbox.ble_subsystem;
49 57
50 let sys_event = mbox.sys_subsystem.read().await; 58 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
51 info!("sys event: {}", sys_event.payload());
52 59
53 let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; 60 let _ = sys.shci_c2_ble_init(Default::default()).await;
54 61
55 info!("starting ble..."); 62 info!("starting ble...");
56 mbox.ble_subsystem.tl_write(0x0c, &[]).await; 63 ble.tl_write(0x0c, &[]).await;
57 64
58 info!("waiting for ble..."); 65 info!("waiting for ble...");
59 let ble_event = mbox.ble_subsystem.tl_read().await; 66 let ble_event = ble.tl_read().await;
60 67
61 info!("ble event: {}", ble_event.payload()); 68 info!("ble event: {}", ble_event.payload());
62 69
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
index 95c73872b..235a48241 100644
--- a/examples/stm32wb/src/bin/tl_mbox_mac.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -6,8 +6,8 @@ use embassy_executor::Spawner;
6use embassy_stm32::bind_interrupts; 6use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
8use embassy_stm32::rcc::WPAN_DEFAULT; 8use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::sub::mm;
10use embassy_stm32_wpan::TlMbox; 9use embassy_stm32_wpan::TlMbox;
10use embassy_stm32_wpan::sub::mm;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs{ 13bind_interrupts!(struct Irqs{
@@ -16,7 +16,7 @@ bind_interrupts!(struct Irqs{
16}); 16});
17 17
18#[embassy_executor::task] 18#[embassy_executor::task]
19async fn run_mm_queue(memory_manager: mm::MemoryManager) { 19async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
20 memory_manager.run_queue().await; 20 memory_manager.run_queue().await;
21} 21}
22 22
@@ -51,16 +51,12 @@ async fn main(spawner: Spawner) {
51 info!("Hello World!"); 51 info!("Hello World!");
52 52
53 let config = Config::default(); 53 let config = Config::default();
54 let mbox = TlMbox::init(p.IPCC, Irqs, config); 54 let mbox = TlMbox::init(p.IPCC, Irqs, config).await;
55 let mut sys = mbox.sys_subsystem;
55 56
56 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); 57 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
57 58
58 let sys_event = mbox.sys_subsystem.read().await; 59 let result = sys.shci_c2_mac_802_15_4_init().await;
59 info!("sys event: {}", sys_event.payload());
60
61 core::mem::drop(sys_event);
62
63 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
64 info!("initialized mac: {}", result); 60 info!("initialized mac: {}", result);
65 61
66 // 62 //
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml
index e1196614a..b10114420 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -1,12 +1,13 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32wba-examples" 3name = "embassy-stm32wba-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } 9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba52cg", "time-driver-any", "memory-x", "exti"] }
10embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wba52cg"] }
10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
@@ -22,6 +23,11 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22heapless = { version = "0.8", default-features = false } 23heapless = { version = "0.8", default-features = false }
23static_cell = "2" 24static_cell = "2"
24 25
26[features]
27default = ["ble", "mac"]
28mac = ["embassy-stm32-wpan/wba_mac", "dep:embassy-net"]
29ble = ["embassy-stm32-wpan/wba_ble"]
30
25[profile.release] 31[profile.release]
26debug = 2 32debug = 2
27 33
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs
index a9651d57e..ade3f5d6a 100644
--- a/examples/stm32wba/src/bin/adc.rs
+++ b/examples/stm32wba/src/bin/adc.rs
@@ -2,7 +2,7 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{adc4, AdcChannel}; 5use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
7 7
8#[embassy_executor::main] 8#[embassy_executor::main]
@@ -12,20 +12,20 @@ async fn main(_spawner: embassy_executor::Spawner) {
12 let mut p = embassy_stm32::init(config); 12 let mut p = embassy_stm32::init(config);
13 13
14 // **** ADC4 init **** 14 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4); 15 let mut adc4 = Adc::new_adc4(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4 16 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5 17 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12); 18 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256); 19 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
20 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); 20
21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
22 22
23 // **** ADC4 blocking read **** 23 // **** ADC4 blocking read ****
24 let raw: u16 = adc4.blocking_read(&mut adc4_pin1); 24 let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5);
25 let volt: f32 = 3.0 * raw as f32 / max4 as f32; 25 let volt: f32 = 3.0 * raw as f32 / max4 as f32;
26 info!("Read adc4 pin 1 {}", volt); 26 info!("Read adc4 pin 1 {}", volt);
27 27
28 let raw: u16 = adc4.blocking_read(&mut adc4_pin2); 28 let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5);
29 let volt: f32 = 3.3 * raw as f32 / max4 as f32; 29 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
30 info!("Read adc4 pin 2 {}", volt); 30 info!("Read adc4 pin 2 {}", volt);
31 31
@@ -37,11 +37,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
37 // The channels must be in ascending order and can't repeat for ADC4 37 // The channels must be in ascending order and can't repeat for ADC4
38 adc4.read( 38 adc4.read(
39 p.GPDMA1_CH1.reborrow(), 39 p.GPDMA1_CH1.reborrow(),
40 [&mut degraded42, &mut degraded41].into_iter(), 40 [
41 (&mut degraded42, SampleTime::CYCLES12_5),
42 (&mut degraded41, SampleTime::CYCLES12_5),
43 ]
44 .into_iter(),
41 &mut measurements, 45 &mut measurements,
42 ) 46 )
43 .await 47 .await;
44 .unwrap();
45 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 48 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
46 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; 49 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32;
47 info!("Async read 4 pin 1 {}", volt1); 50 info!("Async read 4 pin 1 {}", volt1);
diff --git a/examples/stm32wba/src/bin/button_exti.rs b/examples/stm32wba/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32wba/src/bin/button_exti.rs
+++ b/examples/stm32wba/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wba/src/bin/mac_ffd.rs b/examples/stm32wba/src/bin/mac_ffd.rs
new file mode 100644
index 000000000..b15fb3452
--- /dev/null
+++ b/examples/stm32wba/src/bin/mac_ffd.rs
@@ -0,0 +1,58 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::rcc::{Sysclk, mux};
8use embassy_stm32_wpan::bindings::mac::ST_MAC_callbacks_t;
9use {defmt_rtt as _, panic_probe as _};
10
11static _MAC_CALLBACKS: ST_MAC_callbacks_t = ST_MAC_callbacks_t {
12 mlmeAssociateCnfCb: None, // ST_MAC_MLMEAssociateCnfCbPtr,
13 mlmeAssociateIndCb: None, // ST_MAC_MLMEAssociateIndCbPtr,
14 mlmeBeaconNotifyIndCb: None, // ST_MAC_MLMEBeaconNotifyIndCbPtr,
15 mlmeCalibrateCnfCb: None, // ST_MAC_MLMECalibrateCnfCbPtr,
16 mlmeCommStatusIndCb: None, // ST_MAC_MLMECommStatusIndCbPtr,
17 mlmeDisassociateCnfCb: None, // ST_MAC_MLMEDisassociateCnfCbPtr,
18 mlmeDisassociateIndCb: None, // ST_MAC_MLMEDisassociateIndCbPtr,
19 mlmeDpsCnfCb: None, // ST_MAC_MLMEDpsCnfCbPtr,
20 mlmeDpsIndCb: None, // ST_MAC_MLMEDpsIndCbPtr,
21 mlmeGetCnfCb: None, // ST_MAC_MLMEGetCnfCbPtr,
22 mlmeGtsCnfCb: None, // ST_MAC_MLMEGtsCnfCbPtr,
23 mlmeGtsIndCb: None, // ST_MAC_MLMEGtsIndCbPtr,
24 mlmeOrphanIndCb: None, // ST_MAC_MLMEOrphanIndCbPtr,
25 mlmePollCnfCb: None, // ST_MAC_MLMEPollCnfCbPtr,
26 mlmeResetCnfCb: None, // ST_MAC_MLMEResetCnfCbPtr,
27 mlmeRxEnableCnfCb: None, // ST_MAC_MLMERxEnableCnfCbPtr,
28 mlmeScanCnfCb: None, // ST_MAC_MLMEScanCnfCbPtr,
29 mlmeSetCnfCb: None, // ST_MAC_MLMESetCnfCbPtr,
30 mlmeSoundingCnfCb: None, // ST_MAC_MLMESoundingCnfCbPtr,
31 mlmeStartCnfCb: None, // ST_MAC_MLMEStartCnfCbPtr,
32 mlmeSyncLossIndCb: None, // ST_MAC_MLMESyncLossIndCbPtr,
33 mcpsDataIndCb: None, // ST_MAC_MCPSDataIndCbPtr,
34 mcpsDataCnfCb: None, // ST_MAC_MCPSDataCnfCbPtr,
35 mcpsPurgeCnfCb: None, // ST_MAC_MCPSPurgeCnfCbPtr,
36 mlmePollIndCb: None, // ST_MAC_MLMEPollIndCbPtr,
37 mlmeBeaconReqIndCb: None, // ST_MAC_MLMEBeaconReqIndCbPtr,
38 mlmeBeaconCnfCb: None, // ST_MAC_MLMEBeaconCnfCbPtr,
39 mlmeGetPwrInfoTableCnfCb: None, // ST_MAC_MLMEGetPwrInfoTableCnfCbPtr,
40 mlmeSetPwrInfoTableCnfCb: None, // ST_MAC_MLMESetPwrInfoTableCnfCbPtr,
41};
42
43#[embassy_executor::main]
44async fn main(_spawner: Spawner) {
45 let mut config = Config::default();
46
47 config.rcc.sys = Sysclk::HSI;
48 config.rcc.mux.rngsel = mux::Rngsel::HSI;
49
50 let _p = embassy_stm32::init(config);
51 info!("Hello World!");
52
53 // let status = unsafe { ST_MAC_init(&_MAC_CALLBACKS as *const _ as *mut _) };
54 //
55 // info!("mac init: {}", status);
56
57 cortex_m::asm::bkpt();
58}
diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs
index de690fda0..f20c77a7c 100644
--- a/examples/stm32wba/src/bin/pwm.rs
+++ b/examples/stm32wba/src/bin/pwm.rs
@@ -4,13 +4,13 @@
4use defmt::*; 4use defmt::*;
5use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config;
7use embassy_stm32::gpio::OutputType; 8use embassy_stm32::gpio::OutputType;
8use embassy_stm32::rcc::{ 9use embassy_stm32::rcc::{
9 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, 10 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
10}; 11};
11use embassy_stm32::time::khz; 12use embassy_stm32::time::khz;
12use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 13use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
13use embassy_stm32::Config;
14use embassy_time::Timer; 14use embassy_time::Timer;
15use panic_probe as _; 15use panic_probe as _;
16 16
diff --git a/examples/stm32wba/src/bin/rtc.rs b/examples/stm32wba/src/bin/rtc.rs
new file mode 100644
index 000000000..cef8501e0
--- /dev/null
+++ b/examples/stm32wba/src/bin/rtc.rs
@@ -0,0 +1,62 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::rcc::*;
8use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12pub fn pll_init(config: &mut Config) {
13 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
14 source: PllSource::HSI,
15 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
16 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
17 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
18 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
19 divq: None,
20 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
21 frac: Some(0), // Fractional part (enabled)
22 });
23
24 config.rcc.ahb_pre = AHBPrescaler::DIV1;
25 config.rcc.apb1_pre = APBPrescaler::DIV1;
26 config.rcc.apb2_pre = APBPrescaler::DIV1;
27 config.rcc.apb7_pre = APBPrescaler::DIV1;
28 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
29
30 // voltage scale for max performance
31 config.rcc.voltage_scale = VoltageScale::RANGE1;
32 // route PLL1_P into the USB‐OTG‐HS block
33 config.rcc.sys = Sysclk::PLL1_R;
34}
35
36#[embassy_executor::main]
37async fn main(_spawner: Spawner) {
38 let mut config = Config::default();
39
40 pll_init(&mut config);
41
42 let p = embassy_stm32::init(config);
43
44 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
45
46 // Setting datetime
47 let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap();
48 match rtc.0.set_datetime(initial_datetime) {
49 Ok(()) => info!("RTC set successfully."),
50 Err(e) => error!("Failed to set RTC date/time: {:?}", e),
51 }
52
53 // Reading datetime every 1s
54 loop {
55 match rtc.1.now() {
56 Ok(result) => info!("{}", result),
57 Err(e) => error!("Failed to set RTC date/time: {:?}", e),
58 }
59
60 Timer::after_millis(1000).await;
61 }
62}
diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml
index f98317846..04bb27cb0 100644
--- a/examples/stm32wba6/Cargo.toml
+++ b/examples/stm32wba6/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32wba6-examples" 3name = "embassy-stm32wba6-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs
index a9651d57e..51dcff57a 100644
--- a/examples/stm32wba6/src/bin/adc.rs
+++ b/examples/stm32wba6/src/bin/adc.rs
@@ -2,30 +2,55 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{adc4, AdcChannel}; 5use embassy_stm32::Config;
6use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
7use embassy_stm32::rcc::{
8 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
9};
6use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
7 11
8#[embassy_executor::main] 12#[embassy_executor::main]
9async fn main(_spawner: embassy_executor::Spawner) { 13async fn main(_spawner: embassy_executor::Spawner) {
10 let config = embassy_stm32::Config::default(); 14 let mut config = Config::default();
15 // Fine-tune PLL1 dividers/multipliers
16 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
17 source: PllSource::HSI,
18 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
19 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
20 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
21 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
22 divq: None,
23 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
24 frac: Some(0), // Fractional part (enabled)
25 });
26
27 config.rcc.ahb_pre = AHBPrescaler::DIV1;
28 config.rcc.apb1_pre = APBPrescaler::DIV1;
29 config.rcc.apb2_pre = APBPrescaler::DIV1;
30 config.rcc.apb7_pre = APBPrescaler::DIV1;
31 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
32
33 // voltage scale for max performance
34 config.rcc.voltage_scale = VoltageScale::RANGE1;
35 // route PLL1_P into the USB‐OTG‐HS block
36 config.rcc.sys = Sysclk::PLL1_R;
11 37
12 let mut p = embassy_stm32::init(config); 38 let mut p = embassy_stm32::init(config);
13 39
14 // **** ADC4 init **** 40 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4); 41 let mut adc4 = Adc::new_adc4(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4 42 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5 43 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12); 44 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256); 45 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
20 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5);
21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 46 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
22 47
23 // **** ADC4 blocking read **** 48 // **** ADC4 blocking read ****
24 let raw: u16 = adc4.blocking_read(&mut adc4_pin1); 49 let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5);
25 let volt: f32 = 3.0 * raw as f32 / max4 as f32; 50 let volt: f32 = 3.0 * raw as f32 / max4 as f32;
26 info!("Read adc4 pin 1 {}", volt); 51 info!("Read adc4 pin 1 {}", volt);
27 52
28 let raw: u16 = adc4.blocking_read(&mut adc4_pin2); 53 let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5);
29 let volt: f32 = 3.3 * raw as f32 / max4 as f32; 54 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
30 info!("Read adc4 pin 2 {}", volt); 55 info!("Read adc4 pin 2 {}", volt);
31 56
@@ -37,11 +62,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
37 // The channels must be in ascending order and can't repeat for ADC4 62 // The channels must be in ascending order and can't repeat for ADC4
38 adc4.read( 63 adc4.read(
39 p.GPDMA1_CH1.reborrow(), 64 p.GPDMA1_CH1.reborrow(),
40 [&mut degraded42, &mut degraded41].into_iter(), 65 [
66 (&mut degraded42, SampleTime::CYCLES12_5),
67 (&mut degraded41, SampleTime::CYCLES12_5),
68 ]
69 .into_iter(),
41 &mut measurements, 70 &mut measurements,
42 ) 71 )
43 .await 72 .await;
44 .unwrap();
45 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 73 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
46 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; 74 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32;
47 info!("Async read 4 pin 1 {}", volt1); 75 info!("Async read 4 pin 1 {}", volt1);
diff --git a/examples/stm32wba6/src/bin/blinky.rs b/examples/stm32wba6/src/bin/blinky.rs
index 0d803b257..95f3339b7 100644
--- a/examples/stm32wba6/src/bin/blinky.rs
+++ b/examples/stm32wba6/src/bin/blinky.rs
@@ -3,16 +3,45 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config;
6use embassy_stm32::gpio::{Level, Output, Speed}; 7use embassy_stm32::gpio::{Level, Output, Speed};
8use embassy_stm32::rcc::{
9 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
10};
7use embassy_time::Timer; 11use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
9 13
10#[embassy_executor::main] 14#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 16 let mut config = Config::default();
17 // Fine-tune PLL1 dividers/multipliers
18 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
19 source: PllSource::HSI,
20 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
21 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
22 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
23 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
24 divq: None,
25 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
26 frac: Some(0), // Fractional part (enabled)
27 });
28
29 config.rcc.ahb_pre = AHBPrescaler::DIV1;
30 config.rcc.apb1_pre = APBPrescaler::DIV1;
31 config.rcc.apb2_pre = APBPrescaler::DIV1;
32 config.rcc.apb7_pre = APBPrescaler::DIV1;
33 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
34
35 // voltage scale for max performance
36 config.rcc.voltage_scale = VoltageScale::RANGE1;
37 // route PLL1_P into the USB‐OTG‐HS block
38 config.rcc.sys = Sysclk::PLL1_R;
39
40 let p = embassy_stm32::init(config);
13 info!("Hello World!"); 41 info!("Hello World!");
14 42
15 let mut led = Output::new(p.PB4, Level::High, Speed::Low); 43 // LD2 - PC4
44 let mut led = Output::new(p.PC4, Level::High, Speed::Low);
16 45
17 loop { 46 loop {
18 info!("high"); 47 info!("high");
diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32wba6/src/bin/button_exti.rs
+++ b/examples/stm32wba6/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wba6/src/bin/pwm.rs b/examples/stm32wba6/src/bin/pwm.rs
index 2c696834a..64ae01945 100644
--- a/examples/stm32wba6/src/bin/pwm.rs
+++ b/examples/stm32wba6/src/bin/pwm.rs
@@ -4,13 +4,13 @@
4use defmt::*; 4use defmt::*;
5use defmt_rtt as _; // global logger 5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::Config;
7use embassy_stm32::gpio::OutputType; 8use embassy_stm32::gpio::OutputType;
8use embassy_stm32::rcc::{ 9use embassy_stm32::rcc::{
9 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, 10 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
10}; 11};
11use embassy_stm32::time::khz; 12use embassy_stm32::time::khz;
12use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; 13use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
13use embassy_stm32::Config;
14use embassy_time::Timer; 14use embassy_time::Timer;
15use panic_probe as _; 15use panic_probe as _;
16 16
diff --git a/examples/stm32wba6/src/bin/rtc.rs b/examples/stm32wba6/src/bin/rtc.rs
new file mode 100644
index 000000000..cef8501e0
--- /dev/null
+++ b/examples/stm32wba6/src/bin/rtc.rs
@@ -0,0 +1,62 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::Config;
7use embassy_stm32::rcc::*;
8use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12pub fn pll_init(config: &mut Config) {
13 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
14 source: PllSource::HSI,
15 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
16 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
17 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
18 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
19 divq: None,
20 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
21 frac: Some(0), // Fractional part (enabled)
22 });
23
24 config.rcc.ahb_pre = AHBPrescaler::DIV1;
25 config.rcc.apb1_pre = APBPrescaler::DIV1;
26 config.rcc.apb2_pre = APBPrescaler::DIV1;
27 config.rcc.apb7_pre = APBPrescaler::DIV1;
28 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
29
30 // voltage scale for max performance
31 config.rcc.voltage_scale = VoltageScale::RANGE1;
32 // route PLL1_P into the USB‐OTG‐HS block
33 config.rcc.sys = Sysclk::PLL1_R;
34}
35
36#[embassy_executor::main]
37async fn main(_spawner: Spawner) {
38 let mut config = Config::default();
39
40 pll_init(&mut config);
41
42 let p = embassy_stm32::init(config);
43
44 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
45
46 // Setting datetime
47 let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap();
48 match rtc.0.set_datetime(initial_datetime) {
49 Ok(()) => info!("RTC set successfully."),
50 Err(e) => error!("Failed to set RTC date/time: {:?}", e),
51 }
52
53 // Reading datetime every 1s
54 loop {
55 match rtc.1.now() {
56 Ok(result) => info!("{}", result),
57 Err(e) => error!("Failed to set RTC date/time: {:?}", e),
58 }
59
60 Timer::after_millis(1000).await;
61 }
62}
diff --git a/examples/stm32wba6/src/bin/usb_hs_serial.rs b/examples/stm32wba6/src/bin/usb_hs_serial.rs
index 20bdeaac3..a60eeb480 100644
--- a/examples/stm32wba6/src/bin/usb_hs_serial.rs
+++ b/examples/stm32wba6/src/bin/usb_hs_serial.rs
@@ -5,10 +5,10 @@ use defmt::{panic, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_stm32::usb::{Driver, Instance}; 7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, usb};
9use embassy_usb::Builder;
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError; 11use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index 825d25c0d..1754aa0b8 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-stm32wl-examples" 3name = "embassy-stm32wl-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs
index 118f02ae1..adabe0df8 100644
--- a/examples/stm32wl/src/bin/adc.rs
+++ b/examples/stm32wl/src/bin/adc.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime};
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
@@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) {
18 info!("Hello World!"); 18 info!("Hello World!");
19 19
20 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); 20 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 });
21 adc.set_sample_time(SampleTime::CYCLES79_5); 21
22 let mut pin = p.PB2; 22 let mut pin = p.PB2;
23 23
24 let mut vrefint = adc.enable_vrefint(); 24 let mut vrefint = adc.enable_vrefint();
25 let vrefint_sample = adc.blocking_read(&mut vrefint); 25 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5);
26 let convert_to_millivolts = |sample| { 26 let convert_to_millivolts = |sample| {
27 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf 27 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
28 // 6.3.3 Embedded internal reference voltage 28 // 6.3.3 Embedded internal reference voltage
@@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) {
32 }; 32 };
33 33
34 loop { 34 loop {
35 let v = adc.blocking_read(&mut pin); 35 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5);
36 info!("--> {} - {} mV", v, convert_to_millivolts(v)); 36 info!("--> {} - {} mV", v, convert_to_millivolts(v));
37 Timer::after_millis(100).await; 37 Timer::after_millis(100).await;
38 } 38 }
diff --git a/examples/stm32wl/src/bin/blinky.rs b/examples/stm32wl/src/bin/blinky.rs
index a2a90871d..f7f57e35c 100644
--- a/examples/stm32wl/src/bin/blinky.rs
+++ b/examples/stm32wl/src/bin/blinky.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_time::Timer; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
diff --git a/examples/stm32wl/src/bin/button.rs b/examples/stm32wl/src/bin/button.rs
index 21bcd2ac6..07bc95ad7 100644
--- a/examples/stm32wl/src/bin/button.rs
+++ b/examples/stm32wl/src/bin/button.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use cortex_m_rt::entry; 6use cortex_m_rt::entry;
7use defmt::*; 7use defmt::*;
8use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[unsafe(link_section = ".shared_data")] 12#[unsafe(link_section = ".shared_data")]
diff --git a/examples/stm32wl/src/bin/button_exti.rs b/examples/stm32wl/src/bin/button_exti.rs
index 0a8aece34..2bb39c709 100644
--- a/examples/stm32wl/src/bin/button_exti.rs
+++ b/examples/stm32wl/src/bin/button_exti.rs
@@ -5,11 +5,16 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput; 8use embassy_stm32::exti::{self, ExtiInput};
9use embassy_stm32::gpio::Pull; 9use embassy_stm32::gpio::Pull;
10use embassy_stm32::SharedData; 10use embassy_stm32::{SharedData, bind_interrupts, interrupt};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(
14 pub struct Irqs{
15 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
16});
17
13#[unsafe(link_section = ".shared_data")] 18#[unsafe(link_section = ".shared_data")]
14static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 19static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
15 20
@@ -18,7 +23,7 @@ async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); 23 let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA);
19 info!("Hello World!"); 24 info!("Hello World!");
20 25
21 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 26 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
22 27
23 info!("Press the USER button..."); 28 info!("Press the USER button...");
24 29
diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs
index 320a9723a..bc707820d 100644
--- a/examples/stm32wl/src/bin/flash.rs
+++ b/examples/stm32wl/src/bin/flash.rs
@@ -5,8 +5,8 @@ use core::mem::MaybeUninit;
5 5
6use defmt::{info, unwrap}; 6use defmt::{info, unwrap};
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::flash::Flash;
9use embassy_stm32::SharedData; 8use embassy_stm32::SharedData;
9use embassy_stm32::flash::Flash;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12#[unsafe(link_section = ".shared_data")] 12#[unsafe(link_section = ".shared_data")]
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 68b9d7d00..931f9819a 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -7,7 +7,7 @@ use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rng::{self, Rng}; 8use embassy_stm32::rng::{self, Rng};
9use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, peripherals, SharedData}; 10use embassy_stm32::{SharedData, bind_interrupts, peripherals};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs{ 13bind_interrupts!(struct Irqs{
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index d3709120f..2185142c9 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
44 .and_hms_opt(10, 30, 15) 44 .and_hms_opt(10, 30, 15)
45 .unwrap(); 45 .unwrap();
46 46
47 let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); 47 let (mut rtc, time_provider) = Rtc::new(p.RTC, RtcConfig::default());
48 info!("Got RTC! {:?}", now.and_utc().timestamp()); 48 info!("Got RTC! {:?}", now.and_utc().timestamp());
49 49
50 rtc.set_datetime(now.into()).expect("datetime not set"); 50 rtc.set_datetime(now.into()).expect("datetime not set");
@@ -52,6 +52,6 @@ async fn main(_spawner: Spawner) {
52 // In reality the delay would be much longer 52 // In reality the delay would be much longer
53 Timer::after_millis(20000).await; 53 Timer::after_millis(20000).await;
54 54
55 let then: NaiveDateTime = rtc.now().unwrap().into(); 55 let then: NaiveDateTime = time_provider.now().unwrap().into();
56 info!("Got RTC! {:?}", then.and_utc().timestamp()); 56 info!("Got RTC! {:?}", then.and_utc().timestamp());
57} 57}
diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs
index 505a85f47..829ea2de7 100644
--- a/examples/stm32wl/src/bin/uart_async.rs
+++ b/examples/stm32wl/src/bin/uart_async.rs
@@ -6,7 +6,7 @@ use core::mem::MaybeUninit;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::usart::{Config, InterruptHandler, Uart}; 8use embassy_stm32::usart::{Config, InterruptHandler, Uart};
9use embassy_stm32::{bind_interrupts, peripherals, SharedData}; 9use embassy_stm32::{SharedData, bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs{ 12bind_interrupts!(struct Irqs{
diff --git a/examples/stm32wle5/.cargo/config.toml b/examples/stm32wle5/.cargo/config.toml
new file mode 100644
index 000000000..0178d377c
--- /dev/null
+++ b/examples/stm32wle5/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip STM32WLE5JCIx --connect-under-reset"
4
5[build]
6target = "thumbv7em-none-eabi"
7
8[env]
9DEFMT_LOG = "info"
diff --git a/examples/stm32wle5/Cargo.toml b/examples/stm32wle5/Cargo.toml
new file mode 100644
index 000000000..f2fc4dd3d
--- /dev/null
+++ b/examples/stm32wle5/Cargo.toml
@@ -0,0 +1,38 @@
1[package]
2edition = "2024"
3name = "embassy-stm32wl-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# Change stm32wl55jc-cm4 to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wle5jc", "time-driver-any", "memory-x", "unstable-pac", "exti", "low-power"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-1_000"] }
14embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
15
16defmt = "1.0.1"
17defmt-rtt = { version = "1.1.0", optional = true }
18defmt-serial = { version = "0.10.0", optional = true }
19
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0"
22embedded-hal = "1.0.0"
23embedded-storage = "0.3.1"
24panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25static_cell = { version = "2.1.1", default-features = false }
26
27[profile.release]
28debug = 2
29
30[package.metadata.embassy]
31build = [
32 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" }
33]
34
35[features]
36default = ["defmt-serial"]
37defmt-rtt = ["dep:defmt-rtt"]
38defmt-serial = ["dep:defmt-serial"]
diff --git a/examples/stm32wle5/README.md b/examples/stm32wle5/README.md
new file mode 100644
index 000000000..18c3b5071
--- /dev/null
+++ b/examples/stm32wle5/README.md
@@ -0,0 +1,52 @@
1# Low Power Examples for STM32WLEx family
2
3Examples in this repo should work with [LoRa-E5 Dev Board](https://www.st.com/en/partner-products-and-services/lora-e5-development-kit.html) board.
4
5## Prerequsits
6
7- Connect a usb serial adapter to LPUart1 (this is where ALL logging will go)
8- Optional: Connect an amp meter that ran measure down to 0.1uA to the power test pins
9- `cargo install defmt-print` so you can print log messahes from LPUart1
10
11## Example Notes
12
13All examples will set all pins to analog mode before configuring pins for the example, if any. This saves about 500uA!!!!
14
15- the `adc` example will sleep in STOP1 betwen samples and the chip will only draw about 13uA while sleeping
16- the `blinky` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
17- the `button_exti` example will sleep in STOP2 and the chip will only draw 1uA or less while sleeping
18- the `i2c` examples will sleep in STOP1 between reads and the chip only draw about 10uA while sleeping
19
20For each example you will need to start `defmt-print` with the example binary and the correct serial port in a seperate terminal. Example:
21```
22defmt-print -w -v -e target/thumbv7em-none-eabi/debug/<module-name> serial --path /dev/cu.usbserial-00000000 --baud 115200
23```
24
25Run individual examples with
26```
27cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin <module-name>
28```
29for example
30```
31cargo flash --chip STM32WLE5JCIx --connect-under-reset --bin blinky
32```
33
34You can also run them with with `run`. However in this case expect probe-rs to be disconnected as soon as flashing is done as all IO pins are set to analog input!
35```
36cargo run --bin blinky
37```
38
39## Checklist before running examples
40You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
41
42* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L432KCU6 it should be `probe-rs run --chip STM32L432KCUx`. (use `probe-rs chip list` to find your chip)
43* [ ] Update Cargo.toml to have the correct `embassy-stm32` feature. For example for L432KCU6 it should be `stm32l432kc`. Look in the `Cargo.toml` file of the `embassy-stm32` project to find the correct feature flag for your chip.
44* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
45* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
46
47If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
48
49* Which example you are trying to run
50* Which chip and board you are using
51
52Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
diff --git a/examples/stm32wle5/build.rs b/examples/stm32wle5/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32wle5/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs
new file mode 100644
index 000000000..8cc84ccdf
--- /dev/null
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -0,0 +1,67 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, SampleTime};
9use embassy_stm32::low_power;
10use embassy_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[embassy_executor::main(executor = "low_power::Executor")]
15async fn async_main(_spawner: Spawner) {
16 let mut config = embassy_stm32::Config::default();
17 // enable HSI clock
18 config.rcc.hsi = true;
19 // enable LSI clock for RTC
20 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
21 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
22 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
23 // enable ADC with HSI clock
24 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
25 #[cfg(feature = "defmt-serial")]
26 {
27 // disable debug during sleep to reduce power consumption since we are
28 // using defmt-serial on LPUART1.
29 config.enable_debug_during_sleep = false;
30 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
31 // so that its registers are preserved during STOP modes.
32 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
33 }
34 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
35 let p = embassy_stm32::init(config);
36
37 #[cfg(feature = "defmt-serial")]
38 {
39 use embassy_stm32::mode::Blocking;
40 use embassy_stm32::usart::Uart;
41 let config = embassy_stm32::usart::Config::default();
42 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
43 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
44 defmt_serial::defmt_serial(SERIAL.init(uart));
45 }
46
47 info!("Hello World!");
48
49 let mut adc = Adc::new(p.ADC1);
50 let mut pin = p.PA10;
51
52 let mut vrefint = adc.enable_vrefint();
53 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5);
54 let convert_to_millivolts = |sample| {
55 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
56 // 6.3.3 Embedded internal reference voltage
57 const VREFINT_MV: u32 = 1212; // mV
58
59 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
60 };
61
62 loop {
63 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5);
64 info!("--> {} - {} mV", v, convert_to_millivolts(v));
65 Timer::after_secs(1).await;
66 }
67}
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
new file mode 100644
index 000000000..3b7eb7761
--- /dev/null
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -0,0 +1,58 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::gpio::{Level, Output, Speed};
9use embassy_stm32::low_power;
10use embassy_time::Timer;
11use panic_probe as _;
12use static_cell::StaticCell;
13
14#[embassy_executor::main(executor = "low_power::Executor")]
15async fn async_main(_spawner: Spawner) {
16 let mut config = embassy_stm32::Config::default();
17 // enable HSI clock
18 config.rcc.hsi = true;
19 // enable LSI clock for RTC
20 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
21 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
22 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
23 #[cfg(feature = "defmt-serial")]
24 {
25 // disable debug during sleep to reduce power consumption since we are
26 // using defmt-serial on LPUART1.
27 config.enable_debug_during_sleep = false;
28 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
29 // so that its registers are preserved during STOP modes.
30 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
31 }
32 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
33 let p = embassy_stm32::init(config);
34
35 #[cfg(feature = "defmt-serial")]
36 {
37 use embassy_stm32::mode::Blocking;
38 use embassy_stm32::usart::Uart;
39 let config = embassy_stm32::usart::Config::default();
40 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
41 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
42 defmt_serial::defmt_serial(SERIAL.init(uart));
43 }
44
45 info!("Hello World!");
46
47 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
48
49 loop {
50 info!("low");
51 led.set_low();
52 Timer::after_millis(15000).await;
53
54 info!("high");
55 led.set_high();
56 Timer::after_millis(15000).await;
57 }
58}
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
new file mode 100644
index 000000000..9ffc39948
--- /dev/null
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -0,0 +1,64 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::exti::{self, ExtiInput};
9use embassy_stm32::gpio::Pull;
10use embassy_stm32::{bind_interrupts, interrupt, low_power};
11use panic_probe as _;
12use static_cell::StaticCell;
13
14bind_interrupts!(
15 pub struct Irqs{
16 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
17});
18
19#[embassy_executor::main(executor = "low_power::Executor")]
20async fn async_main(_spawner: Spawner) {
21 let mut config = embassy_stm32::Config::default();
22 // enable HSI clock
23 config.rcc.hsi = true;
24 // enable LSI clock for RTC
25 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
26 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
27 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
28 // enable ADC with HSI clock
29 config.rcc.mux.adcsel = embassy_stm32::pac::rcc::vals::Adcsel::HSI;
30 #[cfg(feature = "defmt-serial")]
31 {
32 // disable debug during sleep to reduce power consumption since we are
33 // using defmt-serial on LPUART1.
34 config.enable_debug_during_sleep = false;
35 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
36 // so that its registers are preserved during STOP modes.
37 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
38 }
39 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
40 let p = embassy_stm32::init(config);
41
42 #[cfg(feature = "defmt-serial")]
43 {
44 use embassy_stm32::mode::Blocking;
45 use embassy_stm32::usart::Uart;
46 let config = embassy_stm32::usart::Config::default();
47 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
48 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
49 defmt_serial::defmt_serial(SERIAL.init(uart));
50 }
51
52 info!("Hello World!");
53
54 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
55
56 info!("Press the USER button...");
57
58 loop {
59 button.wait_for_falling_edge().await;
60 info!("Pressed!");
61 button.wait_for_rising_edge().await;
62 info!("Released!");
63 }
64}
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
new file mode 100644
index 000000000..8e7a6e2d8
--- /dev/null
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -0,0 +1,77 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::i2c::I2c;
9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, low_power, peripherals};
11use embassy_time::{Duration, Timer};
12use panic_probe as _;
13use static_cell::StaticCell;
14
15bind_interrupts!(struct IrqsI2C{
16 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18});
19
20#[embassy_executor::main(executor = "low_power::Executor")]
21async fn async_main(_spawner: Spawner) {
22 let mut config = embassy_stm32::Config::default();
23 // enable HSI clock
24 config.rcc.hsi = true;
25 // enable LSI clock for RTC
26 config.rcc.ls = embassy_stm32::rcc::LsConfig::default_lsi();
27 config.rcc.msi = Some(embassy_stm32::rcc::MSIRange::RANGE4M);
28 config.rcc.sys = embassy_stm32::rcc::Sysclk::MSI;
29 // enable ADC with HSI clock
30 config.rcc.mux.i2c2sel = embassy_stm32::pac::rcc::vals::I2c2sel::HSI;
31 #[cfg(feature = "defmt-serial")]
32 {
33 // disable debug during sleep to reduce power consumption since we are
34 // using defmt-serial on LPUART1.
35 config.enable_debug_during_sleep = false;
36 // if we are using defmt-serial on LPUART1, we need to use HSI for the clock
37 // so that its registers are preserved during STOP modes.
38 config.rcc.mux.lpuart1sel = embassy_stm32::pac::rcc::vals::Lpuart1sel::HSI;
39 }
40 // Initialize STM32WL peripherals (use default config like wio-e5-async example)
41 let p = embassy_stm32::init(config);
42
43 #[cfg(feature = "defmt-serial")]
44 {
45 use embassy_stm32::mode::Blocking;
46 use embassy_stm32::usart::Uart;
47 let config = embassy_stm32::usart::Config::default();
48 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
49 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
50 defmt_serial::defmt_serial(SERIAL.init(uart));
51 }
52
53 info!("Hello World!");
54 let en3v3 = embassy_stm32::gpio::Output::new(
55 p.PA9,
56 embassy_stm32::gpio::Level::High,
57 embassy_stm32::gpio::Speed::High,
58 );
59 core::mem::forget(en3v3); // keep the output pin enabled
60
61 let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, {
62 let mut config = i2c::Config::default();
63 config.frequency = Hertz::khz(100);
64 config.timeout = Duration::from_millis(1000);
65 config
66 });
67
68 loop {
69 let mut buffer = [0; 2];
70 // read the temperature register of the onboard lm75
71 match i2c.read(0x48, &mut buffer).await {
72 Ok(_) => info!("--> {:?}", buffer),
73 Err(e) => info!("--> Error: {:?}", e),
74 }
75 Timer::after_secs(5).await;
76 }
77}
diff --git a/examples/stm32wle5/stm32wle5.code-workspace b/examples/stm32wle5/stm32wle5.code-workspace
new file mode 100644
index 000000000..a7c4a0ebd
--- /dev/null
+++ b/examples/stm32wle5/stm32wle5.code-workspace
@@ -0,0 +1,13 @@
1{
2 "folders": [
3 {
4 "path": "."
5 }
6 ],
7 "settings": {
8 "rust-analyzer.cargo.target": "thumbv7em-none-eabi",
9 "rust-analyzer.cargo.allTargets": false,
10 "rust-analyzer.cargo.targetDir": "target/rust-analyzer",
11 "rust-analyzer.checkOnSave": true,
12 }
13}
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index e8897506c..79d50b584 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -1,5 +1,5 @@
1[package] 1[package]
2edition = "2021" 2edition = "2024"
3name = "embassy-wasm-example" 3name = "embassy-wasm-example"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"