aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-24 21:28:58 -0600
committerxoviat <[email protected]>2025-11-24 21:28:58 -0600
commitee14305d152273254571d2a5a8192fad26f3ab73 (patch)
tree80ee08b08ddb82fe712da50b0a0859d4ded6b9b9 /examples
parent461681028681930e50f41ee00154ac3e1886ebca (diff)
parent5ffb3698541674d57fddb22044ac0f06397c6113 (diff)
Merge branch 'main' of https://github.com/embassy-rs/embassy into xspi
Diffstat (limited to 'examples')
-rw-r--r--examples/boot/application/nrf/Cargo.toml2
-rw-r--r--examples/boot/application/rp/Cargo.toml2
-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.toml2
-rw-r--r--examples/boot/bootloader/nrf/src/main.rs6
-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/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.toml2
-rw-r--r--examples/mimxrt6/src/bin/button.rs2
-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/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.toml2
-rw-r--r--examples/nrf51/Cargo.toml2
-rw-r--r--examples/nrf52810/Cargo.toml2
-rw-r--r--examples/nrf52840-edf/Cargo.toml2
-rw-r--r--examples/nrf52840-edf/src/bin/basic.rs2
-rw-r--r--examples/nrf52840-rtic/Cargo.toml2
-rw-r--r--examples/nrf52840-rtic/src/bin/blinky.rs2
-rw-r--r--examples/nrf52840/Cargo.toml2
-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.toml2
-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.toml11
-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/rtc.rs56
-rw-r--r--examples/nrf54l15/src/bin/saadc.rs28
-rw-r--r--examples/nrf54l15/src/bin/spim.rs30
-rw-r--r--examples/nrf54l15/src/bin/twim.rs37
-rw-r--r--examples/nrf54l15/src/bin/twis.rs47
-rw-r--r--examples/nrf54l15/src/bin/uart.rs37
-rw-r--r--examples/nrf9151/ns/Cargo.toml2
-rw-r--r--examples/nrf9151/s/Cargo.toml2
-rw-r--r--examples/nrf9160/Cargo.toml2
-rw-r--r--examples/nrf9160/src/bin/modem_tcp_client.rs6
-rw-r--r--examples/rp/Cargo.toml2
-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.rs2
-rw-r--r--examples/rp/src/bin/wifi_webrequest.rs92
-rw-r--r--examples/rp/src/bin/zerocopy.rs2
-rw-r--r--examples/rp235x/Cargo.toml2
-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_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/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.toml2
-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/multiprio.rs4
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs2
-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.rs4
-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.rs2
-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/qspi.rs2
-rw-r--r--examples/stm32f7/src/bin/sdmmc.rs4
-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.toml15
-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.rs9
-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/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.rs2
-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/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/sdmmc.rs2
-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.rs6
-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/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/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.toml2
-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.toml78
-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/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.toml4
-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.toml2
-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/pwm.rs2
-rw-r--r--examples/stm32wba6/Cargo.toml2
-rw-r--r--examples/stm32wba6/src/bin/adc.rs50
-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/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.rs85
-rw-r--r--examples/stm32wle5/src/bin/blinky.rs76
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs82
-rw-r--r--examples/stm32wle5/src/bin/i2c.rs95
-rw-r--r--examples/stm32wle5/stm32wle5.code-workspace13
-rw-r--r--examples/wasm/Cargo.toml2
397 files changed, 4610 insertions, 1346 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index f5f89ecb5..55053bc33 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"
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml
index d86386b00..70a2c28c3 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"
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..1fea2b7d7 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"
diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs
index b849a0df3..76c4c1048 100644
--- a/examples/boot/bootloader/nrf/src/main.rs
+++ b/examples/boot/bootloader/nrf/src/main.rs
@@ -38,8 +38,8 @@ fn main() -> ! {
38 unsafe { bl.load(active_offset) } 38 unsafe { bl.load(active_offset) }
39} 39}
40 40
41#[no_mangle] 41#[unsafe(no_mangle)]
42#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] 42#[cfg_attr(target_os = "none", unsafe(link_section = ".HardFault.user"))]
43unsafe extern "C" fn HardFault() { 43unsafe extern "C" fn HardFault() {
44 cortex_m::peripheral::SCB::sys_reset(); 44 cortex_m::peripheral::SCB::sys_reset();
45} 45}
@@ -47,7 +47,7 @@ unsafe extern "C" fn HardFault() {
47#[exception] 47#[exception]
48unsafe fn DefaultHandler(_: i16) -> ! { 48unsafe fn DefaultHandler(_: i16) -> ! {
49 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; 49 const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
50 let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; 50 let irqn = unsafe { core::ptr::read_volatile(SCB_ICSR) } as u8 as i16 - 16;
51 51
52 panic!("DefaultHandler #{:?}", irqn); 52 panic!("DefaultHandler #{:?}", irqn);
53} 53}
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/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..dc09e97e7 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
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/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/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..5caabf228 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"
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml
index 082d85e5b..c7492f562 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"
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml
index 7835320e5..1711a3d8d 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"
diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml
index 67a624d6d..8b1db4652 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"
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..26b21598f 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"
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..a026d6352 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"
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..4dcbdd715 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"
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..4ef77279f 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"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.8.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
16
17rand = { version = "0.9.0", default-features = false }
12 18
13defmt = "1.0.1" 19defmt = "1.0.1"
14defmt-rtt = "1.0.0" 20defmt-rtt = "1.0.0"
@@ -18,6 +24,9 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
18cortex-m-rt = "0.7.0" 24cortex-m-rt = "0.7.0"
19 25
20embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
27portable-atomic = "1"
28
29static_cell = "2"
21 30
22[profile.release] 31[profile.release]
23debug = 2 32debug = 2
diff --git a/examples/nrf54l15/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/rtc.rs b/examples/nrf54l15/src/bin/rtc.rs
new file mode 100644
index 000000000..a45aaca52
--- /dev/null
+++ b/examples/nrf54l15/src/bin/rtc.rs
@@ -0,0 +1,56 @@
1#![no_std]
2#![no_main]
3
4use core::cell::RefCell;
5
6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_nrf::interrupt;
9use embassy_nrf::rtc::Rtc;
10use embassy_sync::blocking_mutex::Mutex;
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
12use portable_atomic::AtomicU64;
13use {defmt_rtt as _, panic_probe as _};
14
15// 64 bit counter which will never overflow.
16static TICK_COUNTER: AtomicU64 = AtomicU64::new(0);
17static RTC: Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc<'static>>>> = Mutex::new(RefCell::new(None));
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 defmt::println!("nRF54L15 RTC example");
22 let p = embassy_nrf::init(Default::default());
23 let mut led = Output::new(p.P2_09, Level::High, OutputDrive::Standard);
24 // Counter resolution is 125 ms.
25 let mut rtc = Rtc::new(p.RTC10, (1 << 12) - 1).unwrap();
26 rtc.enable_interrupt(embassy_nrf::rtc::Interrupt::Tick, true);
27 rtc.enable_event(embassy_nrf::rtc::Interrupt::Tick);
28 rtc.enable();
29 RTC.lock(|r| {
30 let mut rtc_borrow = r.borrow_mut();
31 *rtc_borrow = Some(rtc);
32 });
33
34 let mut last_counter_val = 0;
35 loop {
36 let current = TICK_COUNTER.load(core::sync::atomic::Ordering::Relaxed);
37 if current != last_counter_val {
38 led.toggle();
39 last_counter_val = current;
40 }
41 }
42}
43
44#[interrupt]
45fn RTC10() {
46 // For 64-bit, we do not need to worry about overflowing, at least not for realistic program
47 // lifetimes.
48 TICK_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
49 RTC.lock(|r| {
50 let mut rtc_borrow = r.borrow_mut();
51 rtc_borrow
52 .as_mut()
53 .unwrap()
54 .reset_event(embassy_nrf::rtc::Interrupt::Tick);
55 });
56}
diff --git a/examples/nrf54l15/src/bin/saadc.rs b/examples/nrf54l15/src/bin/saadc.rs
new file mode 100644
index 000000000..567177894
--- /dev/null
+++ b/examples/nrf54l15/src/bin/saadc.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::saadc::{ChannelConfig, Config, Saadc};
7use embassy_nrf::{bind_interrupts, saadc};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 SAADC => saadc::InterruptHandler;
13});
14
15#[embassy_executor::main]
16async fn main(_p: Spawner) {
17 let mut p = embassy_nrf::init(Default::default());
18 let config = Config::default();
19 let channel_config = ChannelConfig::single_ended(p.P1_04.reborrow());
20 let mut saadc = Saadc::new(p.SAADC, Irqs, config, [channel_config]);
21
22 loop {
23 let mut buf = [0; 1];
24 saadc.sample(&mut buf).await;
25 info!("sample: {=i16}", &buf[0]);
26 Timer::after_millis(100).await;
27 }
28}
diff --git a/examples/nrf54l15/src/bin/spim.rs b/examples/nrf54l15/src/bin/spim.rs
new file mode 100644
index 000000000..3f5980647
--- /dev/null
+++ b/examples/nrf54l15/src/bin/spim.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::{bind_interrupts, peripherals, spim};
6use {defmt_rtt as _, panic_probe as _};
7
8bind_interrupts!(struct Irqs {
9 SERIAL00 => spim::InterruptHandler<peripherals::SERIAL00>;
10});
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nrf::init(Default::default());
15 let mut config = spim::Config::default();
16 config.frequency = spim::Frequency::M32;
17 let mut spim = spim::Spim::new(p.SERIAL00, Irqs, p.P2_05, p.P2_09, p.P2_08, config.clone());
18 let data = [
19 0x42, 0x43, 0x44, 0x45, 0x66, 0x12, 0x23, 0x34, 0x45, 0x19, 0x91, 0xaa, 0xff, 0xa5, 0x5a, 0x77,
20 ];
21 let mut buf = [0u8; 16];
22
23 buf.fill(0);
24 spim.blocking_transfer(&mut buf, &data).unwrap();
25 assert_eq!(data, buf);
26
27 buf.fill(0);
28 spim.transfer(&mut buf, &data).await.unwrap();
29 assert_eq!(data, buf);
30}
diff --git a/examples/nrf54l15/src/bin/twim.rs b/examples/nrf54l15/src/bin/twim.rs
new file mode 100644
index 000000000..53b85034e
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twim.rs
@@ -0,0 +1,37 @@
1//! Example on how to read a 24C/24LC i2c eeprom.
2//!
3//! Connect SDA to P0.03, SCL to P0.04
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_nrf::twim::{self, Twim};
11use embassy_nrf::{bind_interrupts, peripherals};
12use static_cell::ConstStaticCell;
13use {defmt_rtt as _, panic_probe as _};
14
15const ADDRESS: u8 = 0x18;
16const WHOAMI: u8 = 0x0F;
17
18bind_interrupts!(struct Irqs {
19 SERIAL20 => twim::InterruptHandler<peripherals::SERIAL20>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_nrf::init(Default::default());
25 info!("Initializing TWI...");
26 let config = twim::Config::default();
27 static RAM_BUFFER: ConstStaticCell<[u8; 16]> = ConstStaticCell::new([0; 16]);
28 let mut twi = Twim::new(p.SERIAL20, Irqs, p.P1_13, p.P1_12, config, RAM_BUFFER.take());
29
30 info!("Reading...");
31
32 let mut data = [0u8; 1];
33 match twi.write_read(ADDRESS, &[WHOAMI], &mut data).await {
34 Ok(()) => info!("Whoami: {}", data[0]),
35 Err(e) => error!("I2c Error: {:?}", e),
36 }
37}
diff --git a/examples/nrf54l15/src/bin/twis.rs b/examples/nrf54l15/src/bin/twis.rs
new file mode 100644
index 000000000..34c04aee3
--- /dev/null
+++ b/examples/nrf54l15/src/bin/twis.rs
@@ -0,0 +1,47 @@
1//! TWIS example
2
3#![no_std]
4#![no_main]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_nrf::twis::{self, Command, Twis};
9use embassy_nrf::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 SERIAL20 => twis::InterruptHandler<peripherals::SERIAL20>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_nrf::init(Default::default());
19
20 let mut config = twis::Config::default();
21 config.address0 = 0x55; // Set i2c address
22 let mut i2c = Twis::new(p.SERIAL20, Irqs, p.P0_03, p.P0_04, config);
23
24 info!("Listening...");
25 loop {
26 let response = [1, 2, 3, 4, 5, 6, 7, 8];
27 // This buffer is used if the i2c master performs a Write or WriteRead
28 let mut buf = [0u8; 16];
29 match i2c.listen(&mut buf).await {
30 Ok(Command::Read) => {
31 info!("Got READ command. Respond with data:\n{:?}\n", response);
32 if let Err(e) = i2c.respond_to_read(&response).await {
33 error!("{:?}", e);
34 }
35 }
36 Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]),
37 Ok(Command::WriteRead(n)) => {
38 info!("Got WRITE/READ command with data:\n{:?}", buf[..n]);
39 info!("Respond with data:\n{:?}\n", response);
40 if let Err(e) = i2c.respond_to_read(&response).await {
41 error!("{:?}", e);
42 }
43 }
44 Err(e) => error!("{:?}", e),
45 }
46 }
47}
diff --git a/examples/nrf54l15/src/bin/uart.rs b/examples/nrf54l15/src/bin/uart.rs
new file mode 100644
index 000000000..cc6528a6f
--- /dev/null
+++ b/examples/nrf54l15/src/bin/uart.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::{bind_interrupts, peripherals, uarte};
7use {defmt_rtt as _, panic_probe as _};
8
9bind_interrupts!(struct Irqs {
10 SERIAL20 => uarte::InterruptHandler<peripherals::SERIAL20>;
11});
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_nrf::init(Default::default());
16 let mut config = uarte::Config::default();
17 config.parity = uarte::Parity::EXCLUDED;
18 config.baudrate = uarte::Baudrate::BAUD115200;
19
20 let mut uart = uarte::Uarte::new(p.SERIAL20, p.P1_12, p.P1_13, Irqs, config);
21
22 info!("uarte initialized!");
23
24 // Message must be in SRAM
25 let mut buf = [0; 8];
26 buf.copy_from_slice(b"Hello!\r\n");
27
28 unwrap!(uart.write(&buf).await);
29 info!("wrote hello in uart!");
30
31 loop {
32 info!("reading...");
33 unwrap!(uart.read(&mut buf).await);
34 info!("writing...");
35 unwrap!(uart.write(&buf).await);
36 }
37}
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml
index 89a6c7c94..7f1f5239a 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"
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml
index 870311c5d..ce71cc456 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"
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml
index 274e26dd6..ae3b2eeb1 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"
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..640addb28 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"
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..e39de4902 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;
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs
index 079def370..ce85f4b9a 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>;
@@ -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..39a4f421a 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"
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_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/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..d06b7505c 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"
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/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..50008a37b 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
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..fe0f887bf 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -4,8 +4,8 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; 6use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
7use embassy_stm32::time::{mhz, Hertz}; 7use embassy_stm32::time::{Hertz, mhz};
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11/// This is a safeguard to not overwrite any data on the SD card. 11/// This is a safeguard to not overwrite any data on the SD card.
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..ccfd0661e 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
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/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..8809b5d0c 100644
--- a/examples/stm32f7/src/bin/sdmmc.rs
+++ b/examples/stm32f7/src/bin/sdmmc.rs
@@ -4,8 +4,8 @@
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::time::{Hertz, mhz};
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
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/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..8bbeb594c 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,12 +7,12 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32g491re to your chip name, if necessary. 9# Change stm32g491re to your chip name, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 15embassy-futures = { path = "../../embassy-futures" }
16usbd-hid = "0.8.1" 16usbd-hid = "0.8.1"
17 17
18defmt = "1.0.1" 18defmt = "1.0.1"
@@ -25,6 +25,7 @@ embedded-can = { version = "0.4" }
25panic-probe = { version = "1.0.0", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27static_cell = "2.0.0" 27static_cell = "2.0.0"
28critical-section = "1.1"
28 29
29[profile.release] 30[profile.release]
30debug = 2 31debug = 2
diff --git a/examples/stm32g4/src/bin/adc.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..2138257f7 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]
@@ -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/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 039008d17..c593d5e0b 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -6,7 +6,7 @@ use 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, McoConfig, 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 _};
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/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/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index 96840d8ff..4977fec79 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::sdmmc::Sdmmc; 6use embassy_stm32::sdmmc::Sdmmc;
7use embassy_stm32::time::mhz; 7use embassy_stm32::time::mhz;
8use embassy_stm32::{bind_interrupts, peripherals, sdmmc, Config}; 8use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc};
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/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..5c29602c6 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,7 +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; 171 sai_config.master_clock_divider = None;
172 172
173 let (sub_block_tx, _) = hal::sai::split_subblocks(sai); 173 let (sub_block_tx, _) = hal::sai::split_subblocks(sai);
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/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/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..b6158c854 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"
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..5ed28eed1
--- /dev/null
+++ b/examples/stm32n6/Cargo.toml
@@ -0,0 +1,78 @@
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"
35
36
37# cargo build/run
38[profile.dev]
39codegen-units = 1
40debug = 2
41debug-assertions = true # <-
42incremental = false
43opt-level = 3 # <-
44overflow-checks = true # <-
45
46# cargo test
47[profile.test]
48codegen-units = 1
49debug = 2
50debug-assertions = true # <-
51incremental = false
52opt-level = 3 # <-
53overflow-checks = true # <-
54
55# cargo build/run --release
56[profile.release]
57codegen-units = 1
58debug = 2
59debug-assertions = false # <-
60incremental = false
61lto = 'fat'
62opt-level = 3 # <-
63overflow-checks = false # <-
64
65# cargo test --release
66[profile.bench]
67codegen-units = 1
68debug = 2
69debug-assertions = false # <-
70incremental = false
71lto = 'fat'
72opt-level = 3 # <-
73overflow-checks = false # <-
74
75[package.metadata.embassy]
76build = [
77 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32n6" }
78]
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/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..83119e3a0 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"] }
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..3496b41b0 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -1,5 +1,5 @@
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"
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/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/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/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/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..ea91fb063
--- /dev/null
+++ b/examples/stm32wle5/src/bin/adc.rs
@@ -0,0 +1,85 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _;
7use embassy_executor::Spawner;
8use embassy_stm32::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 // start with all GPIOs as analog to reduce power consumption
38 for r in [
39 embassy_stm32::pac::GPIOA,
40 embassy_stm32::pac::GPIOB,
41 embassy_stm32::pac::GPIOC,
42 embassy_stm32::pac::GPIOH,
43 ] {
44 r.moder().modify(|w| {
45 for i in 0..16 {
46 // don't reset these if probe-rs should stay connected!
47 #[cfg(feature = "defmt-rtt")]
48 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
49 continue;
50 }
51 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
52 }
53 });
54 }
55 #[cfg(feature = "defmt-serial")]
56 {
57 use embassy_stm32::mode::Blocking;
58 use embassy_stm32::usart::Uart;
59 let config = embassy_stm32::usart::Config::default();
60 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
61 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
62 defmt_serial::defmt_serial(SERIAL.init(uart));
63 }
64
65 info!("Hello World!");
66
67 let mut adc = Adc::new(p.ADC1);
68 let mut pin = p.PA10;
69
70 let mut vrefint = adc.enable_vrefint();
71 let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5);
72 let convert_to_millivolts = |sample| {
73 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
74 // 6.3.3 Embedded internal reference voltage
75 const VREFINT_MV: u32 = 1212; // mV
76
77 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
78 };
79
80 loop {
81 let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5);
82 info!("--> {} - {} mV", v, convert_to_millivolts(v));
83 Timer::after_secs(1).await;
84 }
85}
diff --git a/examples/stm32wle5/src/bin/blinky.rs b/examples/stm32wle5/src/bin/blinky.rs
new file mode 100644
index 000000000..9f0c04672
--- /dev/null
+++ b/examples/stm32wle5/src/bin/blinky.rs
@@ -0,0 +1,76 @@
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 // start with all GPIOs as analog to reduce power consumption
36 for r in [
37 embassy_stm32::pac::GPIOA,
38 embassy_stm32::pac::GPIOB,
39 embassy_stm32::pac::GPIOC,
40 embassy_stm32::pac::GPIOH,
41 ] {
42 r.moder().modify(|w| {
43 for i in 0..16 {
44 // don't reset these if probe-rs should stay connected!
45 #[cfg(feature = "defmt-rtt")]
46 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
47 continue;
48 }
49 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
50 }
51 });
52 }
53 #[cfg(feature = "defmt-serial")]
54 {
55 use embassy_stm32::mode::Blocking;
56 use embassy_stm32::usart::Uart;
57 let config = embassy_stm32::usart::Config::default();
58 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
59 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
60 defmt_serial::defmt_serial(SERIAL.init(uart));
61 }
62
63 info!("Hello World!");
64
65 let mut led = Output::new(p.PB5, Level::High, Speed::Low);
66
67 loop {
68 info!("low");
69 led.set_low();
70 Timer::after_millis(500).await;
71
72 info!("high");
73 led.set_high();
74 Timer::after_millis(500).await;
75 }
76}
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
new file mode 100644
index 000000000..f248b6147
--- /dev/null
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -0,0 +1,82 @@
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 // start with all GPIOs as analog to reduce power consumption
43 for r in [
44 embassy_stm32::pac::GPIOA,
45 embassy_stm32::pac::GPIOB,
46 embassy_stm32::pac::GPIOC,
47 embassy_stm32::pac::GPIOH,
48 ] {
49 r.moder().modify(|w| {
50 for i in 0..16 {
51 // don't reset these if probe-rs should stay connected!
52 #[cfg(feature = "defmt-rtt")]
53 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
54 continue;
55 }
56 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
57 }
58 });
59 }
60 #[cfg(feature = "defmt-serial")]
61 {
62 use embassy_stm32::mode::Blocking;
63 use embassy_stm32::usart::Uart;
64 let config = embassy_stm32::usart::Config::default();
65 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
66 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
67 defmt_serial::defmt_serial(SERIAL.init(uart));
68 }
69
70 info!("Hello World!");
71
72 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
73
74 info!("Press the USER button...");
75
76 loop {
77 button.wait_for_falling_edge().await;
78 info!("Pressed!");
79 button.wait_for_rising_edge().await;
80 info!("Released!");
81 }
82}
diff --git a/examples/stm32wle5/src/bin/i2c.rs b/examples/stm32wle5/src/bin/i2c.rs
new file mode 100644
index 000000000..68c17a672
--- /dev/null
+++ b/examples/stm32wle5/src/bin/i2c.rs
@@ -0,0 +1,95 @@
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 // start with all GPIOs as analog to reduce power consumption
44 for r in [
45 embassy_stm32::pac::GPIOA,
46 embassy_stm32::pac::GPIOB,
47 embassy_stm32::pac::GPIOC,
48 embassy_stm32::pac::GPIOH,
49 ] {
50 r.moder().modify(|w| {
51 for i in 0..16 {
52 // don't reset these if probe-rs should stay connected!
53 #[cfg(feature = "defmt-rtt")]
54 if config.enable_debug_during_sleep && r == embassy_stm32::pac::GPIOA && [13, 14].contains(&i) {
55 continue;
56 }
57 w.set_moder(i, embassy_stm32::pac::gpio::vals::Moder::ANALOG);
58 }
59 });
60 }
61 #[cfg(feature = "defmt-serial")]
62 {
63 use embassy_stm32::mode::Blocking;
64 use embassy_stm32::usart::Uart;
65 let config = embassy_stm32::usart::Config::default();
66 let uart = Uart::new_blocking(p.LPUART1, p.PC0, p.PC1, config).expect("failed to configure UART!");
67 static SERIAL: StaticCell<Uart<'static, Blocking>> = StaticCell::new();
68 defmt_serial::defmt_serial(SERIAL.init(uart));
69 }
70
71 info!("Hello World!");
72 let en3v3 = embassy_stm32::gpio::Output::new(
73 p.PA9,
74 embassy_stm32::gpio::Level::High,
75 embassy_stm32::gpio::Speed::High,
76 );
77 core::mem::forget(en3v3); // keep the output pin enabled
78
79 let mut i2c = I2c::new(p.I2C2, p.PB15, p.PA15, IrqsI2C, p.DMA1_CH6, p.DMA1_CH7, {
80 let mut config = i2c::Config::default();
81 config.frequency = Hertz::khz(100);
82 config.timeout = Duration::from_millis(500);
83 config
84 });
85
86 loop {
87 let mut buffer = [0; 2];
88 // read the temperature register of the onboard lm75
89 match i2c.read(0x48, &mut buffer).await {
90 Ok(_) => info!("--> {:?}", buffer),
91 Err(e) => info!("--> Error: {:?}", e),
92 }
93 Timer::after_secs(5).await;
94 }
95}
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"