aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/boot/application/nrf/Cargo.toml28
-rw-r--r--examples/boot/application/rp/Cargo.toml24
-rw-r--r--examples/boot/application/rp/src/bin/a.rs2
-rw-r--r--examples/boot/application/stm32f3/Cargo.toml22
-rw-r--r--examples/boot/application/stm32f7/Cargo.toml22
-rw-r--r--examples/boot/application/stm32h7/Cargo.toml22
-rw-r--r--examples/boot/application/stm32l0/Cargo.toml22
-rw-r--r--examples/boot/application/stm32l1/Cargo.toml22
-rw-r--r--examples/boot/application/stm32l4/Cargo.toml22
-rw-r--r--examples/boot/application/stm32wb-dfu/Cargo.toml26
-rw-r--r--examples/boot/application/stm32wb-dfu/memory.x8
-rw-r--r--examples/boot/application/stm32wb-dfu/secrets/key.sec2
-rw-r--r--examples/boot/application/stm32wb-dfu/src/main.rs30
-rw-r--r--examples/boot/application/stm32wba-dfu/.cargo/config.toml9
-rw-r--r--examples/boot/application/stm32wba-dfu/Cargo.toml38
-rw-r--r--examples/boot/application/stm32wba-dfu/README.md9
-rw-r--r--examples/boot/application/stm32wba-dfu/build.rs37
-rw-r--r--examples/boot/application/stm32wba-dfu/memory.x15
-rw-r--r--examples/boot/application/stm32wba-dfu/secrets/key.sec2
-rw-r--r--examples/boot/application/stm32wba-dfu/src/main.rs114
-rw-r--r--examples/boot/application/stm32wl/Cargo.toml22
-rw-r--r--examples/boot/bootloader/nrf/Cargo.toml16
-rw-r--r--examples/boot/bootloader/rp/Cargo.toml12
-rw-r--r--examples/boot/bootloader/stm32-dual-bank/Cargo.toml12
-rw-r--r--examples/boot/bootloader/stm32/Cargo.toml12
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/Cargo.toml20
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/README.md26
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/memory.x8
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short1
-rw-r--r--examples/boot/bootloader/stm32wb-dfu/src/main.rs29
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml8
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/Cargo.toml70
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/README.md63
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/build.rs27
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/memory.x18
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short1
-rw-r--r--examples/boot/bootloader/stm32wba-dfu/src/main.rs158
-rw-r--r--examples/lpc55s69/Cargo.toml22
-rw-r--r--examples/lpc55s69/README.md12
-rw-r--r--examples/lpc55s69/src/bin/blinky_embassy_time.rs26
-rw-r--r--examples/lpc55s69/src/bin/usart_blocking.rs40
-rw-r--r--examples/mimxrt1011/.cargo/config.toml8
-rw-r--r--examples/mimxrt1011/Cargo.toml35
-rw-r--r--examples/mimxrt1011/build.rs14
-rw-r--r--examples/mimxrt1011/src/bin/blinky.rs48
-rw-r--r--examples/mimxrt1011/src/bin/button.rs62
-rw-r--r--examples/mimxrt1011/src/lib.rs75
-rw-r--r--examples/mimxrt1062-evk/.cargo/config.toml8
-rw-r--r--examples/mimxrt1062-evk/Cargo.toml35
-rw-r--r--examples/mimxrt1062-evk/build.rs12
-rw-r--r--examples/mimxrt1062-evk/src/bin/blinky.rs25
-rw-r--r--examples/mimxrt1062-evk/src/bin/button.rs36
-rw-r--r--examples/mimxrt1062-evk/src/lib.rs60
-rw-r--r--examples/mimxrt6/Cargo.toml21
-rw-r--r--examples/mimxrt6/src/bin/button.rs29
-rw-r--r--examples/mimxrt6/src/bin/crc.rs175
-rw-r--r--examples/mimxrt6/src/bin/rng.rs39
-rw-r--r--examples/mimxrt6/src/bin/uart-async.rs87
-rw-r--r--examples/mimxrt6/src/bin/uart.rs55
-rw-r--r--examples/mspm0c1104/Cargo.toml22
-rw-r--r--examples/mspm0c1104/README.md4
-rw-r--r--examples/mspm0c1104/build.rs2
-rw-r--r--examples/mspm0c1104/src/bin/wwdt.rs54
-rw-r--r--examples/mspm0g3507/.cargo/config.toml2
-rw-r--r--examples/mspm0g3507/Cargo.toml24
-rw-r--r--examples/mspm0g3507/README.md4
-rw-r--r--examples/mspm0g3507/build.rs2
-rw-r--r--examples/mspm0g3507/src/bin/i2c.rs45
-rw-r--r--examples/mspm0g3507/src/bin/i2c_async.rs50
-rw-r--r--examples/mspm0g3507/src/bin/wwdt.rs54
-rw-r--r--examples/mspm0g3519/Cargo.toml22
-rw-r--r--examples/mspm0g3519/README.md4
-rw-r--r--examples/mspm0g3519/build.rs2
-rw-r--r--examples/mspm0g3519/src/bin/wwdt.rs54
-rw-r--r--examples/mspm0l1306/Cargo.toml26
-rw-r--r--examples/mspm0l1306/README.md4
-rw-r--r--examples/mspm0l1306/build.rs2
-rw-r--r--examples/mspm0l1306/src/bin/i2c.rs45
-rw-r--r--examples/mspm0l1306/src/bin/i2c_async.rs50
-rw-r--r--examples/mspm0l1306/src/bin/wwdt.rs54
-rw-r--r--examples/mspm0l2228/Cargo.toml22
-rw-r--r--examples/mspm0l2228/README.md4
-rw-r--r--examples/mspm0l2228/build.rs2
-rw-r--r--examples/mspm0l2228/src/bin/wwdt.rs54
-rw-r--r--examples/nrf-rtos-trace/Cargo.toml21
-rw-r--r--examples/nrf-rtos-trace/build.rs2
-rw-r--r--examples/nrf-rtos-trace/src/bin/rtos_trace.rs6
-rw-r--r--examples/nrf51/Cargo.toml18
-rw-r--r--examples/nrf52810/Cargo.toml22
-rw-r--r--examples/nrf52840-edf/.cargo/config.toml9
-rw-r--r--examples/nrf52840-edf/Cargo.toml27
-rw-r--r--examples/nrf52840-edf/build.rs35
-rw-r--r--examples/nrf52840-edf/memory.x12
-rw-r--r--examples/nrf52840-edf/src/bin/basic.rs194
-rw-r--r--examples/nrf52840-rtic/Cargo.toml22
-rw-r--r--examples/nrf52840-rtic/src/bin/blinky.rs1
-rw-r--r--examples/nrf52840/Cargo.toml32
-rw-r--r--examples/nrf52840/src/bin/channel.rs2
-rw-r--r--examples/nrf52840/src/bin/channel_sender_receiver.rs4
-rw-r--r--examples/nrf52840/src/bin/ethernet_enc28j60.rs2
-rw-r--r--examples/nrf52840/src/bin/executor_fairness_test.rs6
-rw-r--r--examples/nrf52840/src/bin/gpiote_port.rs8
-rw-r--r--examples/nrf52840/src/bin/ieee802154_receive.rs38
-rw-r--r--examples/nrf52840/src/bin/ieee802154_send.rs39
-rw-r--r--examples/nrf52840/src/bin/manually_create_executor.rs4
-rw-r--r--examples/nrf52840/src/bin/multiprio.rs6
-rw-r--r--examples/nrf52840/src/bin/mutex.rs2
-rw-r--r--examples/nrf52840/src/bin/nfct.rs274
-rw-r--r--examples/nrf52840/src/bin/pubsub.rs6
-rw-r--r--examples/nrf52840/src/bin/raw_spawn.rs4
-rwxr-xr-x[-rw-r--r--]examples/nrf52840/src/bin/rng.rs2
-rw-r--r--examples/nrf52840/src/bin/self_spawn.rs4
-rw-r--r--examples/nrf52840/src/bin/self_spawn_current_executor.rs5
-rw-r--r--examples/nrf52840/src/bin/sixlowpan.rs120
-rw-r--r--examples/nrf52840/src/bin/timer.rs4
-rw-r--r--examples/nrf52840/src/bin/uart_split.rs2
-rw-r--r--examples/nrf52840/src/bin/usb_ethernet.rs6
-rw-r--r--examples/nrf52840/src/bin/usb_serial_multitask.rs4
-rw-r--r--examples/nrf52840/src/bin/wifi_esp_hosted.rs4
-rw-r--r--examples/nrf5340/Cargo.toml27
-rw-r--r--examples/nrf54l15/Cargo.toml20
-rw-r--r--examples/nrf54l15/src/bin/nvmc.rs44
-rw-r--r--examples/nrf54l15/src/bin/temp.rs25
-rw-r--r--examples/nrf54l15/src/bin/wdt.rs42
-rw-r--r--examples/nrf9151/ns/Cargo.toml18
-rw-r--r--examples/nrf9151/s/Cargo.toml18
-rw-r--r--examples/nrf9160/Cargo.toml20
-rw-r--r--examples/nrf9160/src/bin/modem_tcp_client.rs10
-rw-r--r--examples/rp/Cargo.toml47
-rw-r--r--examples/rp/src/bin/adc.rs9
-rw-r--r--examples/rp/src/bin/assign_resources.rs6
-rw-r--r--examples/rp/src/bin/blinky_two_channels.rs4
-rw-r--r--examples/rp/src/bin/blinky_two_tasks.rs4
-rw-r--r--examples/rp/src/bin/ethernet_w5500_icmp.rs5
-rw-r--r--examples/rp/src/bin/ethernet_w5500_icmp_ping.rs5
-rw-r--r--examples/rp/src/bin/ethernet_w5500_multisocket.rs9
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs5
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_server.rs5
-rw-r--r--examples/rp/src/bin/ethernet_w5500_udp.rs5
-rw-r--r--examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs155
-rw-r--r--examples/rp/src/bin/i2c_blocking.rs4
-rw-r--r--examples/rp/src/bin/i2c_slave.rs4
-rw-r--r--examples/rp/src/bin/interrupt.rs2
-rw-r--r--examples/rp/src/bin/multicore.rs4
-rw-r--r--examples/rp/src/bin/multiprio.rs6
-rw-r--r--examples/rp/src/bin/orchestrate_tasks.rs15
-rw-r--r--examples/rp/src/bin/overclock.rs10
-rw-r--r--examples/rp/src/bin/overclock_manual.rs10
-rw-r--r--examples/rp/src/bin/pio_async.rs6
-rw-r--r--examples/rp/src/bin/pio_i2s.rs2
-rw-r--r--examples/rp/src/bin/pio_onewire.rs1
-rw-r--r--examples/rp/src/bin/pio_onewire_parasite.rs89
-rw-r--r--examples/rp/src/bin/pio_rotary_encoder.rs4
-rw-r--r--examples/rp/src/bin/pio_spi.rs48
-rw-r--r--examples/rp/src/bin/pio_spi_async.rs57
-rw-r--r--examples/rp/src/bin/pwm.rs4
-rw-r--r--examples/rp/src/bin/shared_bus.rs8
-rw-r--r--examples/rp/src/bin/sharing.rs7
-rw-r--r--examples/rp/src/bin/spi_gc9a01.rs1
-rw-r--r--examples/rp/src/bin/uart_buffered_split.rs2
-rw-r--r--examples/rp/src/bin/uart_unidir.rs2
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs7
-rwxr-xr-x[-rw-r--r--]examples/rp/src/bin/usb_hid_mouse.rs4
-rw-r--r--examples/rp/src/bin/usb_logger.rs2
-rw-r--r--examples/rp/src/bin/usb_raw_bulk.rs4
-rw-r--r--examples/rp/src/bin/usb_serial.rs2
-rw-r--r--examples/rp/src/bin/usb_serial_with_handler.rs2
-rw-r--r--examples/rp/src/bin/usb_webusb.rs4
-rw-r--r--examples/rp/src/bin/wifi_ap_tcp_server.rs5
-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.rs32
-rw-r--r--examples/rp/src/bin/wifi_webrequest.rs38
-rw-r--r--examples/rp/src/bin/zerocopy.rs4
-rw-r--r--examples/rp235x/Cargo.toml42
-rw-r--r--examples/rp235x/memory.x4
-rw-r--r--examples/rp235x/src/bin/assign_resources.rs6
-rw-r--r--examples/rp235x/src/bin/blinky_two_channels.rs4
-rw-r--r--examples/rp235x/src/bin/blinky_two_tasks.rs4
-rw-r--r--examples/rp235x/src/bin/blinky_wifi.rs8
-rw-r--r--examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs2
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_icmp.rs143
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs134
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_multisocket.rs139
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs127
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs136
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_udp.rs116
-rw-r--r--examples/rp235x/src/bin/i2c_slave.rs4
-rw-r--r--examples/rp235x/src/bin/interrupt.rs2
-rw-r--r--examples/rp235x/src/bin/multicore.rs4
-rw-r--r--examples/rp235x/src/bin/multiprio.rs6
-rw-r--r--examples/rp235x/src/bin/overclock.rs74
-rw-r--r--examples/rp235x/src/bin/pio_async.rs6
-rw-r--r--examples/rp235x/src/bin/pio_i2s.rs2
-rw-r--r--examples/rp235x/src/bin/pio_i2s_rx.rs81
-rw-r--r--examples/rp235x/src/bin/pio_onewire.rs103
-rw-r--r--examples/rp235x/src/bin/pio_onewire_parasite.rs89
-rw-r--r--examples/rp235x/src/bin/pio_rotary_encoder.rs4
-rw-r--r--examples/rp235x/src/bin/psram.rs49
-rw-r--r--examples/rp235x/src/bin/pwm.rs4
-rw-r--r--examples/rp235x/src/bin/shared_bus.rs8
-rw-r--r--examples/rp235x/src/bin/sharing.rs7
-rw-r--r--examples/rp235x/src/bin/trng.rs5
-rw-r--r--examples/rp235x/src/bin/uart_buffered_split.rs2
-rw-r--r--examples/rp235x/src/bin/uart_unidir.rs2
-rw-r--r--examples/rp235x/src/bin/usb_webusb.rs4
-rw-r--r--examples/rp235x/src/bin/zerocopy.rs4
-rw-r--r--examples/std/Cargo.toml18
-rw-r--r--examples/std/README.md119
-rw-r--r--examples/std/src/bin/net.rs8
-rw-r--r--examples/std/src/bin/net_dns.rs8
-rw-r--r--examples/std/src/bin/net_ppp.rs10
-rw-r--r--examples/std/src/bin/net_udp.rs8
-rw-r--r--examples/std/src/bin/serial.rs2
-rw-r--r--examples/std/src/bin/tcp_accept.rs8
-rw-r--r--examples/std/src/bin/tick.rs2
-rw-r--r--examples/std/tap.sh2
-rw-r--r--examples/stm32c0/Cargo.toml21
-rw-r--r--examples/stm32c0/src/bin/rtc.rs35
-rw-r--r--examples/stm32f0/Cargo.toml20
-rw-r--r--examples/stm32f0/src/bin/adc-watchdog.rs34
-rw-r--r--examples/stm32f0/src/bin/button_controlled_blink.rs2
-rw-r--r--examples/stm32f0/src/bin/multiprio.rs6
-rw-r--r--examples/stm32f1/Cargo.toml24
-rw-r--r--examples/stm32f1/src/bin/input_capture.rs9
-rw-r--r--examples/stm32f1/src/bin/pwm_input.rs6
-rw-r--r--examples/stm32f2/Cargo.toml20
-rw-r--r--examples/stm32f3/Cargo.toml24
-rw-r--r--examples/stm32f3/src/bin/button_events.rs4
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs6
-rw-r--r--examples/stm32f334/Cargo.toml24
-rw-r--r--examples/stm32f4/Cargo.toml28
-rw-r--r--examples/stm32f4/src/bin/adc_dma.rs2
-rw-r--r--examples/stm32f4/src/bin/eth.rs2
-rw-r--r--examples/stm32f4/src/bin/eth_w5500.rs4
-rw-r--r--examples/stm32f4/src/bin/flash_async.rs2
-rw-r--r--examples/stm32f4/src/bin/i2c.rs3
-rw-r--r--examples/stm32f4/src/bin/i2c_async.rs12
-rw-r--r--examples/stm32f4/src/bin/i2c_comparison.rs34
-rw-r--r--examples/stm32f4/src/bin/i2s_dma.rs1
-rw-r--r--examples/stm32f4/src/bin/input_capture.rs4
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs6
-rw-r--r--examples/stm32f4/src/bin/pwm.rs2
-rw-r--r--examples/stm32f4/src/bin/pwm_complementary.rs4
-rw-r--r--examples/stm32f4/src/bin/pwm_input.rs4
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs6
-rw-r--r--examples/stm32f4/src/bin/usb_uac_speaker.rs10
-rw-r--r--examples/stm32f4/src/bin/ws2812_pwm.rs2
-rw-r--r--examples/stm32f469/Cargo.toml18
-rw-r--r--examples/stm32f7/Cargo.toml25
-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.rs3
-rw-r--r--examples/stm32f7/src/bin/qspi.rs15
-rw-r--r--examples/stm32g0/Cargo.toml24
-rw-r--r--examples/stm32g0/src/bin/adc.rs4
-rw-r--r--examples/stm32g0/src/bin/adc_dma.rs4
-rw-r--r--examples/stm32g0/src/bin/adc_oversampling.rs4
-rw-r--r--examples/stm32g0/src/bin/hf_timer.rs4
-rw-r--r--examples/stm32g0/src/bin/i2c_async.rs12
-rw-r--r--examples/stm32g0/src/bin/input_capture.rs6
-rw-r--r--examples/stm32g0/src/bin/pwm_complementary.rs8
-rw-r--r--examples/stm32g0/src/bin/pwm_input.rs6
-rw-r--r--examples/stm32g4/Cargo.toml24
-rw-r--r--examples/stm32g4/src/bin/i2c_slave.rs149
-rw-r--r--examples/stm32g4/src/bin/pwm.rs2
-rw-r--r--examples/stm32h5/Cargo.toml27
-rw-r--r--examples/stm32h5/src/bin/adc_dma.rs94
-rw-r--r--examples/stm32h5/src/bin/eth.rs3
-rw-r--r--examples/stm32h5/src/bin/i2c.rs2
-rw-r--r--examples/stm32h5/src/bin/sai.rs52
-rw-r--r--examples/stm32h5/src/bin/stop.rs6
-rw-r--r--examples/stm32h5/src/bin/usart.rs2
-rw-r--r--examples/stm32h5/src/bin/usart_dma.rs2
-rw-r--r--examples/stm32h5/src/bin/usart_split.rs2
-rw-r--r--examples/stm32h5/src/bin/usb_uac_speaker.rs10
-rw-r--r--examples/stm32h7/Cargo.toml29
-rw-r--r--examples/stm32h7/src/bin/camera.rs12
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs4
-rw-r--r--examples/stm32h7/src/bin/eth.rs3
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs3
-rw-r--r--examples/stm32h7/src/bin/eth_client_mii.rs3
-rw-r--r--examples/stm32h7/src/bin/i2c.rs12
-rw-r--r--examples/stm32h7/src/bin/i2c_shared.rs22
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs10
-rw-r--r--examples/stm32h7/src/bin/multiprio.rs6
-rw-r--r--examples/stm32h7/src/bin/pwm.rs2
-rw-r--r--examples/stm32h7/src/bin/sai.rs72
-rw-r--r--examples/stm32h7/src/bin/signal.rs2
-rw-r--r--examples/stm32h7/src/bin/spi.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_bdma.rs2
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs2
-rw-r--r--examples/stm32h7/src/bin/usart.rs2
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs2
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs2
-rw-r--r--examples/stm32h723/Cargo.toml23
-rw-r--r--examples/stm32h723/src/bin/spdifrx.rs26
-rw-r--r--examples/stm32h735/Cargo.toml24
-rw-r--r--examples/stm32h735/src/bin/ltdc.rs2
-rw-r--r--examples/stm32h742/Cargo.toml30
-rw-r--r--examples/stm32h742/src/bin/qspi.rs15
-rw-r--r--examples/stm32h755cm4/Cargo.toml39
-rw-r--r--examples/stm32h755cm4/src/bin/intercore.rs182
-rw-r--r--examples/stm32h755cm7/Cargo.toml41
-rw-r--r--examples/stm32h755cm7/src/bin/intercore.rs228
-rw-r--r--examples/stm32h7b0/Cargo.toml29
-rw-r--r--examples/stm32h7rs/Cargo.toml27
-rw-r--r--examples/stm32h7rs/src/bin/blinky.rs2
-rw-r--r--examples/stm32h7rs/src/bin/eth.rs5
-rw-r--r--examples/stm32h7rs/src/bin/i2c.rs2
-rw-r--r--examples/stm32h7rs/src/bin/multiprio.rs6
-rw-r--r--examples/stm32h7rs/src/bin/signal.rs2
-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/usart.rs2
-rw-r--r--examples/stm32h7rs/src/bin/usart_dma.rs2
-rw-r--r--examples/stm32h7rs/src/bin/usart_split.rs2
-rw-r--r--examples/stm32h7rs/src/bin/usb_serial.rs2
-rw-r--r--examples/stm32h7rs/src/bin/xspi_memory_mapped.rs852
-rw-r--r--examples/stm32l0/Cargo.toml22
-rw-r--r--examples/stm32l0/src/bin/dds.rs4
-rw-r--r--examples/stm32l0/src/bin/eeprom.rs32
-rw-r--r--examples/stm32l0/src/bin/raw_spawn.rs4
-rw-r--r--examples/stm32l0/src/bin/usb_serial.rs95
-rw-r--r--examples/stm32l1/Cargo.toml24
-rw-r--r--examples/stm32l1/src/bin/eeprom.rs32
-rw-r--r--examples/stm32l4/Cargo.toml31
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs4
-rw-r--r--examples/stm32l4/src/bin/i2c.rs3
-rw-r--r--examples/stm32l4/src/bin/i2c_blocking_async.rs3
-rw-r--r--examples/stm32l4/src/bin/i2c_dma.rs12
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs12
-rw-r--r--examples/stm32l432/Cargo.toml22
-rw-r--r--examples/stm32l432/src/bin/qspi_mmap.rs17
-rw-r--r--examples/stm32l5/Cargo.toml27
-rw-r--r--examples/stm32l5/src/bin/stop.rs6
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs7
-rw-r--r--examples/stm32u0/Cargo.toml24
-rw-r--r--examples/stm32u0/src/bin/i2c.rs3
-rw-r--r--examples/stm32u5/Cargo.toml24
-rw-r--r--examples/stm32u5/src/bin/i2c.rs3
-rw-r--r--examples/stm32u5/src/bin/ltdc.rs2
-rw-r--r--examples/stm32wb/Cargo.toml24
-rw-r--r--examples/stm32wb/src/bin/gatt_server.rs9
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs4
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs2
-rw-r--r--examples/stm32wba/Cargo.toml24
-rw-r--r--examples/stm32wba/src/bin/adc.rs49
-rw-r--r--examples/stm32wba/src/bin/pwm.rs65
-rw-r--r--examples/stm32wba6/.cargo/config.toml8
-rw-r--r--examples/stm32wba6/Cargo.toml32
-rw-r--r--examples/stm32wba6/build.rs10
-rw-r--r--examples/stm32wba6/src/bin/adc.rs49
-rw-r--r--examples/stm32wba6/src/bin/blinky.rs26
-rw-r--r--examples/stm32wba6/src/bin/button_exti.rs25
-rw-r--r--examples/stm32wba6/src/bin/pwm.rs65
-rw-r--r--examples/stm32wba6/src/bin/usb_hs_serial.rs125
-rw-r--r--examples/stm32wl/Cargo.toml22
-rw-r--r--examples/stm32wl/src/bin/adc.rs39
-rw-r--r--examples/wasm/Cargo.toml12
-rw-r--r--examples/wasm/src/lib.rs2
363 files changed, 7983 insertions, 1485 deletions
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index 4ae0e6a77..b0cc63a6c 100644
--- a/examples/boot/application/nrf/Cargo.toml
+++ b/examples/boot/application/nrf/Cargo.toml
@@ -3,18 +3,19 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] }
11embassy-nrf = { version = "0.3.1", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] } 12embassy-nrf = { version = "0.7.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", ] }
12embassy-boot = { version = "0.4.0", path = "../../../../embassy-boot", features = [] } 13embassy-boot = { version = "0.6.1", path = "../../../../embassy-boot", features = [] }
13embassy-boot-nrf = { version = "0.4.0", path = "../../../../embassy-boot-nrf", features = [] } 14embassy-boot-nrf = { version = "0.8.0", path = "../../../../embassy-boot-nrf", features = [] }
14embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 15embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
15 16
16defmt = { version = "0.3", optional = true } 17defmt = { version = "1.0.1", optional = true }
17defmt-rtt = { version = "0.4", optional = true } 18defmt-rtt = { version = "1.0.0", optional = true }
18panic-reset = { version = "0.1.1" } 19panic-reset = { version = "0.1.1" }
19embedded-hal = { version = "0.2.6" } 20embedded-hal = { version = "0.2.6" }
20 21
@@ -32,3 +33,12 @@ defmt = [
32 "embassy-boot-nrf/defmt", 33 "embassy-boot-nrf/defmt",
33 "embassy-sync/defmt", 34 "embassy-sync/defmt",
34] 35]
36
37[package.metadata.embassy]
38build = [
39 { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840", "skip-include"], artifact-dir = "out/examples/boot/nrf52840" },
40 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9160" },
41 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9120" },
42 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9151" },
43 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns", "skip-include"], artifact-dir = "out/examples/boot/nrf9161" }
44]
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml
index 3c0d207d1..d86386b00 100644
--- a/examples/boot/application/rp/Cargo.toml
+++ b/examples/boot/application/rp/Cargo.toml
@@ -3,18 +3,19 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [] }
11embassy-rp = { version = "0.4.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] } 12embassy-rp = { version = "0.8.0", path = "../../../../embassy-rp", features = ["time-driver", "rp2040"] }
12embassy-boot-rp = { version = "0.5.0", path = "../../../../embassy-boot-rp", features = [] } 13embassy-boot-rp = { version = "0.8.0", path = "../../../../embassy-boot-rp", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3", features = ["print-defmt"], optional = true } 18panic-probe = { version = "1.0.0", features = ["print-defmt"], optional = true }
18panic-reset = { version = "0.1.1", optional = true } 19panic-reset = { version = "0.1.1", optional = true }
19embedded-hal = { version = "0.2.6" } 20embedded-hal = { version = "0.2.6" }
20 21
@@ -34,3 +35,8 @@ skip-include = []
34 35
35[profile.release] 36[profile.release]
36debug = true 37debug = true
38
39[package.metadata.embassy]
40build = [
41 { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/rp" }
42]
diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs
index ede0c07da..e6d7b3d4f 100644
--- a/examples/boot/application/rp/src/bin/a.rs
+++ b/examples/boot/application/rp/src/bin/a.rs
@@ -54,7 +54,7 @@ async fn main(_s: Spawner) {
54 for chunk in APP_B.chunks(4096) { 54 for chunk in APP_B.chunks(4096) {
55 buf.0[..chunk.len()].copy_from_slice(chunk); 55 buf.0[..chunk.len()].copy_from_slice(chunk);
56 defmt::info!("writing block at offset {}", offset); 56 defmt::info!("writing block at offset {}", offset);
57 writer.write(offset, &buf.0[..]).unwrap(); 57 writer.write(offset, &buf.0[..chunk.len()]).unwrap();
58 offset += chunk.len() as u32; 58 offset += chunk.len() as u32;
59 } 59 }
60 watchdog.feed(); 60 watchdog.feed();
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml
index f32727ea8..cd5f422fc 100644
--- a/examples/boot/application/stm32f3/Cargo.toml
+++ b/examples/boot/application/stm32f3/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f303re", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32" } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32" }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19 20
@@ -29,3 +30,8 @@ defmt = [
29 "embassy-sync/defmt", 30 "embassy-sync/defmt",
30] 31]
31skip-include = [] 32skip-include = []
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f3" }
37]
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml
index d62c67742..c3921a166 100644
--- a/examples/boot/application/stm32f7/Cargo.toml
+++ b/examples/boot/application/stm32f7/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32f767zi", "time-driver-any", "exti", "single-bank"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19embedded-storage = "0.3.1" 20embedded-storage = "0.3.1"
@@ -30,3 +31,8 @@ defmt = [
30 "embassy-sync/defmt", 31 "embassy-sync/defmt",
31] 32]
32skip-include = [] 33skip-include = []
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32f7" }
38]
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml
index dd3a32e45..ca186d4d9 100644
--- a/examples/boot/application/stm32h7/Cargo.toml
+++ b/examples/boot/application/stm32h7/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32h743zi", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19embedded-storage = "0.3.1" 20embedded-storage = "0.3.1"
@@ -30,3 +31,8 @@ defmt = [
30 "embassy-sync/defmt", 31 "embassy-sync/defmt",
31] 32]
32skip-include = [] 33skip-include = []
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32h7" }
38]
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml
index 0b9e9b96a..be08956f1 100644
--- a/examples/boot/application/stm32l0/Cargo.toml
+++ b/examples/boot/application/stm32l0/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l072cz", "time-driver-any", "exti", "memory-x"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19 20
@@ -29,3 +30,8 @@ defmt = [
29 "embassy-sync/defmt", 30 "embassy-sync/defmt",
30] 31]
31skip-include = [] 32skip-include = []
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv6m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l0" }
37]
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml
index 490541a2e..207eed733 100644
--- a/examples/boot/application/stm32l1/Cargo.toml
+++ b/examples/boot/application/stm32l1/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l151cb-a", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19 20
@@ -29,3 +30,8 @@ defmt = [
29 "embassy-sync/defmt", 30 "embassy-sync/defmt",
30] 31]
31skip-include = [] 32skip-include = []
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv7m-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l1" }
37]
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml
index c3aa31161..22b9642d8 100644
--- a/examples/boot/application/stm32l4/Cargo.toml
+++ b/examples/boot/application/stm32l4/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32l475vg", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19 20
@@ -29,3 +30,8 @@ defmt = [
29 "embassy-sync/defmt", 30 "embassy-sync/defmt",
30] 31]
31skip-include = [] 32skip-include = []
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32l4" }
37]
diff --git a/examples/boot/application/stm32wb-dfu/Cargo.toml b/examples/boot/application/stm32wb-dfu/Cargo.toml
index a89e2bb6e..e2be4f470 100644
--- a/examples/boot/application/stm32wb-dfu/Cargo.toml
+++ b/examples/boot/application/stm32wb-dfu/Cargo.toml
@@ -3,19 +3,20 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wb55rg", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb" } 15embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" }
15embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] } 16embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] }
16 17
17defmt = { version = "0.3", optional = true } 18defmt = { version = "1.0.1", optional = true }
18defmt-rtt = { version = "0.4", optional = true } 19defmt-rtt = { version = "1.0.0", optional = true }
19panic-reset = { version = "0.1.1" } 20panic-reset = { version = "0.1.1" }
20embedded-hal = { version = "0.2.6" } 21embedded-hal = { version = "0.2.6" }
21 22
@@ -30,3 +31,8 @@ defmt = [
30 "embassy-boot-stm32/defmt", 31 "embassy-boot-stm32/defmt",
31 "embassy-sync/defmt", 32 "embassy-sync/defmt",
32] 33]
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/boot/stm32wb-dfu" }
38]
diff --git a/examples/boot/application/stm32wb-dfu/memory.x b/examples/boot/application/stm32wb-dfu/memory.x
index ff1b800d2..f1e6b053c 100644
--- a/examples/boot/application/stm32wb-dfu/memory.x
+++ b/examples/boot/application/stm32wb-dfu/memory.x
@@ -1,10 +1,10 @@
1MEMORY 1MEMORY
2{ 2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */ 3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 24K 4 BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 48K
5 BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K 5 BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K
6 FLASH : ORIGIN = 0x08008000, LENGTH = 128K 6 FLASH : ORIGIN = 0x0800D000, LENGTH = 120K
7 DFU : ORIGIN = 0x08028000, LENGTH = 132K 7 DFU : ORIGIN = 0x0802B000, LENGTH = 120K
8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K 8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
9} 9}
10 10
diff --git a/examples/boot/application/stm32wb-dfu/secrets/key.sec b/examples/boot/application/stm32wb-dfu/secrets/key.sec
new file mode 100644
index 000000000..52e7f125b
--- /dev/null
+++ b/examples/boot/application/stm32wb-dfu/secrets/key.sec
@@ -0,0 +1,2 @@
1untrusted comment: signify secret key
2RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI=
diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs
index dda2b795b..5e7b71f5a 100644
--- a/examples/boot/application/stm32wb-dfu/src/main.rs
+++ b/examples/boot/application/stm32wb-dfu/src/main.rs
@@ -13,7 +13,7 @@ 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::Builder; 16use embassy_usb::{msos, Builder};
17use embassy_usb_dfu::consts::DfuAttributes; 17use embassy_usb_dfu::consts::DfuAttributes;
18use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate}; 18use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate};
19use panic_reset as _; 19use panic_reset as _;
@@ -22,6 +22,11 @@ bind_interrupts!(struct Irqs {
22 USB_LP => usb::InterruptHandler<peripherals::USB>; 22 USB_LP => usb::InterruptHandler<peripherals::USB>;
23}); 23});
24 24
25// This is a randomly generated GUID to allow clients on Windows to find your device.
26//
27// N.B. update to a custom GUID for your own device!
28const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
29
25#[embassy_executor::main] 30#[embassy_executor::main]
26async fn main(_spawner: Spawner) { 31async fn main(_spawner: Spawner) {
27 let mut config = embassy_stm32::Config::default(); 32 let mut config = embassy_stm32::Config::default();
@@ -54,7 +59,28 @@ async fn main(_spawner: Spawner) {
54 &mut control_buf, 59 &mut control_buf,
55 ); 60 );
56 61
57 usb_dfu(&mut builder, &mut state, Duration::from_millis(2500)); 62 // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows.
63 // Otherwise users need to do this manually using a tool like Zadig.
64 //
65 // It seems these always need to be at added at the device level for this to work and for
66 // composite devices they also need to be added on the function level (as shown later).
67 //
68 builder.msos_descriptor(msos::windows_version::WIN8_1, 2);
69 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
70 builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
71 "DeviceInterfaceGUIDs",
72 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
73 ));
74
75 usb_dfu(&mut builder, &mut state, Duration::from_millis(2500), |func| {
76 // You likely don't have to add these function level headers if your USB device is not composite
77 // (i.e. if your device does not expose another interface in addition to DFU)
78 func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
79 func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
80 "DeviceInterfaceGUIDs",
81 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
82 ));
83 });
58 84
59 let mut dev = builder.build(); 85 let mut dev = builder.build();
60 dev.run().await 86 dev.run().await
diff --git a/examples/boot/application/stm32wba-dfu/.cargo/config.toml b/examples/boot/application/stm32wba-dfu/.cargo/config.toml
new file mode 100644
index 000000000..a18ec3944
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/.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 STM32WBA65RI"
4
5[build]
6target = "thumbv8m.main-none-eabihf"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/boot/application/stm32wba-dfu/Cargo.toml b/examples/boot/application/stm32wba-dfu/Cargo.toml
new file mode 100644
index 000000000..6f4213b2c
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/Cargo.toml
@@ -0,0 +1,38 @@
1[package]
2edition = "2021"
3name = "embassy-boot-stm32wba-dfu-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wba65ri", "time-driver-any", "exti"] }
13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
15embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb" }
16embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["application", "cortex-m"] }
17
18defmt = { version = "1.0.1", optional = true }
19defmt-rtt = { version = "1.0.0", optional = true }
20panic-reset = { version = "0.1.1" }
21embedded-hal = { version = "0.2.6" }
22
23cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
24cortex-m-rt = "0.7.0"
25
26[features]
27defmt = [
28 "dep:defmt",
29 "dep:defmt-rtt",
30 "embassy-stm32/defmt",
31 "embassy-boot-stm32/defmt",
32 "embassy-sync/defmt",
33]
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/boot/stm32wba-dfu" }
38]
diff --git a/examples/boot/application/stm32wba-dfu/README.md b/examples/boot/application/stm32wba-dfu/README.md
new file mode 100644
index 000000000..30692034c
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/README.md
@@ -0,0 +1,9 @@
1# Examples using bootloader
2
3Example for STM32WBA demonstrating the USB DFU application.
4
5## Usage
6
7```
8cargo flash --release --chip STM32WBA65RI
9```
diff --git a/examples/boot/application/stm32wba-dfu/build.rs b/examples/boot/application/stm32wba-dfu/build.rs
new file mode 100644
index 000000000..e1da69328
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/build.rs
@@ -0,0 +1,37 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 if env::var("CARGO_FEATURE_DEFMT").is_ok() {
35 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
36 }
37}
diff --git a/examples/boot/application/stm32wba-dfu/memory.x b/examples/boot/application/stm32wba-dfu/memory.x
new file mode 100644
index 000000000..fcdb6b6d2
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/memory.x
@@ -0,0 +1,15 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 BOOTLOADER : ORIGIN = 0x08000000, LENGTH = 80K
5 BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K
6 FLASH : ORIGIN = 0x08016000, LENGTH = 120K
7 DFU : ORIGIN = 0x0803C000, LENGTH = 160K
8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K
9}
10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
13
14__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER);
15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER);
diff --git a/examples/boot/application/stm32wba-dfu/secrets/key.sec b/examples/boot/application/stm32wba-dfu/secrets/key.sec
new file mode 100644
index 000000000..52e7f125b
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/secrets/key.sec
@@ -0,0 +1,2 @@
1untrusted comment: signify secret key
2RWRCSwAAAAATdHQF3B4jEIoNZrjADRp2LbjJjNdNNzKwTCe4IB6mDNq96pe53nbNxwbdCc/T4hrz7W+Kx1MwrZ0Yz5xebSK5Z0Kh/3Cdf039U5f+eoTDS2fIGbohyUbrtwKzjyE0qXI=
diff --git a/examples/boot/application/stm32wba-dfu/src/main.rs b/examples/boot/application/stm32wba-dfu/src/main.rs
new file mode 100644
index 000000000..bf17a7150
--- /dev/null
+++ b/examples/boot/application/stm32wba-dfu/src/main.rs
@@ -0,0 +1,114 @@
1#![no_std]
2#![no_main]
3
4use core::cell::RefCell;
5
6#[cfg(feature = "defmt")]
7use defmt_rtt as _;
8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareState, FirmwareUpdaterConfig};
9use embassy_executor::Spawner;
10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::usb::{self, Driver};
12use embassy_stm32::{bind_interrupts, peripherals};
13use embassy_sync::blocking_mutex::Mutex;
14use embassy_time::Duration;
15use embassy_usb::{msos, Builder};
16use embassy_usb_dfu::consts::DfuAttributes;
17use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate};
18use panic_reset as _;
19
20bind_interrupts!(struct Irqs {
21 USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
22});
23
24// This is a randomly generated GUID to allow clients on Windows to find your device.
25//
26// N.B. update to a custom GUID for your own device!
27const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
28
29#[embassy_executor::main]
30async fn main(_spawner: Spawner) {
31 let mut config = embassy_stm32::Config::default();
32
33 {
34 use embassy_stm32::rcc::*;
35 config.rcc.pll1 = Some(Pll {
36 source: PllSource::HSI,
37 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
38 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
39 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
40 divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz
41 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS)
42 frac: Some(0), // Fractional part (disabled)
43 });
44
45 config.rcc.ahb_pre = AHBPrescaler::DIV1;
46 config.rcc.apb1_pre = APBPrescaler::DIV1;
47 config.rcc.apb2_pre = APBPrescaler::DIV1;
48 config.rcc.apb7_pre = APBPrescaler::DIV1;
49 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
50
51 config.rcc.voltage_scale = VoltageScale::RANGE1;
52 config.rcc.mux.otghssel = mux::Otghssel::PLL1_P;
53 config.rcc.sys = Sysclk::PLL1_R;
54 }
55
56 let p = embassy_stm32::init(config);
57 let flash = Flash::new_blocking(p.FLASH);
58 let flash = Mutex::new(RefCell::new(flash));
59
60 let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash);
61 let mut magic = AlignedBuffer([0; WRITE_SIZE]);
62 let mut firmware_state = BlockingFirmwareState::from_config(config, &mut magic.0);
63 firmware_state.mark_booted().expect("Failed to mark booted");
64
65 // Create the driver, from the HAL.
66 let mut ep_out_buffer = [0u8; 256];
67 let mut config = embassy_stm32::usb::Config::default();
68 config.vbus_detection = false;
69
70 let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config);
71 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
72 config.manufacturer = Some("Embassy");
73 config.product = Some("USB-DFU Runtime example");
74 config.serial_number = Some("1235678");
75
76 let mut config_descriptor = [0; 256];
77 let mut bos_descriptor = [0; 256];
78 let mut control_buf = [0; 64];
79 let mut state = Control::new(firmware_state, DfuAttributes::CAN_DOWNLOAD, ResetImmediate);
80 let mut builder = Builder::new(
81 driver,
82 config,
83 &mut config_descriptor,
84 &mut bos_descriptor,
85 &mut [],
86 &mut control_buf,
87 );
88
89 // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows.
90 // Otherwise users need to do this manually using a tool like Zadig.
91 //
92 // It seems these always need to be at added at the device level for this to work and for
93 // composite devices they also need to be added on the function level (as shown later).
94
95 builder.msos_descriptor(msos::windows_version::WIN8_1, 2);
96 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
97 builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
98 "DeviceInterfaceGUIDs",
99 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
100 ));
101
102 usb_dfu(&mut builder, &mut state, Duration::from_millis(1000), |func| {
103 // You likely don't have to add these function level headers if your USB device is not composite
104 // (i.e. if your device does not expose another interface in addition to DFU)
105 func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
106 func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
107 "DeviceInterfaceGUIDs",
108 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
109 ));
110 });
111
112 let mut dev = builder.build();
113 dev.run().await
114}
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml
index f4d7ae712..8d1446ba9 100644
--- a/examples/boot/application/stm32wl/Cargo.toml
+++ b/examples/boot/application/stm32wl/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 9embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
9embassy-executor = { version = "0.7.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] } 10embassy-executor = { version = "0.9.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
10embassy-time = { version = "0.4.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../../../embassy-time", features = [ "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../../../embassy-stm32", features = ["stm32wl55jc-cm4", "time-driver-any", "exti"] }
12embassy-boot-stm32 = { version = "0.2.0", path = "../../../../embassy-boot-stm32", features = [] } 13embassy-boot-stm32 = { version = "0.6.0", path = "../../../../embassy-boot-stm32", features = [] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../../../embassy-embedded-hal" }
14 15
15defmt = { version = "0.3", optional = true } 16defmt = { version = "1.0.1", optional = true }
16defmt-rtt = { version = "0.4", optional = true } 17defmt-rtt = { version = "1.0.0", optional = true }
17panic-reset = { version = "0.1.1" } 18panic-reset = { version = "0.1.1" }
18embedded-hal = { version = "0.2.6" } 19embedded-hal = { version = "0.2.6" }
19 20
@@ -29,3 +30,8 @@ defmt = [
29 "embassy-sync/defmt", 30 "embassy-sync/defmt",
30] 31]
31skip-include = [] 32skip-include = []
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv7em-none-eabi", features = ["skip-include"], artifact-dir = "out/examples/boot/stm32wl" }
37]
diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml
index 34a0553e3..72b7114d4 100644
--- a/examples/boot/bootloader/nrf/Cargo.toml
+++ b/examples/boot/bootloader/nrf/Cargo.toml
@@ -4,15 +4,16 @@ name = "nrf-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Bootloader for nRF chips" 5description = "Bootloader for nRF chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7publish = false
7 8
8[dependencies] 9[dependencies]
9defmt = { version = "0.3", optional = true } 10defmt = { version = "1.0.1", optional = true }
10defmt-rtt = { version = "0.4", optional = true } 11defmt-rtt = { version = "1.0.0", optional = true }
11 12
12embassy-nrf = { path = "../../../../embassy-nrf", features = [] } 13embassy-nrf = { path = "../../../../embassy-nrf", features = [] }
13embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" } 14embassy-boot-nrf = { path = "../../../../embassy-boot-nrf" }
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 16embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
16cortex-m-rt = { version = "0.7" } 17cortex-m-rt = { version = "0.7" }
17cfg-if = "1.0.0" 18cfg-if = "1.0.0"
18 19
@@ -57,3 +58,12 @@ debug = false
57debug-assertions = false 58debug-assertions = false
58opt-level = 0 59opt-level = 0
59overflow-checks = false 60overflow-checks = false
61
62[package.metadata.embassy]
63build = [
64 { target = "thumbv7em-none-eabi", features = ["embassy-nrf/nrf52840"] },
65 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9160-ns"] },
66 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9120-ns"] },
67 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9151-ns"] },
68 { target = "thumbv8m.main-none-eabihf", features = ["embassy-nrf/nrf9161-ns"] }
69]
diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml
index 7c9c3c779..93a1c4edf 100644
--- a/examples/boot/bootloader/rp/Cargo.toml
+++ b/examples/boot/bootloader/rp/Cargo.toml
@@ -4,14 +4,15 @@ name = "rp-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example bootloader for RP2040 chips" 5description = "Example bootloader for RP2040 chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7publish = false
7 8
8[dependencies] 9[dependencies]
9defmt = { version = "0.3", optional = true } 10defmt = { version = "1.0.1", optional = true }
10defmt-rtt = { version = "0.4", optional = true } 11defmt-rtt = { version = "1.0.0", optional = true }
11 12
12embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] } 13embassy-rp = { path = "../../../../embassy-rp", features = ["rp2040"] }
13embassy-boot-rp = { path = "../../../../embassy-boot-rp" } 14embassy-boot-rp = { path = "../../../../embassy-boot-rp" }
14embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 15embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
15embassy-time = { path = "../../../../embassy-time", features = [] } 16embassy-time = { path = "../../../../embassy-time", features = [] }
16 17
17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
@@ -31,3 +32,8 @@ defmt = [
31[profile.release] 32[profile.release]
32debug = true 33debug = true
33opt-level = 's' 34opt-level = 's'
35
36[package.metadata.embassy]
37build = [
38 { target = "thumbv6m-none-eabi" }
39]
diff --git a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
index 4beb9c61c..95ca20a59 100644
--- a/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
+++ b/examples/boot/bootloader/stm32-dual-bank/Cargo.toml
@@ -4,10 +4,11 @@ name = "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"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7publish = false
7 8
8[dependencies] 9[dependencies]
9defmt = { version = "0.3", optional = true } 10defmt = { version = "1.0.1", optional = true }
10defmt-rtt = { version = "0.4", optional = true } 11defmt-rtt = { version = "1.0.0", optional = true }
11 12
12embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } 13embassy-stm32 = { path = "../../../../embassy-stm32", features = [] }
13embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } 14embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" }
@@ -15,7 +16,7 @@ cortex-m = { version = "0.7.6", features = [
15 "inline-asm", 16 "inline-asm",
16 "critical-section-single-core", 17 "critical-section-single-core",
17] } 18] }
18embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 19embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
19cortex-m-rt = { version = "0.7" } 20cortex-m-rt = { version = "0.7" }
20embedded-storage = "0.3.1" 21embedded-storage = "0.3.1"
21embedded-storage-async = "0.4.0" 22embedded-storage-async = "0.4.0"
@@ -54,3 +55,8 @@ debug = false
54debug-assertions = false 55debug-assertions = false
55opt-level = 0 56opt-level = 0
56overflow-checks = false 57overflow-checks = false
58
59[package.metadata.embassy]
60build = [
61 { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32h743zi"] }
62]
diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml
index 9abad8636..526637f37 100644
--- a/examples/boot/bootloader/stm32/Cargo.toml
+++ b/examples/boot/bootloader/stm32/Cargo.toml
@@ -4,15 +4,16 @@ name = "stm32-bootloader-example"
4version = "0.1.0" 4version = "0.1.0"
5description = "Example bootloader for STM32 chips" 5description = "Example bootloader for STM32 chips"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7publish = false
7 8
8[dependencies] 9[dependencies]
9defmt = { version = "0.3", optional = true } 10defmt = { version = "1.0.1", optional = true }
10defmt-rtt = { version = "0.4", optional = true } 11defmt-rtt = { version = "1.0.0", optional = true }
11 12
12embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } 13embassy-stm32 = { path = "../../../../embassy-stm32", features = [] }
13embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } 14embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" }
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 16embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
16cortex-m-rt = { version = "0.7" } 17cortex-m-rt = { version = "0.7" }
17embedded-storage = "0.3.1" 18embedded-storage = "0.3.1"
18embedded-storage-async = "0.4.0" 19embedded-storage-async = "0.4.0"
@@ -56,3 +57,8 @@ debug = false
56debug-assertions = false 57debug-assertions = false
57opt-level = 0 58opt-level = 0
58overflow-checks = false 59overflow-checks = false
60
61[package.metadata.embassy]
62build = [
63 { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32l496zg"] }
64]
diff --git a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
index 01343b86b..ef10aeabf 100644
--- a/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
+++ b/examples/boot/bootloader/stm32wb-dfu/Cargo.toml
@@ -4,22 +4,23 @@ name = "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"
6license = "MIT OR Apache-2.0" 6license = "MIT OR Apache-2.0"
7publish = false
7 8
8[dependencies] 9[dependencies]
9defmt = { version = "0.3", optional = true } 10defmt = { version = "1.0.1", optional = true }
10defmt-rtt = { version = "0.4", optional = true } 11defmt-rtt = { version = "1.0.0", optional = true }
11 12
12embassy-stm32 = { path = "../../../../embassy-stm32", features = [] } 13embassy-stm32 = { path = "../../../../embassy-stm32", features = [] }
13embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" } 14embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" }
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15embassy-sync = { version = "0.6.2", path = "../../../../embassy-sync" } 16embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
16cortex-m-rt = { version = "0.7" } 17cortex-m-rt = { version = "0.7" }
17embedded-storage = "0.3.1" 18embedded-storage = "0.3.1"
18embedded-storage-async = "0.4.0" 19embedded-storage-async = "0.4.0"
19cfg-if = "1.0.0" 20cfg-if = "1.0.0"
20embassy-usb-dfu = { version = "0.1.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] } 21embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] }
21embassy-usb = { version = "0.4.0", path = "../../../../embassy-usb", default-features = false } 22embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false }
22embassy-futures = { version = "0.1.1", path = "../../../../embassy-futures" } 23embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" }
23 24
24[features] 25[features]
25defmt = [ 26defmt = [
@@ -30,6 +31,7 @@ defmt = [
30 "embassy-usb/defmt", 31 "embassy-usb/defmt",
31 "embassy-usb-dfu/defmt" 32 "embassy-usb-dfu/defmt"
32] 33]
34verify = ["embassy-usb-dfu/ed25519-salty"]
33 35
34[profile.dev] 36[profile.dev]
35debug = 2 37debug = 2
@@ -61,3 +63,9 @@ debug = false
61debug-assertions = false 63debug-assertions = false
62opt-level = 0 64opt-level = 0
63overflow-checks = false 65overflow-checks = false
66
67[package.metadata.embassy]
68build = [
69 { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg"] },
70 { target = "thumbv7em-none-eabi", features = ["embassy-stm32/stm32wb55rg", "verify"] }
71]
diff --git a/examples/boot/bootloader/stm32wb-dfu/README.md b/examples/boot/bootloader/stm32wb-dfu/README.md
index 3c5f268a0..99a7002c4 100644
--- a/examples/boot/bootloader/stm32wb-dfu/README.md
+++ b/examples/boot/bootloader/stm32wb-dfu/README.md
@@ -28,6 +28,32 @@ cargo objcopy --release -- -O binary fw.bin
28dfu-util -d c0de:cafe -w -D fw.bin 28dfu-util -d c0de:cafe -w -D fw.bin
29``` 29```
30 30
31### 3. Sign Updates Before Flashing (Optional)
32
33Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu.
34
35To sign (and then verify) application updates, you will first need to generate a key pair:
36
37```
38signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec
39tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short
40```
41
42Then you will need to sign all you binaries with the private key:
43
44```
45cargo objcopy --release -- -O binary fw.bin
46shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt
47signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig
48cp fw.bin fw-signed.bin
49tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin
50dfu-util -d c0de:cafe -w -D fw-signed.bin
51```
52
53Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures.
54
55N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system.
56
31## Troubleshooting 57## Troubleshooting
32 58
33- Make sure your device is in DFU mode before flashing 59- Make sure your device is in DFU mode before flashing
diff --git a/examples/boot/bootloader/stm32wb-dfu/memory.x b/examples/boot/bootloader/stm32wb-dfu/memory.x
index 858062631..77c4d2ee2 100644
--- a/examples/boot/bootloader/stm32wb-dfu/memory.x
+++ b/examples/boot/bootloader/stm32wb-dfu/memory.x
@@ -1,10 +1,10 @@
1MEMORY 1MEMORY
2{ 2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */ 3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 FLASH : ORIGIN = 0x08000000, LENGTH = 24K 4 FLASH : ORIGIN = 0x08000000, LENGTH = 48K
5 BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K 5 BOOTLOADER_STATE : ORIGIN = 0x0800C000, LENGTH = 4K
6 ACTIVE : ORIGIN = 0x08008000, LENGTH = 128K 6 ACTIVE : ORIGIN = 0x0800D000, LENGTH = 120K
7 DFU : ORIGIN = 0x08028000, LENGTH = 132K 7 DFU : ORIGIN = 0x0802B000, LENGTH = 120K
8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K 8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
9} 9}
10 10
diff --git a/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short
new file mode 100644
index 000000000..7a4de8585
--- /dev/null
+++ b/examples/boot/bootloader/stm32wb-dfu/secrets/key.pub.short
@@ -0,0 +1 @@
gB��p�M�S��z��Kg��!�F���!4�r \ No newline at end of file
diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
index 28216806e..107f243fd 100644
--- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs
+++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs
@@ -20,9 +20,17 @@ bind_interrupts!(struct Irqs {
20 USB_LP => usb::InterruptHandler<peripherals::USB>; 20 USB_LP => usb::InterruptHandler<peripherals::USB>;
21}); 21});
22 22
23// This is a randomly generated GUID to allow clients on Windows to find our device 23// This is a randomly generated GUID to allow clients on Windows to find your device.
24//
25// N.B. update to a custom GUID for your own device!
24const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"]; 26const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
25 27
28// This is a randomly generated example key.
29//
30// N.B. Please replace with your own!
31#[cfg(feature = "verify")]
32static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short");
33
26#[entry] 34#[entry]
27fn main() -> ! { 35fn main() -> ! {
28 let mut config = embassy_stm32::Config::default(); 36 let mut config = embassy_stm32::Config::default();
@@ -55,7 +63,13 @@ fn main() -> ! {
55 let mut config_descriptor = [0; 256]; 63 let mut config_descriptor = [0; 256];
56 let mut bos_descriptor = [0; 256]; 64 let mut bos_descriptor = [0; 256];
57 let mut control_buf = [0; 4096]; 65 let mut control_buf = [0; 4096];
66
67 #[cfg(not(feature = "verify"))]
58 let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate); 68 let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate);
69
70 #[cfg(feature = "verify")]
71 let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY);
72
59 let mut builder = Builder::new( 73 let mut builder = Builder::new(
60 driver, 74 driver,
61 config, 75 config,
@@ -68,7 +82,8 @@ fn main() -> ! {
68 // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows. 82 // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows.
69 // Otherwise users need to do this manually using a tool like Zadig. 83 // Otherwise users need to do this manually using a tool like Zadig.
70 // 84 //
71 // It seems it is important for the DFU class that these headers be on the Device level. 85 // It seems these always need to be at added at the device level for this to work and for
86 // composite devices they also need to be added on the function level (as shown later).
72 // 87 //
73 builder.msos_descriptor(msos::windows_version::WIN8_1, 2); 88 builder.msos_descriptor(msos::windows_version::WIN8_1, 2);
74 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", "")); 89 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
@@ -77,7 +92,15 @@ fn main() -> ! {
77 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS), 92 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
78 )); 93 ));
79 94
80 usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state); 95 usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| {
96 // You likely don't have to add these function level headers if your USB device is not composite
97 // (i.e. if your device does not expose another interface in addition to DFU)
98 func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
99 func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
100 "DeviceInterfaceGUIDs",
101 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
102 ));
103 });
81 104
82 let mut dev = builder.build(); 105 let mut dev = builder.build();
83 embassy_futures::block_on(dev.run()); 106 embassy_futures::block_on(dev.run());
diff --git a/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml
new file mode 100644
index 000000000..1896068d8
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/.cargo/config.toml
@@ -0,0 +1,8 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2runner = "probe-rs run --chip STM32WBA65RI"
3
4[build]
5target = "thumbv8m.main-none-eabihf"
6
7[env]
8DEFMT_LOG = "trace"
diff --git a/examples/boot/bootloader/stm32wba-dfu/Cargo.toml b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml
new file mode 100644
index 000000000..16de7684e
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/Cargo.toml
@@ -0,0 +1,70 @@
1[package]
2edition = "2021"
3name = "stm32wba6-dfu-bootloader-example"
4version = "0.1.0"
5description = "Example USB DFUbootloader for the STM32WBA series of chips"
6license = "MIT OR Apache-2.0"
7publish = false
8
9[dependencies]
10defmt = { version = "1.0.1", optional = true }
11defmt-rtt = { version = "1.0.0", optional = true }
12
13embassy-stm32 = { path = "../../../../embassy-stm32", features = [] }
14embassy-boot-stm32 = { path = "../../../../embassy-boot-stm32" }
15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
16embassy-sync = { version = "0.7.2", path = "../../../../embassy-sync" }
17cortex-m-rt = { version = "0.7" }
18embedded-storage = "0.3.1"
19embedded-storage-async = "0.4.0"
20cfg-if = "1.0.0"
21embassy-usb-dfu = { version = "0.2.0", path = "../../../../embassy-usb-dfu", features = ["dfu", "cortex-m"] }
22embassy-usb = { version = "0.5.1", path = "../../../../embassy-usb", default-features = false }
23embassy-futures = { version = "0.1.2", path = "../../../../embassy-futures" }
24
25[features]
26defmt = [
27 "dep:defmt",
28 "dep:defmt-rtt",
29 "embassy-boot-stm32/defmt",
30 "embassy-stm32/defmt",
31 "embassy-usb/defmt",
32 "embassy-usb-dfu/defmt"
33]
34verify = ["embassy-usb-dfu/ed25519-salty"]
35
36[profile.dev]
37debug = 2
38debug-assertions = true
39incremental = false
40opt-level = 'z'
41overflow-checks = true
42
43[profile.release]
44codegen-units = 1
45debug = 2
46debug-assertions = false
47incremental = false
48lto = 'fat'
49opt-level = 'z'
50overflow-checks = false
51
52# do not optimize proc-macro crates = faster builds from scratch
53[profile.dev.build-override]
54codegen-units = 8
55debug = false
56debug-assertions = false
57opt-level = 0
58overflow-checks = false
59
60[profile.release.build-override]
61codegen-units = 8
62debug = false
63debug-assertions = false
64opt-level = 0
65overflow-checks = false
66
67[package.metadata.embassy]
68build = [
69 { target = "thumbv8m.main-none-eabihf", features = ["embassy-stm32/stm32wba65ri", "verify"] }
70]
diff --git a/examples/boot/bootloader/stm32wba-dfu/README.md b/examples/boot/bootloader/stm32wba-dfu/README.md
new file mode 100644
index 000000000..d50164255
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/README.md
@@ -0,0 +1,63 @@
1# Bootloader for STM32
2
3This bootloader implementation uses `embassy-boot` and `embassy-usb-dfu` to manage firmware updates and interact with the flash memory on STM32WB55 devices.
4
5## Prerequisites
6
7- Rust toolchain with `cargo` installed
8- `cargo-flash` for flashing the bootloader
9- `dfu-util` for firmware updates
10- `cargo-binutils` for binary generation
11
12## Usage
13
14### 1. Flash the Bootloader
15
16First, flash the bootloader to your device:
17
18```
19cargo flash --features embassy-stm32/stm32wba65ri --release --chip STM32WBA65RI
20```
21
22### 2. Build and Flash Application
23
24Generate your application binary and flash it using DFU:
25
26```
27cargo objcopy --release -- -O binary fw.bin
28dfu-util -d c0de:cafe -w -D fw.bin
29```
30
31### 3. Sign Updates Before Flashing (Optional)
32
33Currently, embassy-usb-dfu only supports a limited implementation of the generic support for ed25519-based update verfication in embassy-boot. This implementation assumes that a signature is simply concatenated to the end of an update binary. For more details, please see https://embassy.dev/book/#_verification and/or refer to the documentation for embassy-boot-dfu.
34
35To sign (and then verify) application updates, you will first need to generate a key pair:
36
37```
38signify-openbsd -G -n -p secrets/key.pub -s secrets/key.sec
39tail -n1 secrets/key.pub | base64 -d -i - | dd ibs=10 skip=1 > secrets/key.pub.short
40```
41
42Then you will need to sign all you binaries with the private key:
43
44```
45cargo objcopy --release -- -O binary fw.bin
46shasum -a 512 -b fw.bin | head -c128 | xxd -p -r > target/fw-hash.txt
47signify-openbsd -S -s secrets/key.sec -m target/fw-hash.txt -x target/fw-hash.sig
48cp fw.bin fw-signed.bin
49tail -n1 target/fw-hash.sig | base64 -d -i - | dd ibs=10 skip=1 >> fw-signed.bin
50dfu-util -d c0de:cafe -w -D fw-signed.bin
51```
52
53Finally, as shown in this example with the `verify` feature flag enabled, you then need to embed the public key into your bootloader so that it can verify update signatures.
54
55N.B. Please note that the exact steps above are NOT a good example of how to manage your keys securely. In a production environment, you should take great care to ensure that (at least the private key) is protected and not leaked into your version control system.
56
57## Troubleshooting
58
59- Make sure your device is in DFU mode before flashing
60- Verify the USB VID:PID matches your device (c0de:cafe)
61- Check USB connections if the device is not detected
62- Make sure the transfer size option of `dfu-util` matches the bootloader configuration. By default, `dfu-util` will use the transfer size reported by the device, but you can override it with the `-t` option if needed.
63- Make sure `control_buf` size is larger than or equal to the `usb_dfu` `BLOCK_SIZE` parameter (in this example, both are set to 4096 bytes).
diff --git a/examples/boot/bootloader/stm32wba-dfu/build.rs b/examples/boot/bootloader/stm32wba-dfu/build.rs
new file mode 100644
index 000000000..fd605991f
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/build.rs
@@ -0,0 +1,27 @@
1use std::env;
2use std::fs::File;
3use std::io::Write;
4use std::path::PathBuf;
5
6fn main() {
7 // Put `memory.x` in our output directory and ensure it's
8 // on the linker search path.
9 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
10 File::create(out.join("memory.x"))
11 .unwrap()
12 .write_all(include_bytes!("memory.x"))
13 .unwrap();
14 println!("cargo:rustc-link-search={}", out.display());
15
16 // By default, Cargo will re-run a build script whenever
17 // any file in the project changes. By specifying `memory.x`
18 // here, we ensure the build script is only re-run when
19 // `memory.x` is changed.
20 println!("cargo:rerun-if-changed=memory.x");
21
22 println!("cargo:rustc-link-arg-bins=--nmagic");
23 println!("cargo:rustc-link-arg-bins=-Tlink.x");
24 if env::var("CARGO_FEATURE_DEFMT").is_ok() {
25 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
26 }
27}
diff --git a/examples/boot/bootloader/stm32wba-dfu/memory.x b/examples/boot/bootloader/stm32wba-dfu/memory.x
new file mode 100644
index 000000000..105c9e960
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/memory.x
@@ -0,0 +1,18 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 FLASH : ORIGIN = 0x08000000, LENGTH = 80K
5 BOOTLOADER_STATE : ORIGIN = 0x08014000, LENGTH = 8K
6 ACTIVE : ORIGIN = 0x08016000, LENGTH = 120K
7 DFU : ORIGIN = 0x0803C000, LENGTH = 160K
8 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 400K
9}
10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(FLASH);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(FLASH);
13
14__bootloader_active_start = ORIGIN(ACTIVE) - ORIGIN(FLASH);
15__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE) - ORIGIN(FLASH);
16
17__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(FLASH);
18__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(FLASH); \ No newline at end of file
diff --git a/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short
new file mode 100644
index 000000000..7a4de8585
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/secrets/key.pub.short
@@ -0,0 +1 @@
gB��p�M�S��z��Kg��!�F���!4�r \ No newline at end of file
diff --git a/examples/boot/bootloader/stm32wba-dfu/src/main.rs b/examples/boot/bootloader/stm32wba-dfu/src/main.rs
new file mode 100644
index 000000000..75d8d4199
--- /dev/null
+++ b/examples/boot/bootloader/stm32wba-dfu/src/main.rs
@@ -0,0 +1,158 @@
1#![no_std]
2#![no_main]
3
4use core::cell::RefCell;
5
6use cortex_m_rt::{entry, exception};
7#[cfg(feature = "defmt")]
8use defmt_rtt as _;
9use embassy_boot_stm32::*;
10use embassy_stm32::flash::{Flash, BANK1_REGION, WRITE_SIZE};
11use embassy_stm32::usb::Driver;
12use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
13use embassy_sync::blocking_mutex::Mutex;
14use embassy_usb::{msos, Builder};
15use embassy_usb_dfu::consts::DfuAttributes;
16use embassy_usb_dfu::{usb_dfu, Control, ResetImmediate};
17
18bind_interrupts!(struct Irqs {
19 USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
20});
21
22// This is a randomly generated GUID to allow clients on Windows to find your device.
23//
24// N.B. update to a custom GUID for your own device!
25const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
26
27// This is a randomly generated example key.
28//
29// N.B. Please replace with your own!
30#[cfg(feature = "verify")]
31static PUBLIC_SIGNING_KEY: &[u8; 32] = include_bytes!("../secrets/key.pub.short");
32
33#[entry]
34fn main() -> ! {
35 let mut config = Config::default();
36
37 {
38 use embassy_stm32::rcc::*;
39 config.rcc.pll1 = Some(Pll {
40 source: PllSource::HSI,
41 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
42 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
43 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
44 divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz
45 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS)
46 frac: Some(0), // Fractional part (disabled)
47 });
48
49 config.rcc.ahb_pre = AHBPrescaler::DIV1;
50 config.rcc.apb1_pre = APBPrescaler::DIV1;
51 config.rcc.apb2_pre = APBPrescaler::DIV1;
52 config.rcc.apb7_pre = APBPrescaler::DIV1;
53 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
54
55 config.rcc.voltage_scale = VoltageScale::RANGE1;
56 config.rcc.mux.otghssel = mux::Otghssel::PLL1_P;
57 config.rcc.sys = Sysclk::PLL1_R;
58 }
59
60 let p = embassy_stm32::init(config);
61
62 // Prevent a hard fault when accessing flash 'too early' after boot.
63 #[cfg(feature = "defmt")]
64 for _ in 0..10000000 {
65 cortex_m::asm::nop();
66 }
67
68 let layout = Flash::new_blocking(p.FLASH).into_blocking_regions();
69 let flash = Mutex::new(RefCell::new(layout.bank1_region));
70
71 let config = BootLoaderConfig::from_linkerfile_blocking(&flash, &flash, &flash);
72 let active_offset = config.active.offset();
73 let bl = BootLoader::prepare::<_, _, _, 2048>(config);
74
75 // Create the driver, from the HAL.
76 let mut ep_out_buffer = [0u8; 256];
77 let mut config = embassy_stm32::usb::Config::default();
78
79 config.vbus_detection = false;
80
81 if bl.state == State::DfuDetach {
82 let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config);
83 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
84 config.manufacturer = Some("Embassy");
85 config.product = Some("USB-DFU Bootloader example");
86 config.serial_number = Some("1235678");
87
88 let fw_config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash, &flash);
89 let mut buffer = AlignedBuffer([0; WRITE_SIZE]);
90 let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]);
91
92 let mut config_descriptor = [0; 256];
93 let mut bos_descriptor = [0; 256];
94 let mut control_buf = [0; 4096];
95
96 #[cfg(not(feature = "verify"))]
97 let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate);
98
99 #[cfg(feature = "verify")]
100 let mut state = Control::new(updater, DfuAttributes::CAN_DOWNLOAD, ResetImmediate, PUBLIC_SIGNING_KEY);
101
102 let mut builder = Builder::new(
103 driver,
104 config,
105 &mut config_descriptor,
106 &mut bos_descriptor,
107 &mut [],
108 &mut control_buf,
109 );
110
111 // We add MSOS headers so that the device automatically gets assigned the WinUSB driver on Windows.
112 // Otherwise users need to do this manually using a tool like Zadig.
113 //
114 // It seems these always need to be at added at the device level for this to work and for
115 // composite devices they also need to be added on the function level (as shown later).
116
117 builder.msos_descriptor(msos::windows_version::WIN8_1, 2);
118 builder.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
119 builder.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
120 "DeviceInterfaceGUIDs",
121 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
122 ));
123
124 usb_dfu::<_, _, _, _, 4096>(&mut builder, &mut state, |func| {
125 // You likely don't have to add these function level headers if your USB device is not composite
126 // (i.e. if your device does not expose another interface in addition to DFU)
127 func.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
128 func.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
129 "DeviceInterfaceGUIDs",
130 msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
131 ));
132 });
133
134 let mut dev = builder.build();
135 embassy_futures::block_on(dev.run());
136 }
137
138 unsafe { bl.load(BANK1_REGION.base + active_offset) }
139}
140
141#[no_mangle]
142#[cfg_attr(target_os = "none", link_section = ".HardFault.user")]
143unsafe extern "C" fn HardFault() {
144 cortex_m::peripheral::SCB::sys_reset();
145}
146
147#[exception]
148unsafe fn DefaultHandler(_: i16) -> ! {
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;
151
152 panic!("DefaultHandler #{:?}", irqn);
153}
154
155#[panic_handler]
156fn panic(_info: &core::panic::PanicInfo) -> ! {
157 cortex_m::asm::udf();
158}
diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml
index f5a6e6995..579748595 100644
--- a/examples/lpc55s69/Cargo.toml
+++ b/examples/lpc55s69/Cargo.toml
@@ -4,19 +4,25 @@ name = "embassy-nxp-lpc55s69-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7publish = false
7 8
8[dependencies] 9[dependencies]
9embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["rt"] } 10embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55-core0", "rt", "defmt", "time-driver-rtc"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
11embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] }
13panic-halt = "0.2.0" 14panic-halt = "1.0.0"
14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
15cortex-m-rt = { version = "0.7.0"} 16cortex-m-rt = { version = "0.7.0"}
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18panic-probe = { version = "0.3.2", features = ["print-defmt"] } 19panic-probe = { version = "1.0.0", features = ["print-defmt"] }
19panic-semihosting = "0.6.0" 20panic-semihosting = "0.6.0"
20 21
21[profile.release] 22[profile.release]
22debug = 2 23debug = 2
24
25[package.metadata.embassy]
26build = [
27 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/lpc55s69" }
28]
diff --git a/examples/lpc55s69/README.md b/examples/lpc55s69/README.md
new file mode 100644
index 000000000..d200f4f99
--- /dev/null
+++ b/examples/lpc55s69/README.md
@@ -0,0 +1,12 @@
1# LPC55S69 Examples
2
3## Available examples:
4- blinky_nop: Blink the integrated RED LED using nops as delay. Useful for flashing simple and known-good software on board.
5- button_executor: Turn on/off an LED by pressing the USER button. Demonstrates how to use the PINT and GPIO drivers.
6- blinky_embassy_time: Blink the integrated RED LED using `embassy-time`. Demonstrates how to use the time-driver that uses RTC.
7
8## Important Notes
9
10On older version of probe-rs, some examples (such as `blinky_embassy_time`) do not work directly after flashing and the board must be reset after flashing. It is reccomended to update the version of probe-rs to the latest one.
11
12When developing drivers for this board, probe-rs might not be able to flash the board after entering a fault. Either reset the board to clear the fault, or use NXP's proprietary software `LinkServer`/`LinkFlash` to bring the board back to a known-good state. \ No newline at end of file
diff --git a/examples/lpc55s69/src/bin/blinky_embassy_time.rs b/examples/lpc55s69/src/bin/blinky_embassy_time.rs
new file mode 100644
index 000000000..adc3d8bd3
--- /dev/null
+++ b/examples/lpc55s69/src/bin/blinky_embassy_time.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nxp::gpio::{Level, Output};
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 info!("Initialization complete");
14 let mut led = Output::new(p.PIO1_6, Level::Low);
15
16 info!("Entering main loop");
17 loop {
18 info!("led off!");
19 led.set_high();
20 Timer::after_millis(500).await;
21
22 info!("led on!");
23 led.set_low();
24 Timer::after_millis(500).await;
25 }
26}
diff --git a/examples/lpc55s69/src/bin/usart_blocking.rs b/examples/lpc55s69/src/bin/usart_blocking.rs
new file mode 100644
index 000000000..a38ec0c5b
--- /dev/null
+++ b/examples/lpc55s69/src/bin/usart_blocking.rs
@@ -0,0 +1,40 @@
1#![no_std]
2#![no_main]
3
4use core::str::from_utf8_mut;
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_nxp::usart::{Config, Usart};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_halt as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_nxp::init(Default::default());
15 let mut usart = Usart::new_blocking(p.USART2, p.PIO0_27, p.PIO1_24, Config::default());
16 let tx_buf = b"Hello, Ferris!";
17 let mut rx_buf = [0u8; 14];
18
19 loop {
20 info!("Write a message");
21 usart.blocking_write(tx_buf).unwrap();
22 usart.blocking_flush().unwrap();
23
24 Timer::after_millis(500).await;
25
26 info!("Read a message");
27 usart.blocking_read(&mut rx_buf).unwrap();
28
29 match from_utf8_mut(&mut rx_buf) {
30 Ok(str) => {
31 info!("The message is: {}", str);
32 }
33 Err(_) => {
34 error!("Error in converting to UTF8");
35 }
36 }
37
38 Timer::after_millis(500).await;
39 }
40}
diff --git a/examples/mimxrt1011/.cargo/config.toml b/examples/mimxrt1011/.cargo/config.toml
new file mode 100644
index 000000000..12f4b27b2
--- /dev/null
+++ b/examples/mimxrt1011/.cargo/config.toml
@@ -0,0 +1,8 @@
1[target.thumbv7em-none-eabihf]
2runner = 'probe-rs run --chip MIMXRT1010'
3
4[build]
5target = "thumbv7em-none-eabihf" # Cortex-M7
6
7[env]
8DEFMT_LOG = "trace"
diff --git a/examples/mimxrt1011/Cargo.toml b/examples/mimxrt1011/Cargo.toml
new file mode 100644
index 000000000..488f3167b
--- /dev/null
+++ b/examples/mimxrt1011/Cargo.toml
@@ -0,0 +1,35 @@
1[package]
2name = "embassy-imxrt1011-examples"
3version = "0.1.0"
4edition = "2021"
5license = "MIT or Apache-2.0"
6publish = false
7
8[dependencies]
9cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
10cortex-m-rt = "0.7.3"
11defmt = "1.0.1"
12defmt-rtt = "1.0.0"
13
14embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1011", "unstable-pac", "time-driver-pit"] }
17embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime" # RT1011 hard faults currently with this enabled.
18embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
19embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
20embedded-hal-async = "1.0.0"
21
22imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1010"] }
23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24panic-semihosting = "0.6.0"
25
26[build-dependencies]
27imxrt-rt = { version = "0.1.7", features = ["device"] }
28
29[profile.release]
30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1011" }
35]
diff --git a/examples/mimxrt1011/build.rs b/examples/mimxrt1011/build.rs
new file mode 100644
index 000000000..99e172aba
--- /dev/null
+++ b/examples/mimxrt1011/build.rs
@@ -0,0 +1,14 @@
1use imxrt_rt::{Family, RuntimeBuilder};
2
3fn main() {
4 // The IMXRT1010-EVK technically has 128M of flash, but we only ever use 8MB so that the examples
5 // will build fine on the Adafruit Metro M7 boards.
6 RuntimeBuilder::from_flexspi(Family::Imxrt1010, 8 * 1024 * 1024)
7 .build()
8 .unwrap();
9
10 println!("cargo:rustc-link-arg-bins=--nmagic");
11 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
12 // Not link.x, as imxrt-rt needs to do some special things
13 println!("cargo:rustc-link-arg-bins=-Timxrt-link.x");
14}
diff --git a/examples/mimxrt1011/src/bin/blinky.rs b/examples/mimxrt1011/src/bin/blinky.rs
new file mode 100644
index 000000000..a5d5de6b3
--- /dev/null
+++ b/examples/mimxrt1011/src/bin/blinky.rs
@@ -0,0 +1,48 @@
1//! This example works on the following boards:
2//! - IMXRT1010-EVK
3//! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button
4//! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this)
5//!
6//! Although beware you will need to change the GPIO pins being used (scroll down).
7
8#![no_std]
9#![no_main]
10
11use defmt::info;
12use embassy_executor::Spawner;
13use embassy_nxp::gpio::{Level, Output};
14use embassy_time::Timer;
15// Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked.
16use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) -> ! {
20 let p = embassy_nxp::init(Default::default());
21 info!("Hello world!");
22
23 /* Pick the pins to use depending on your board. */
24
25 // IMXRT1010-EVK
26 //
27 // LED (D25)
28 let led = p.GPIO_11;
29
30 // Adafruit Metro M7 (both microSD and AirLift variants)
31 //
32 // The LED is connected to D13 on the board.
33 // let led = p.GPIO_03;
34
35 // Makerdiary iMX RT1011 Nano Kit
36 //
37 // LED0
38 // let led = p.GPIO_SD_04;
39
40 let mut led = Output::new(led, Level::Low);
41
42 loop {
43 Timer::after_millis(500).await;
44
45 info!("Toggle");
46 led.toggle();
47 }
48}
diff --git a/examples/mimxrt1011/src/bin/button.rs b/examples/mimxrt1011/src/bin/button.rs
new file mode 100644
index 000000000..e63d7171d
--- /dev/null
+++ b/examples/mimxrt1011/src/bin/button.rs
@@ -0,0 +1,62 @@
1//! This example works on the following boards:
2//! - IMXRT1010-EVK
3//! - Adafruit Metro M7 (with microSD or with AirLift), requires an external button
4//! - Makerdiary iMX RT1011 Nano Kit (TODO: currently untested, please change this)
5//!
6//! Although beware you will need to change the GPIO pins being used (scroll down).
7
8#![no_std]
9#![no_main]
10
11use defmt::info;
12use embassy_executor::Spawner;
13use embassy_nxp::gpio::{Input, Level, Output, Pull};
14// Must include `embassy_imxrt1011_examples` to ensure the FCB gets linked.
15use {defmt_rtt as _, embassy_imxrt1011_examples as _, panic_probe as _};
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 let p = embassy_nxp::init(Default::default());
20 info!("Hello world!");
21
22 /* Pick the pins to use depending on your board. */
23
24 // IMXRT1010-EVK
25 //
26 // LED (D25) and user button (SW4)
27 let (led, button) = (p.GPIO_11, p.GPIO_SD_05);
28
29 // Adafruit Metro M7 (both microSD and AirLift variants)
30 //
31 // The LED is connected to D13 on the board.
32 //
33 // In particular the Metro M7 has no board user buttons, so you will need to connect a button.
34 // Any other GPIO pin can be used. GPIO_04 is used for example since it is on pin D12.
35 // let (led, button) = (p.GPIO_03, p.GPIO_04);
36
37 // Makerdiary iMX RT1011 Nano Kit
38 //
39 // LED0 and user button.
40 // let (led, button) = (p.GPIO_SD_04, p.GPIO_SD_03);
41
42 let mut button = Input::new(button, Pull::Up100K);
43 let mut led = Output::new(led, Level::Low);
44 led.set_high();
45
46 loop {
47 button.wait_for_falling_edge().await;
48
49 info!("Toggled");
50 led.toggle();
51
52 // The RT1010EVK has a 100 nF debouncing capacitor which results in false positive events
53 // when listening for a falling edge in a loop, wait for the rising edge and then wait for
54 // stabilization.
55 button.wait_for_rising_edge().await;
56
57 // Stabilization.
58 for _ in 0..100_000 {
59 cortex_m::asm::nop();
60 }
61 }
62}
diff --git a/examples/mimxrt1011/src/lib.rs b/examples/mimxrt1011/src/lib.rs
new file mode 100644
index 000000000..f0391ef57
--- /dev/null
+++ b/examples/mimxrt1011/src/lib.rs
@@ -0,0 +1,75 @@
1//! FlexSPI configuration block (FCB) for iMXRT1011 boards.
2//!
3//! This is a generic FCB that should work with most QSPI flash.
4
5#![no_std]
6
7use imxrt_boot_gen::flexspi;
8use imxrt_boot_gen::flexspi::opcodes::sdr::*;
9use imxrt_boot_gen::flexspi::{
10 ColumnAddressWidth, Command, DeviceModeConfiguration, FlashPadType, Instr, LookupTable, Pads,
11 ReadSampleClockSource, Sequence, SequenceBuilder, SerialClockFrequency, SerialFlashRegion,
12 WaitTimeConfigurationCommands,
13};
14use imxrt_boot_gen::serial_flash::nor;
15
16/// While the IMXRT1010-EVK and Makerdiary iMX RT1011 Nano Kit have 128MBit of flash we limit to 64Mbit
17/// to allow the Metro M7 boards to use the same FCB configuration.
18const DENSITY_BITS: u32 = 64 * 1024 * 1024;
19const DENSITY_BYTES: u32 = DENSITY_BITS / 8;
20
21const SEQ_READ: Sequence = SequenceBuilder::new()
22 .instr(Instr::new(CMD, Pads::One, 0xEB))
23 .instr(Instr::new(RADDR, Pads::Four, 0x18))
24 .instr(Instr::new(DUMMY, Pads::Four, 0x06))
25 .instr(Instr::new(READ, Pads::Four, 0x04))
26 .build();
27
28const SEQ_READ_STATUS: Sequence = SequenceBuilder::new()
29 .instr(Instr::new(CMD, Pads::One, 0x05))
30 .instr(Instr::new(READ, Pads::One, 0x01))
31 .build();
32
33const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build();
34
35const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new()
36 .instr(Instr::new(CMD, Pads::One, 0x20))
37 .instr(Instr::new(RADDR, Pads::One, 0x18))
38 .build();
39
40const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new()
41 .instr(Instr::new(CMD, Pads::One, 0x02))
42 .instr(Instr::new(RADDR, Pads::One, 0x18))
43 .instr(Instr::new(WRITE, Pads::One, 0x04))
44 .build();
45
46const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build();
47
48const LUT: LookupTable = LookupTable::new()
49 .command(Command::Read, SEQ_READ)
50 .command(Command::ReadStatus, SEQ_READ_STATUS)
51 .command(Command::WriteEnable, SEQ_WRITE_ENABLE)
52 .command(Command::EraseSector, SEQ_ERASE_SECTOR)
53 .command(Command::PageProgram, SEQ_PAGE_PROGRAM)
54 .command(Command::ChipErase, SEQ_CHIP_ERASE);
55
56const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT)
57 .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad)
58 .cs_hold_time(0x03)
59 .cs_setup_time(0x03)
60 .column_address_width(ColumnAddressWidth::OtherDevices)
61 .device_mode_configuration(DeviceModeConfiguration::Disabled)
62 .wait_time_cfg_commands(WaitTimeConfigurationCommands::disable())
63 .flash_size(SerialFlashRegion::A1, DENSITY_BYTES)
64 .serial_clk_freq(SerialClockFrequency::MHz120)
65 .serial_flash_pad_type(FlashPadType::Quad);
66
67pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock =
68 nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK)
69 .page_size(256)
70 .sector_size(4096)
71 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30);
72
73#[unsafe(no_mangle)]
74#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")]
75pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;
diff --git a/examples/mimxrt1062-evk/.cargo/config.toml b/examples/mimxrt1062-evk/.cargo/config.toml
new file mode 100644
index 000000000..ca4c606dc
--- /dev/null
+++ b/examples/mimxrt1062-evk/.cargo/config.toml
@@ -0,0 +1,8 @@
1[target.thumbv7em-none-eabihf]
2runner = 'probe-rs run --chip MIMXRT1060'
3
4[build]
5target = "thumbv7em-none-eabihf" # Cortex-M7
6
7[env]
8DEFMT_LOG = "trace"
diff --git a/examples/mimxrt1062-evk/Cargo.toml b/examples/mimxrt1062-evk/Cargo.toml
new file mode 100644
index 000000000..ec6c5c872
--- /dev/null
+++ b/examples/mimxrt1062-evk/Cargo.toml
@@ -0,0 +1,35 @@
1[package]
2name = "embassy-imxrt1062-evk-examples"
3version = "0.1.0"
4edition = "2021"
5license = "MIT or Apache-2.0"
6publish = false
7
8[dependencies]
9cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
10cortex-m-rt = "0.7.3"
11defmt = "1.0.1"
12defmt-rtt = "1.0.0"
13
14embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["defmt", "mimxrt1062", "unstable-pac", "time-driver-pit"] }
17embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", ] } # "defmt-timestamp-uptime"
18embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
19embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
20embedded-hal-async = "1.0.0"
21
22imxrt-boot-gen = { version = "0.3.4", features = ["imxrt1060"] }
23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24panic-semihosting = "0.6.0"
25
26[build-dependencies]
27imxrt-rt = { version = "0.1.7", features = ["device"] }
28
29[profile.release]
30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv7em-none-eabihf", artifact-dir = "out/examples/mimxrt1062-evk" }
35]
diff --git a/examples/mimxrt1062-evk/build.rs b/examples/mimxrt1062-evk/build.rs
new file mode 100644
index 000000000..e0e0d547e
--- /dev/null
+++ b/examples/mimxrt1062-evk/build.rs
@@ -0,0 +1,12 @@
1use imxrt_rt::{Family, RuntimeBuilder};
2
3fn main() {
4 RuntimeBuilder::from_flexspi(Family::Imxrt1060, 8 * 1024 * 1024)
5 .build()
6 .unwrap();
7
8 println!("cargo:rustc-link-arg-bins=--nmagic");
9 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
10 // Not link.x, as imxrt-rt needs to do some special things
11 println!("cargo:rustc-link-arg-bins=-Timxrt-link.x");
12}
diff --git a/examples/mimxrt1062-evk/src/bin/blinky.rs b/examples/mimxrt1062-evk/src/bin/blinky.rs
new file mode 100644
index 000000000..b6d90d94d
--- /dev/null
+++ b/examples/mimxrt1062-evk/src/bin/blinky.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nxp::gpio::{Level, Output};
7use embassy_time::Timer;
8// Must include `embassy_imxrt1062_evk_examples` to ensure the FCB gets linked.
9use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) -> ! {
13 let p = embassy_nxp::init(Default::default());
14 info!("Hello world!");
15
16 let led = p.GPIO_AD_B0_08;
17 let mut led = Output::new(led, Level::Low);
18
19 loop {
20 Timer::after_millis(500).await;
21
22 info!("Toggle");
23 led.toggle();
24 }
25}
diff --git a/examples/mimxrt1062-evk/src/bin/button.rs b/examples/mimxrt1062-evk/src/bin/button.rs
new file mode 100644
index 000000000..d60fa3dac
--- /dev/null
+++ b/examples/mimxrt1062-evk/src/bin/button.rs
@@ -0,0 +1,36 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nxp::gpio::{Input, Level, Output, Pull};
7use {defmt_rtt as _, embassy_imxrt1062_evk_examples as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) -> ! {
11 let p = embassy_nxp::init(Default::default());
12 info!("Hello world!");
13
14 // User LED (D8)
15 let led = p.GPIO_AD_B0_08;
16 // User button (SW5)
17 let button = p.WAKEUP;
18 let mut button = Input::new(button, Pull::Up100K);
19 let mut led = Output::new(led, Level::Low);
20 led.set_high();
21
22 loop {
23 button.wait_for_falling_edge().await;
24
25 info!("Toggled");
26 led.toggle();
27
28 // Software debounce.
29 button.wait_for_rising_edge().await;
30
31 // Stabilization.
32 for _ in 0..100_000 {
33 cortex_m::asm::nop();
34 }
35 }
36}
diff --git a/examples/mimxrt1062-evk/src/lib.rs b/examples/mimxrt1062-evk/src/lib.rs
new file mode 100644
index 000000000..3f99f9db3
--- /dev/null
+++ b/examples/mimxrt1062-evk/src/lib.rs
@@ -0,0 +1,60 @@
1//! FlexSPI configuration block (FCB) for the iMXRT1060-EVK
2//!
3//! This uses IS25WP QuadSPI flash.
4
5#![no_std]
6
7use imxrt_boot_gen::flexspi::opcodes::sdr::*;
8use imxrt_boot_gen::flexspi::{self, FlashPadType, ReadSampleClockSource, SerialClockFrequency, SerialFlashRegion, *};
9use imxrt_boot_gen::serial_flash::*;
10pub use nor::ConfigurationBlock;
11
12const SEQ_READ: Sequence = SequenceBuilder::new()
13 .instr(Instr::new(CMD, Pads::One, 0xEB))
14 .instr(Instr::new(RADDR, Pads::Four, 0x18))
15 .instr(Instr::new(DUMMY, Pads::Four, 0x06))
16 .instr(Instr::new(READ, Pads::Four, 0x04))
17 .build();
18const SEQ_READ_STATUS: Sequence = SequenceBuilder::new()
19 .instr(Instr::new(CMD, Pads::One, 0x05))
20 .instr(Instr::new(READ, Pads::One, 0x04))
21 .build();
22const SEQ_WRITE_ENABLE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x06)).build();
23const SEQ_ERASE_SECTOR: Sequence = SequenceBuilder::new()
24 .instr(Instr::new(CMD, Pads::One, 0x20))
25 .instr(Instr::new(RADDR, Pads::One, 0x18))
26 .build();
27const SEQ_PAGE_PROGRAM: Sequence = SequenceBuilder::new()
28 .instr(Instr::new(CMD, Pads::One, 0x02))
29 .instr(Instr::new(RADDR, Pads::One, 0x18))
30 .instr(Instr::new(WRITE, Pads::One, 0x04))
31 .build();
32const SEQ_CHIP_ERASE: Sequence = SequenceBuilder::new().instr(Instr::new(CMD, Pads::One, 0x60)).build();
33
34const LUT: LookupTable = LookupTable::new()
35 .command(Command::Read, SEQ_READ)
36 .command(Command::ReadStatus, SEQ_READ_STATUS)
37 .command(Command::WriteEnable, SEQ_WRITE_ENABLE)
38 .command(Command::EraseSector, SEQ_ERASE_SECTOR)
39 .command(Command::PageProgram, SEQ_PAGE_PROGRAM)
40 .command(Command::ChipErase, SEQ_CHIP_ERASE);
41
42const COMMON_CONFIGURATION_BLOCK: flexspi::ConfigurationBlock = flexspi::ConfigurationBlock::new(LUT)
43 .version(Version::new(1, 4, 0))
44 .read_sample_clk_src(ReadSampleClockSource::LoopbackFromDQSPad)
45 .cs_hold_time(3)
46 .cs_setup_time(3)
47 .controller_misc_options(0x10)
48 .serial_flash_pad_type(FlashPadType::Quad)
49 .serial_clk_freq(SerialClockFrequency::MHz133)
50 .flash_size(SerialFlashRegion::A1, 8 * 1024 * 1024);
51
52pub const SERIAL_NOR_CONFIGURATION_BLOCK: nor::ConfigurationBlock =
53 nor::ConfigurationBlock::new(COMMON_CONFIGURATION_BLOCK)
54 .page_size(256)
55 .sector_size(4096)
56 .ip_cmd_serial_clk_freq(nor::SerialClockFrequency::MHz30);
57
58#[no_mangle]
59#[cfg_attr(all(target_arch = "arm", target_os = "none"), link_section = ".fcb")]
60pub static FLEXSPI_CONFIGURATION_BLOCK: nor::ConfigurationBlock = SERIAL_NOR_CONFIGURATION_BLOCK;
diff --git a/examples/mimxrt6/Cargo.toml b/examples/mimxrt6/Cargo.toml
index b0c56f003..28de9d273 100644
--- a/examples/mimxrt6/Cargo.toml
+++ b/examples/mimxrt6/Cargo.toml
@@ -3,24 +3,24 @@ name = "embassy-imxrt-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5license = "MIT or Apache-2.0" 5license = "MIT or Apache-2.0"
6publish = false
6 7
7[dependencies] 8[dependencies]
8cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } 9cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
9cortex-m-rt = "0.7.3" 10cortex-m-rt = "0.7.3"
10defmt = "1.0" 11defmt = "1.0.1"
11defmt-rtt = "1.0" 12defmt-rtt = "1.0.0"
12 13
13embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 14embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
14embassy-futures = { version = "0.1.1", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] } 16embassy-imxrt = { version = "0.1.0", path = "../../embassy-imxrt", features = ["defmt", "mimxrt685s", "unstable-pac", "time", "time-driver-os-timer"] }
16embassy-time = { version = "0.4", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 17embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
17embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 18embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
18embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 19embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
19embedded-hal-async = "1.0.0" 20embedded-hal-async = "1.0.0"
20 21
21mimxrt600-fcb = "0.2.2" 22mimxrt600-fcb = "0.2.2"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23rand = { version = "0.8.5", default-features = false }
24 24
25# cargo build/run 25# cargo build/run
26[profile.dev] 26[profile.dev]
@@ -59,3 +59,8 @@ incremental = false
59lto = 'fat' 59lto = 'fat'
60opt-level = 3 # <- 60opt-level = 3 # <-
61overflow-checks = false # <- 61overflow-checks = false # <-
62
63[package.metadata.embassy]
64build = [
65 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/mimxrt6" }
66]
diff --git a/examples/mimxrt6/src/bin/button.rs b/examples/mimxrt6/src/bin/button.rs
new file mode 100644
index 000000000..efb7f14af
--- /dev/null
+++ b/examples/mimxrt6/src/bin/button.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_futures::select::{select, Either};
7use embassy_imxrt::gpio;
8use {defmt_rtt as _, embassy_imxrt_examples as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_imxrt::init(Default::default());
13
14 let mut user1 = gpio::Input::new(p.PIO1_1, gpio::Pull::None, gpio::Inverter::Disabled);
15 let mut user2 = gpio::Input::new(p.PIO0_10, gpio::Pull::None, gpio::Inverter::Disabled);
16
17 loop {
18 let res = select(user1.wait_for_falling_edge(), user2.wait_for_falling_edge()).await;
19
20 match res {
21 Either::First(()) => {
22 info!("Button `USER1' pressed");
23 }
24 Either::Second(()) => {
25 info!("Button `USER2' pressed");
26 }
27 }
28 }
29}
diff --git a/examples/mimxrt6/src/bin/crc.rs b/examples/mimxrt6/src/bin/crc.rs
new file mode 100644
index 000000000..005a250e5
--- /dev/null
+++ b/examples/mimxrt6/src/bin/crc.rs
@@ -0,0 +1,175 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_imxrt::crc::{Config, Crc, Polynomial};
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut p = embassy_imxrt::init(Default::default());
14 let data = b"123456789";
15
16 info!("Initializing CRC");
17
18 // CRC-CCITT
19 let mut crc = Crc::new(p.CRC.reborrow(), Default::default());
20 let output = crc.feed_bytes(data);
21 defmt::assert_eq!(output, 0x29b1);
22
23 // CRC16-ARC
24 let mut crc = Crc::new(
25 p.CRC.reborrow(),
26 Config {
27 polynomial: Polynomial::Crc16,
28 reverse_in: true,
29 reverse_out: true,
30 complement_out: false,
31 seed: 0,
32 ..Default::default()
33 },
34 );
35 let output = crc.feed_bytes(data);
36 defmt::assert_eq!(output, 0xbb3d);
37
38 // CRC16-CMS
39 let mut crc = Crc::new(
40 p.CRC.reborrow(),
41 Config {
42 polynomial: Polynomial::Crc16,
43 reverse_in: false,
44 reverse_out: false,
45 complement_out: false,
46 seed: 0xffff,
47 ..Default::default()
48 },
49 );
50 let output = crc.feed_bytes(data);
51 defmt::assert_eq!(output, 0xaee7);
52
53 // CRC16-DDS-110
54 let mut crc = Crc::new(
55 p.CRC.reborrow(),
56 Config {
57 polynomial: Polynomial::Crc16,
58 reverse_in: false,
59 reverse_out: false,
60 complement_out: false,
61 seed: 0x800d,
62 ..Default::default()
63 },
64 );
65 let output = crc.feed_bytes(data);
66 defmt::assert_eq!(output, 0x9ecf);
67
68 // CRC16-MAXIM-DOW
69 let mut crc = Crc::new(
70 p.CRC.reborrow(),
71 Config {
72 polynomial: Polynomial::Crc16,
73 reverse_in: true,
74 reverse_out: true,
75 complement_out: true,
76 seed: 0,
77 ..Default::default()
78 },
79 );
80 let output = crc.feed_bytes(data);
81 defmt::assert_eq!(output, 0x44c2);
82
83 // CRC16-MODBUS
84 let mut crc = Crc::new(
85 p.CRC.reborrow(),
86 Config {
87 polynomial: Polynomial::Crc16,
88 reverse_in: true,
89 reverse_out: true,
90 complement_out: false,
91 seed: 0xffff,
92 ..Default::default()
93 },
94 );
95 let output = crc.feed_bytes(data);
96 defmt::assert_eq!(output, 0x4b37);
97
98 // CRC32-BZIP2
99 let mut crc = Crc::new(
100 p.CRC.reborrow(),
101 Config {
102 polynomial: Polynomial::Crc32,
103 reverse_in: false,
104 reverse_out: false,
105 complement_out: true,
106 seed: 0xffff_ffff,
107 ..Default::default()
108 },
109 );
110 let output = crc.feed_bytes(data);
111 defmt::assert_eq!(output, 0xfc89_1918);
112
113 // CRC32-CKSUM
114 let mut crc = Crc::new(
115 p.CRC.reborrow(),
116 Config {
117 polynomial: Polynomial::Crc32,
118 reverse_in: false,
119 reverse_out: false,
120 complement_out: true,
121 seed: 0,
122 ..Default::default()
123 },
124 );
125 let output = crc.feed_bytes(data);
126 defmt::assert_eq!(output, 0x765e_7680);
127
128 // CRC32-ISO-HDLC
129 let mut crc = Crc::new(
130 p.CRC.reborrow(),
131 Config {
132 polynomial: Polynomial::Crc32,
133 reverse_in: true,
134 reverse_out: true,
135 complement_out: true,
136 seed: 0xffff_ffff,
137 ..Default::default()
138 },
139 );
140 let output = crc.feed_bytes(data);
141 defmt::assert_eq!(output, 0xcbf4_3926);
142
143 // CRC32-JAMCRC
144 let mut crc = Crc::new(
145 p.CRC.reborrow(),
146 Config {
147 polynomial: Polynomial::Crc32,
148 reverse_in: true,
149 reverse_out: true,
150 complement_out: false,
151 seed: 0xffff_ffff,
152 ..Default::default()
153 },
154 );
155 let output = crc.feed_bytes(data);
156 defmt::assert_eq!(output, 0x340b_c6d9);
157
158 // CRC32-MPEG-2
159 let mut crc = Crc::new(
160 p.CRC.reborrow(),
161 Config {
162 polynomial: Polynomial::Crc32,
163 reverse_in: false,
164 reverse_out: false,
165 complement_out: false,
166 seed: 0xffff_ffff,
167 ..Default::default()
168 },
169 );
170 let output = crc.feed_bytes(data);
171 defmt::assert_eq!(output, 0x0376_e6e7);
172
173 info!("end program");
174 cortex_m::asm::bkpt();
175}
diff --git a/examples/mimxrt6/src/bin/rng.rs b/examples/mimxrt6/src/bin/rng.rs
new file mode 100644
index 000000000..9468dd109
--- /dev/null
+++ b/examples/mimxrt6/src/bin/rng.rs
@@ -0,0 +1,39 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_imxrt::rng::Rng;
9use embassy_imxrt::{bind_interrupts, peripherals, rng};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 RNG => rng::InterruptHandler<peripherals::RNG>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_imxrt::init(Default::default());
19
20 info!("Initializing RNG");
21 let mut rng = Rng::new(p.RNG, Irqs);
22 let mut buf = [0u8; 65];
23
24 // Async interface
25 unwrap!(rng.async_fill_bytes(&mut buf).await);
26 info!("random bytes: {:02x}", buf);
27
28 // RngCore interface
29 let mut random_bytes = [0; 16];
30
31 let random_u32 = rng.blocking_next_u32();
32 let random_u64 = rng.blocking_next_u64();
33
34 rng.blocking_fill_bytes(&mut random_bytes);
35
36 info!("random_u32 {}", random_u32);
37 info!("random_u64 {}", random_u64);
38 info!("random_bytes {}", random_bytes);
39}
diff --git a/examples/mimxrt6/src/bin/uart-async.rs b/examples/mimxrt6/src/bin/uart-async.rs
new file mode 100644
index 000000000..d808d755c
--- /dev/null
+++ b/examples/mimxrt6/src/bin/uart-async.rs
@@ -0,0 +1,87 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::info;
7use embassy_executor::Spawner;
8use embassy_imxrt::flexcomm::uart::{self, Async, Uart};
9use embassy_imxrt::{bind_interrupts, peripherals};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _};
12
13bind_interrupts!(struct Irqs {
14 FLEXCOMM2 => uart::InterruptHandler<peripherals::FLEXCOMM2>;
15 FLEXCOMM4 => uart::InterruptHandler<peripherals::FLEXCOMM4>;
16});
17
18const BUFLEN: usize = 16;
19
20#[embassy_executor::task]
21async fn usart4_task(mut uart: Uart<'static, Async>) {
22 info!("RX Task");
23
24 loop {
25 let mut rx_buf = [0; BUFLEN];
26 uart.read(&mut rx_buf).await.unwrap();
27 info!("usart4: rx_buf {:02x}", rx_buf);
28
29 Timer::after_millis(10).await;
30
31 let tx_buf = [0xaa; BUFLEN];
32 uart.write(&tx_buf).await.unwrap();
33 info!("usart4: tx_buf {:02x}", tx_buf);
34 }
35}
36
37#[embassy_executor::task]
38async fn usart2_task(mut uart: Uart<'static, Async>) {
39 info!("TX Task");
40
41 loop {
42 let tx_buf = [0x55; BUFLEN];
43 uart.write(&tx_buf).await.unwrap();
44 info!("usart2: tx_buf {:02x}", tx_buf);
45
46 Timer::after_millis(10).await;
47
48 let mut rx_buf = [0x00; BUFLEN];
49 uart.read(&mut rx_buf).await.unwrap();
50 info!("usart2: rx_buf {:02x}", rx_buf);
51 }
52}
53
54#[embassy_executor::main]
55async fn main(spawner: Spawner) {
56 let p = embassy_imxrt::init(Default::default());
57
58 info!("UART test start");
59
60 let usart4 = Uart::new_with_rtscts(
61 p.FLEXCOMM4,
62 p.PIO0_29,
63 p.PIO0_30,
64 p.PIO1_0,
65 p.PIO0_31,
66 Irqs,
67 p.DMA0_CH9,
68 p.DMA0_CH8,
69 Default::default(),
70 )
71 .unwrap();
72 spawner.spawn(usart4_task(usart4).unwrap());
73
74 let usart2 = Uart::new_with_rtscts(
75 p.FLEXCOMM2,
76 p.PIO0_15,
77 p.PIO0_16,
78 p.PIO0_18,
79 p.PIO0_17,
80 Irqs,
81 p.DMA0_CH5,
82 p.DMA0_CH4,
83 Default::default(),
84 )
85 .unwrap();
86 spawner.spawn(usart2_task(usart2).unwrap());
87}
diff --git a/examples/mimxrt6/src/bin/uart.rs b/examples/mimxrt6/src/bin/uart.rs
new file mode 100644
index 000000000..1636c958f
--- /dev/null
+++ b/examples/mimxrt6/src/bin/uart.rs
@@ -0,0 +1,55 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::info;
7use embassy_executor::Spawner;
8use embassy_imxrt::flexcomm::uart::{Blocking, Uart, UartRx, UartTx};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::task]
13async fn usart4_task(mut uart: UartRx<'static, Blocking>) {
14 info!("RX Task");
15
16 loop {
17 let mut buf = [0; 8];
18
19 Timer::after_millis(10).await;
20
21 uart.blocking_read(&mut buf).unwrap();
22
23 let s = core::str::from_utf8(&buf).unwrap();
24
25 info!("Received '{}'", s);
26 }
27}
28
29#[embassy_executor::task]
30async fn usart2_task(mut uart: UartTx<'static, Blocking>) {
31 info!("TX Task");
32
33 loop {
34 let buf = "Testing\0".as_bytes();
35
36 uart.blocking_write(buf).unwrap();
37
38 Timer::after_millis(10).await;
39 }
40}
41
42#[embassy_executor::main]
43async fn main(spawner: Spawner) {
44 let p = embassy_imxrt::init(Default::default());
45
46 info!("UART test start");
47
48 let usart4 = Uart::new_blocking(p.FLEXCOMM4, p.PIO0_29, p.PIO0_30, Default::default()).unwrap();
49
50 let (_, usart4) = usart4.split();
51 spawner.spawn(usart4_task(usart4).unwrap());
52
53 let usart2 = UartTx::new_blocking(p.FLEXCOMM2, p.PIO0_15, Default::default()).unwrap();
54 spawner.spawn(usart2_task(usart2).unwrap());
55}
diff --git a/examples/mspm0c1104/Cargo.toml b/examples/mspm0c1104/Cargo.toml
index ba64a578d..21434106a 100644
--- a/examples/mspm0c1104/Cargo.toml
+++ b/examples/mspm0c1104/Cargo.toml
@@ -3,18 +3,19 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c110x", "defmt", "rt", "time-driver-any"] } 9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0c1104dgs20", "defmt", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0" 13panic-halt = "1.0.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"} 15cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
19 20
20# The chip only has 1KB of ram, so we must optimize binaries regardless 21# The chip only has 1KB of ram, so we must optimize binaries regardless
@@ -30,3 +31,8 @@ debug = 0
30opt-level = "z" 31opt-level = "z"
31lto = true 32lto = true
32codegen-units = 1 33codegen-units = 1
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0c1104", env = { DEFMT_RTT_BUFFER_SIZE = "72" }}
38]
diff --git a/examples/mspm0c1104/README.md b/examples/mspm0c1104/README.md
index e5c9f961d..86b6c3918 100644
--- a/examples/mspm0c1104/README.md
+++ b/examples/mspm0c1104/README.md
@@ -1,4 +1,4 @@
1# Examples for MSPM0C110x family 1# Examples for MSPM0C1104
2 2
3Run individual examples with 3Run individual examples with
4``` 4```
@@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0C1104](https://www.t
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. 15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16 16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip) 17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for C1104 it should be `probe-rs run --chip MSPM0C1104`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for C1104 it should be `mspm0c1104`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. 18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0C1104 it should be `mspm0c1104dgs20`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. 19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic 20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21 21
diff --git a/examples/mspm0c1104/build.rs b/examples/mspm0c1104/build.rs
index 30691aa97..2d777c2d3 100644
--- a/examples/mspm0c1104/build.rs
+++ b/examples/mspm0c1104/build.rs
@@ -32,4 +32,6 @@ fn main() {
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
35} 37}
diff --git a/examples/mspm0c1104/src/bin/wwdt.rs b/examples/mspm0c1104/src/bin/wwdt.rs
new file mode 100644
index 000000000..2859ccd5e
--- /dev/null
+++ b/examples/mspm0c1104/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0C1104 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/mspm0g3507/.cargo/config.toml b/examples/mspm0g3507/.cargo/config.toml
index 34c720cdd..e711afaf2 100644
--- a/examples/mspm0g3507/.cargo/config.toml
+++ b/examples/mspm0g3507/.cargo/config.toml
@@ -6,4 +6,4 @@ runner = "probe-rs run --chip MSPM0G3507 --protocol=swd"
6target = "thumbv6m-none-eabi" 6target = "thumbv6m-none-eabi"
7 7
8[env] 8[env]
9DEFMT_LOG = "debug" 9DEFMT_LOG = "trace"
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml
index f6fed091d..616b82adb 100644
--- a/examples/mspm0g3507/Cargo.toml
+++ b/examples/mspm0g3507/Cargo.toml
@@ -3,19 +3,27 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g350x", "defmt", "rt", "time-driver-any"] } 9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3507pm", "defmt", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0" 13panic-halt = "1.0.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"} 15cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
19 20
21embedded-io-async = "0.6.1"
22
20[profile.release] 23[profile.release]
21debug = 2 24debug = 2
25
26[package.metadata.embassy]
27build = [
28 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3507" }
29]
diff --git a/examples/mspm0g3507/README.md b/examples/mspm0g3507/README.md
index 5e8a83212..be91dc5a0 100644
--- a/examples/mspm0g3507/README.md
+++ b/examples/mspm0g3507/README.md
@@ -1,4 +1,4 @@
1# Examples for MSPM0C350x family 1# Examples for MSPM0M3507
2 2
3Run individual examples with 3Run individual examples with
4``` 4```
@@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3507](https://www.t
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. 15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16 16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip) 17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3507 it should be `probe-rs run --chip MSPM0G3507`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3507 it should be `mspm0g3507`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. 18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3507 it should be `mspm0g3507pm`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. 19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic 20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21 21
diff --git a/examples/mspm0g3507/build.rs b/examples/mspm0g3507/build.rs
index 30691aa97..2d777c2d3 100644
--- a/examples/mspm0g3507/build.rs
+++ b/examples/mspm0g3507/build.rs
@@ -32,4 +32,6 @@ fn main() {
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
35} 37}
diff --git a/examples/mspm0g3507/src/bin/i2c.rs b/examples/mspm0g3507/src/bin/i2c.rs
new file mode 100644
index 000000000..8d1ed1726
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/i2c.rs
@@ -0,0 +1,45 @@
1//! This example uses FIFO with polling, and the maximum FIFO size is 8.
2//! Refer to async example to handle larger packets.
3//!
4//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board.
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_mspm0::i2c::{Config, I2c};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15const ADDRESS: u8 = 0x6a;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 let p = embassy_mspm0::init(Default::default());
20
21 let instance = p.I2C1;
22 let scl = p.PB2;
23 let sda = p.PB3;
24
25 let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default()));
26
27 let mut pot_value: u8 = 0;
28
29 loop {
30 let to_write = [0u8, pot_value];
31
32 match i2c.blocking_write(ADDRESS, &to_write) {
33 Ok(()) => info!("New potentioemter value: {}", pot_value),
34 Err(e) => error!("I2c Error: {:?}", e),
35 }
36
37 pot_value += 1;
38 // if reached 64th position (max)
39 // start over from lowest value
40 if pot_value == 64 {
41 pot_value = 0;
42 }
43 Timer::after_millis(500).await;
44 }
45}
diff --git a/examples/mspm0g3507/src/bin/i2c_async.rs b/examples/mspm0g3507/src/bin/i2c_async.rs
new file mode 100644
index 000000000..d486e2a03
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/i2c_async.rs
@@ -0,0 +1,50 @@
1//! The example uses FIFO and interrupts, wrapped in async API.
2//!
3//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0G3507 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::bind_interrupts;
11use embassy_mspm0::i2c::{Config, I2c, InterruptHandler};
12use embassy_mspm0::peripherals::I2C1;
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_halt as _};
15
16const ADDRESS: u8 = 0x6a;
17
18bind_interrupts!(struct Irqs {
19 I2C1 => InterruptHandler<I2C1>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) -> ! {
24 let p = embassy_mspm0::init(Default::default());
25
26 let instance = p.I2C1;
27 let scl = p.PB2;
28 let sda = p.PB3;
29
30 let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default()));
31
32 let mut pot_value: u8 = 0;
33
34 loop {
35 let to_write = [0u8, pot_value];
36
37 match i2c.async_write(ADDRESS, &to_write).await {
38 Ok(()) => info!("New potentioemter value: {}", pot_value),
39 Err(e) => error!("I2c Error: {:?}", e),
40 }
41
42 pot_value += 1;
43 // if reached 64th position (max)
44 // start over from lowest value
45 if pot_value == 64 {
46 pot_value = 0;
47 }
48 Timer::after_millis(500).await;
49 }
50}
diff --git a/examples/mspm0g3507/src/bin/wwdt.rs b/examples/mspm0g3507/src/bin/wwdt.rs
new file mode 100644
index 000000000..d10451448
--- /dev/null
+++ b/examples/mspm0g3507/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0G3507 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/mspm0g3519/Cargo.toml b/examples/mspm0g3519/Cargo.toml
index 1662e1f8d..ae699d6f4 100644
--- a/examples/mspm0g3519/Cargo.toml
+++ b/examples/mspm0g3519/Cargo.toml
@@ -3,19 +3,25 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g351x", "defmt", "rt", "time-driver-any"] } 9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0g3519pz", "defmt", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0" 13panic-halt = "1.0.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"} 15cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
19 20
20[profile.release] 21[profile.release]
21debug = 2 22debug = 2
23
24[package.metadata.embassy]
25build = [
26 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0g3519" }
27]
diff --git a/examples/mspm0g3519/README.md b/examples/mspm0g3519/README.md
index 5034b1913..c392c9e25 100644
--- a/examples/mspm0g3519/README.md
+++ b/examples/mspm0g3519/README.md
@@ -1,4 +1,4 @@
1# Examples for MSPM0G351x family 1# Examples for MSPM0G3519
2 2
3Run individual examples with 3Run individual examples with
4``` 4```
@@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0G3519](https://www.t
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. 15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16 16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip) 17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for G3519 it should be `probe-rs run --chip MSPM0G3519`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for G3519 it should be `mspm0g3519`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. 18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0G3519 it should be `mspm0g3519pz`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. 19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic 20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21 21
diff --git a/examples/mspm0g3519/build.rs b/examples/mspm0g3519/build.rs
index 30691aa97..2d777c2d3 100644
--- a/examples/mspm0g3519/build.rs
+++ b/examples/mspm0g3519/build.rs
@@ -32,4 +32,6 @@ fn main() {
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
35} 37}
diff --git a/examples/mspm0g3519/src/bin/wwdt.rs b/examples/mspm0g3519/src/bin/wwdt.rs
new file mode 100644
index 000000000..fede95fa2
--- /dev/null
+++ b/examples/mspm0g3519/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0G3519 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/mspm0l1306/Cargo.toml b/examples/mspm0l1306/Cargo.toml
index 609b3f205..8100e11da 100644
--- a/examples/mspm0l1306/Cargo.toml
+++ b/examples/mspm0l1306/Cargo.toml
@@ -3,19 +3,29 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l130x", "defmt", "rt", "time-driver-any"] } 9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l1306rhb", "defmt", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0" 13panic-halt = "1.0.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"} 15cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
19 20
20[profile.release] 21[profile.release]
21debug = 2 22debug = 2
23
24[profile.dev]
25debug = 2
26opt-level = 2
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l1306" }
31]
diff --git a/examples/mspm0l1306/README.md b/examples/mspm0l1306/README.md
index 5a55d721e..4d698e0fa 100644
--- a/examples/mspm0l1306/README.md
+++ b/examples/mspm0l1306/README.md
@@ -1,4 +1,4 @@
1# Examples for MSPM0L130x family 1# Examples for MSPM0L1306
2 2
3Run individual examples with 3Run individual examples with
4``` 4```
@@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L1306](https://www.t
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. 15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16 16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip) 17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L1306 it should be `probe-rs run --chip MSPM0L1306`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L1306 it should be `mspm0l1306`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. 18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For the LP-MSPM0L1306 it should be `mspm0l1306rhb`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. 19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic 20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21 21
diff --git a/examples/mspm0l1306/build.rs b/examples/mspm0l1306/build.rs
index 30691aa97..2d777c2d3 100644
--- a/examples/mspm0l1306/build.rs
+++ b/examples/mspm0l1306/build.rs
@@ -32,4 +32,6 @@ fn main() {
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
35} 37}
diff --git a/examples/mspm0l1306/src/bin/i2c.rs b/examples/mspm0l1306/src/bin/i2c.rs
new file mode 100644
index 000000000..e8801c485
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c.rs
@@ -0,0 +1,45 @@
1//! This example uses FIFO with polling, and the maximum FIFO size is 8.
2//! Refer to async example to handle larger packets.
3//!
4//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_mspm0::i2c::{Config, I2c};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15const ADDRESS: u8 = 0x2c;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 let p = embassy_mspm0::init(Default::default());
20
21 let instance = p.I2C0;
22 let scl = p.PA1;
23 let sda = p.PA0;
24
25 let mut i2c = unwrap!(I2c::new_blocking(instance, scl, sda, Config::default()));
26
27 let mut pot_value: u8 = 0;
28
29 loop {
30 let to_write = [0u8, pot_value];
31
32 match i2c.blocking_write(ADDRESS, &to_write) {
33 Ok(()) => info!("New potentioemter value: {}", pot_value),
34 Err(e) => error!("I2c Error: {:?}", e),
35 }
36
37 pot_value += 1;
38 // if reached 64th position (max)
39 // start over from lowest value
40 if pot_value == 64 {
41 pot_value = 0;
42 }
43 Timer::after_millis(500).await;
44 }
45}
diff --git a/examples/mspm0l1306/src/bin/i2c_async.rs b/examples/mspm0l1306/src/bin/i2c_async.rs
new file mode 100644
index 000000000..c4a6938ff
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/i2c_async.rs
@@ -0,0 +1,50 @@
1//! The example uses FIFO and interrupts, wrapped in async API.
2//!
3//! This example controls AD5171 digital potentiometer via I2C with the LP-MSPM0L1306 board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::bind_interrupts;
11use embassy_mspm0::i2c::{Config, I2c, InterruptHandler};
12use embassy_mspm0::peripherals::I2C0;
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_halt as _};
15
16const ADDRESS: u8 = 0x6a;
17
18bind_interrupts!(struct Irqs {
19 I2C0 => InterruptHandler<I2C0>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) -> ! {
24 let p = embassy_mspm0::init(Default::default());
25
26 let instance = p.I2C0;
27 let scl = p.PA1;
28 let sda = p.PA0;
29
30 let mut i2c = unwrap!(I2c::new_async(instance, scl, sda, Irqs, Config::default()));
31
32 let mut pot_value: u8 = 0;
33
34 loop {
35 let to_write = [0u8, pot_value];
36
37 match i2c.async_write(ADDRESS, &to_write).await {
38 Ok(()) => info!("New potentioemter value: {}", pot_value),
39 Err(e) => error!("I2c Error: {:?}", e),
40 }
41
42 pot_value += 1;
43 // if reached 64th position (max)
44 // start over from lowest value
45 if pot_value == 64 {
46 pot_value = 0;
47 }
48 Timer::after_millis(500).await;
49 }
50}
diff --git a/examples/mspm0l1306/src/bin/wwdt.rs b/examples/mspm0l1306/src/bin/wwdt.rs
new file mode 100644
index 000000000..b8fb1a1cd
--- /dev/null
+++ b/examples/mspm0l1306/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0L1306 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/mspm0l2228/Cargo.toml b/examples/mspm0l2228/Cargo.toml
index bbca011a1..3add7b8e8 100644
--- a/examples/mspm0l2228/Cargo.toml
+++ b/examples/mspm0l2228/Cargo.toml
@@ -3,19 +3,25 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l222x", "defmt", "rt", "time-driver-any"] } 9embassy-mspm0 = { version = "0.1.0", path = "../../embassy-mspm0", features = ["mspm0l2228pn", "defmt", "rt", "time-driver-any"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt"] }
12panic-halt = "0.2.0" 13panic-halt = "1.0.0"
13cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 14cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
14cortex-m-rt = { version = "0.7.0"} 15cortex-m-rt = { version = "0.7.0"}
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17panic-probe = { version = "0.3.2", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
19 20
20[profile.release] 21[profile.release]
21debug = 2 22debug = 2
23
24[package.metadata.embassy]
25build = [
26 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/mspm0l2228" }
27]
diff --git a/examples/mspm0l2228/README.md b/examples/mspm0l2228/README.md
index c73fa13b6..191022258 100644
--- a/examples/mspm0l2228/README.md
+++ b/examples/mspm0l2228/README.md
@@ -1,4 +1,4 @@
1# Examples for MSPM0L222x family 1# Examples for MSPM0L2228
2 2
3Run individual examples with 3Run individual examples with
4``` 4```
@@ -15,7 +15,7 @@ A large number of the examples are written for the [LP-MSPM0L2228](https://www.t
15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using. 15You might need to adjust `.cargo/config.toml`, `Cargo.toml` and possibly update pin numbers or peripherals to match the specific MCU or board you are using.
16 16
17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip) 17* [ ] Update .cargo/config.toml with the correct probe-rs command to use your specific MCU. For example for L2228 it should be `probe-rs run --chip MSPM0L2228`. (use `probe-rs chip list` to find your chip)
18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for L2228 it should be `mspm0l2228`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip. 18* [ ] Update Cargo.toml to have the correct `embassy-mspm0` feature. For example for LP-MSPM0L2228 it should be `mspm0l2228pn`. Look in the `Cargo.toml` file of the `embassy-mspm0` project to find the correct feature flag for your chip.
19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately. 19* [ ] If your board has a special clock or power configuration, make sure that it is set up appropriately.
20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic 20* [ ] If your board has different pin mapping, update any pin numbers or peripherals in the given example code to match your schematic
21 21
diff --git a/examples/mspm0l2228/build.rs b/examples/mspm0l2228/build.rs
index 30691aa97..2d777c2d3 100644
--- a/examples/mspm0l2228/build.rs
+++ b/examples/mspm0l2228/build.rs
@@ -32,4 +32,6 @@ fn main() {
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35 // You must tell cargo to link interrupt groups if the rt feature is enabled.
36 println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x");
35} 37}
diff --git a/examples/mspm0l2228/src/bin/wwdt.rs b/examples/mspm0l2228/src/bin/wwdt.rs
new file mode 100644
index 000000000..487d09820
--- /dev/null
+++ b/examples/mspm0l2228/src/bin/wwdt.rs
@@ -0,0 +1,54 @@
1//! Example of using window watchdog timer in the MSPM0L2228 chip.
2//!
3//! It tests the use case when watchdog timer is expired and when watchdog is pet too early.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_mspm0::gpio::{Level, Output};
11use embassy_mspm0::wwdt::{ClosedWindowPercentage, Config, Timeout, Watchdog};
12use embassy_time::Timer;
13use {defmt_rtt as _, panic_halt as _};
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) -> ! {
17 info!("Hello world!");
18
19 let p = embassy_mspm0::init(Default::default());
20 let mut conf = Config::default();
21 conf.timeout = Timeout::Sec1;
22
23 // watchdog also resets the system if the pet comes too early,
24 // less than 250 msec == 25% from 1 sec
25 conf.closed_window = ClosedWindowPercentage::TwentyFive;
26 let mut wdt = Watchdog::new(p.WWDT0, conf);
27 info!("Started the watchdog timer");
28
29 let mut led1 = Output::new(p.PA0, Level::High);
30 led1.set_inversion(true);
31 Timer::after_millis(900).await;
32
33 for _ in 1..=5 {
34 info!("pet watchdog");
35 led1.toggle();
36 wdt.pet();
37 Timer::after_millis(500).await;
38 }
39
40 // watchdog timeout test
41 info!("Stopped the pet command, device will reset in less than 1 second");
42 loop {
43 led1.toggle();
44 Timer::after_millis(500).await;
45 }
46
47 // watchdog "too early" test
48 // info!("Device will reset when the pet comes too early");
49 // loop {
50 // led1.toggle();
51 // wdt.pet();
52 // Timer::after_millis(200).await;
53 // }
54}
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
index af12212cd..c9eeaaac7 100644
--- a/examples/nrf-rtos-trace/Cargo.toml
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2021"
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"
6publish = false
6 7
7[features] 8[features]
8default = ["log"] 9default = ["log"]
@@ -15,18 +16,17 @@ log = [
15] 16]
16 17
17[dependencies] 18[dependencies]
18embassy-sync = { version = "0.6.2", path = "../../embassy-sync" } 19embassy-sync = { version = "0.7.2", path = "../../embassy-sync" }
19embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] } 20embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace"] }
20embassy-time = { version = "0.4.0", path = "../../embassy-time" } 21embassy-time = { version = "0.5.0", path = "../../embassy-time" }
21embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 22embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
22 23
23cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
24cortex-m-rt = "0.7.0" 25cortex-m-rt = "0.7.0"
25panic-probe = { version = "0.3" } 26panic-probe = "1.0.0"
26rand = { version = "0.8.4", default-features = false }
27serde = { version = "1.0.136", default-features = false } 27serde = { version = "1.0.136", default-features = false }
28rtos-trace = "0.1.3" 28rtos-trace = "0.2"
29systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] } 29systemview-target = { version = "0.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] }
30log = { version = "0.4.17", optional = true } 30log = { version = "0.4.17", optional = true }
31 31
32[[bin]] 32[[bin]]
@@ -35,3 +35,8 @@ name = "rtos_trace"
35 35
36[profile.release] 36[profile.release]
37debug = 2 37debug = 2
38
39[package.metadata.embassy]
40build = [
41 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf-rtos-trace" }
42]
diff --git a/examples/nrf-rtos-trace/build.rs b/examples/nrf-rtos-trace/build.rs
index 36cdb65a8..cd1a264c4 100644
--- a/examples/nrf-rtos-trace/build.rs
+++ b/examples/nrf-rtos-trace/build.rs
@@ -31,6 +31,4 @@ fn main() {
31 31
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 #[cfg(feature = "defmt")]
35 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
36} 34}
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
index 41cc06417..c1e7f8f58 100644
--- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
+++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
@@ -63,7 +63,7 @@ async fn main(spawner: Spawner) {
63 ::log::set_max_level(::log::LevelFilter::Trace); 63 ::log::set_max_level(::log::LevelFilter::Trace);
64 } 64 }
65 65
66 spawner.spawn(run1()).unwrap(); 66 spawner.spawn(run1().unwrap());
67 spawner.spawn(run2()).unwrap(); 67 spawner.spawn(run2().unwrap());
68 spawner.spawn(run3()).unwrap(); 68 spawner.spawn(run3().unwrap());
69} 69}
diff --git a/examples/nrf51/Cargo.toml b/examples/nrf51/Cargo.toml
index 97b5b924a..dded6de59 100644
--- a/examples/nrf51/Cargo.toml
+++ b/examples/nrf51/Cargo.toml
@@ -3,18 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
9embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] } 11embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf51", "gpiote", "time-driver-rtc1", "unstable-pac", "time", "rt"] }
11 12
12defmt = "0.3" 13defmt = "1.0.1"
13defmt-rtt = "0.4" 14defmt-rtt = "1.0.0"
14 15
15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
16cortex-m-rt = "0.7" 17cortex-m-rt = "0.7"
17panic-probe = { version = "0.3", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18 19
19[profile.release] 20[profile.release]
20debug = 2 21debug = 2
22
23[package.metadata.embassy]
24build = [
25 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/nrf51" }
26]
diff --git a/examples/nrf52810/Cargo.toml b/examples/nrf52810/Cargo.toml
index cd59b86c3..aa1a4bf73 100644
--- a/examples/nrf52810/Cargo.toml
+++ b/examples/nrf52810/Cargo.toml
@@ -3,22 +3,28 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52810", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
13 14
14defmt = "0.3" 15defmt = "1.0.1"
15defmt-rtt = "0.4" 16defmt-rtt = "1.0.0"
16 17
17fixed = "1.10.0" 18fixed = "1.10.0"
18static_cell = { version = "2" } 19static_cell = { version = "2" }
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22 23
23[profile.release] 24[profile.release]
24debug = 2 25debug = 2
26
27[package.metadata.embassy]
28build = [
29 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52810" }
30]
diff --git a/examples/nrf52840-edf/.cargo/config.toml b/examples/nrf52840-edf/.cargo/config.toml
new file mode 100644
index 000000000..e0b9ce59e
--- /dev/null
+++ b/examples/nrf52840-edf/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip nRF52840_xxAA"
4
5[build]
6target = "thumbv7em-none-eabi"
7
8[env]
9DEFMT_LOG = "debug"
diff --git a/examples/nrf52840-edf/Cargo.toml b/examples/nrf52840-edf/Cargo.toml
new file mode 100644
index 000000000..1e8803233
--- /dev/null
+++ b/examples/nrf52840-edf/Cargo.toml
@@ -0,0 +1,27 @@
1[package]
2edition = "2021"
3name = "embassy-nrf52840-edf-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9# NOTE: "scheduler-deadline" and "embassy-time-driver" features are enabled
10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "scheduler-deadline", "embassy-time-driver"] }
11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
13
14defmt = "1.0.1"
15defmt-rtt = "1.0.0"
16
17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
18cortex-m-rt = "0.7.0"
19panic-probe = { version = "1.0.0", features = ["print-defmt"] }
20
21[profile.release]
22debug = 2
23
24[package.metadata.embassy]
25build = [
26 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-edf" }
27]
diff --git a/examples/nrf52840-edf/build.rs b/examples/nrf52840-edf/build.rs
new file mode 100644
index 000000000..30691aa97
--- /dev/null
+++ b/examples/nrf52840-edf/build.rs
@@ -0,0 +1,35 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
35}
diff --git a/examples/nrf52840-edf/memory.x b/examples/nrf52840-edf/memory.x
new file mode 100644
index 000000000..15b492bce
--- /dev/null
+++ b/examples/nrf52840-edf/memory.x
@@ -0,0 +1,12 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
5 RAM : ORIGIN = 0x20000000, LENGTH = 256K
6
7 /* These values correspond to the NRF52840 with Softdevices S140 7.3.0 */
8 /*
9 FLASH : ORIGIN = 0x00027000, LENGTH = 868K
10 RAM : ORIGIN = 0x20020000, LENGTH = 128K
11 */
12}
diff --git a/examples/nrf52840-edf/src/bin/basic.rs b/examples/nrf52840-edf/src/bin/basic.rs
new file mode 100644
index 000000000..d888e17d1
--- /dev/null
+++ b/examples/nrf52840-edf/src/bin/basic.rs
@@ -0,0 +1,194 @@
1//! Basic side-by-side example of the Earliest Deadline First scheduler
2//!
3//! This test spawns a number of background "ambient system load" workers
4//! that are constantly working, and runs two sets of trials.
5//!
6//! The first trial runs with no deadline set, so our trial task is at the
7//! same prioritization level as the background worker tasks.
8//!
9//! The second trial sets a deadline, meaning that it will be given higher
10//! scheduling priority than background tasks, that have no deadline set
11
12#![no_std]
13#![no_main]
14
15use core::sync::atomic::{compiler_fence, Ordering};
16
17use defmt::unwrap;
18use embassy_executor::Spawner;
19use embassy_time::{Duration, Instant, Timer};
20use {defmt_rtt as _, panic_probe as _};
21
22#[embassy_executor::main]
23async fn main(spawner: Spawner) {
24 embassy_nrf::init(Default::default());
25
26 // Enable flash cache to remove some flash latency jitter
27 compiler_fence(Ordering::SeqCst);
28 embassy_nrf::pac::NVMC.icachecnf().write(|w| {
29 w.set_cacheen(true);
30 });
31 compiler_fence(Ordering::SeqCst);
32
33 //
34 // Baseline system load tunables
35 //
36
37 // how many load tasks? More load tasks means more tasks contending
38 // for the runqueue
39 let tasks = 32;
40 // how long should each task work for? The longer the working time,
41 // the longer the max jitter possible, even when a task is prioritized,
42 // as EDF is still cooperative and not pre-emptive
43 //
44 // 33 ticks ~= 1ms
45 let work_time_ticks = 33;
46 // what fraction, 1/denominator, should the system be busy?
47 // bigger number means **less** busy
48 //
49 // 2 => 50%
50 // 4 => 25%
51 // 10 => 10%
52 let denominator = 2;
53
54 // Total time window, so each worker is working 1/denominator
55 // amount of the total time
56 let time_window = work_time_ticks * u64::from(tasks) * denominator;
57
58 // Spawn all of our load workers!
59 for i in 0..tasks {
60 spawner.spawn(unwrap!(load_task(i, work_time_ticks, time_window)));
61 }
62
63 // Let all the tasks spin up
64 defmt::println!("Spinning up load tasks...");
65 Timer::after_secs(1).await;
66
67 //
68 // Trial task worker tunables
69 //
70
71 // How many steps should the workers under test run?
72 // More steps means more chances to have to wait for other tasks
73 // in line ahead of us.
74 let num_steps = 100;
75
76 // How many ticks should the worker take working on each step?
77 //
78 // 33 ticks ~= 1ms
79 let work_ticks = 33;
80 // How many ticks should the worker wait on each step?
81 //
82 // 66 ticks ~= 2ms
83 let idle_ticks = 66;
84
85 // How many times to repeat each trial?
86 let trials = 3;
87
88 // The total time a trial would take, in a perfect unloaded system
89 let theoretical = (num_steps * work_ticks) + (num_steps * idle_ticks);
90
91 defmt::println!("");
92 defmt::println!("Starting UNPRIORITIZED worker trials");
93 for _ in 0..trials {
94 //
95 // UNPRIORITIZED worker
96 //
97 defmt::println!("");
98 defmt::println!("Starting unprioritized worker");
99 let start = Instant::now();
100 for _ in 0..num_steps {
101 let now = Instant::now();
102 while now.elapsed().as_ticks() < work_ticks {}
103 Timer::after_ticks(idle_ticks).await;
104 }
105 let elapsed = start.elapsed().as_ticks();
106 defmt::println!(
107 "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}",
108 theoretical,
109 elapsed
110 );
111 let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0;
112 defmt::println!("Took {=f32}% of ideal time", ratio);
113 Timer::after_millis(500).await;
114 }
115
116 Timer::after_secs(1).await;
117
118 defmt::println!("");
119 defmt::println!("Starting PRIORITIZED worker trials");
120 for _ in 0..trials {
121 //
122 // PRIORITIZED worker
123 //
124 defmt::println!("");
125 defmt::println!("Starting prioritized worker");
126 let start = Instant::now();
127 // Set the deadline to ~2x the theoretical time. In practice, setting any deadline
128 // here elevates the current task above all other worker tasks.
129 let meta = embassy_executor::Metadata::for_current_task().await;
130 meta.set_deadline_after(theoretical * 2);
131
132 // Perform the trial
133 for _ in 0..num_steps {
134 let now = Instant::now();
135 while now.elapsed().as_ticks() < work_ticks {}
136 Timer::after_ticks(idle_ticks).await;
137 }
138
139 let elapsed = start.elapsed().as_ticks();
140 defmt::println!(
141 "Trial complete, theoretical ticks: {=u64}, actual ticks: {=u64}",
142 theoretical,
143 elapsed
144 );
145 let ratio = ((elapsed as f32) / (theoretical as f32)) * 100.0;
146 defmt::println!("Took {=f32}% of ideal time", ratio);
147
148 // Unset the deadline, deadlines are not automatically cleared, and if our
149 // deadline is in the past, then we get very high priority!
150 meta.unset_deadline();
151
152 Timer::after_millis(500).await;
153 }
154
155 defmt::println!("");
156 defmt::println!("Trials Complete.");
157}
158
159#[embassy_executor::task(pool_size = 32)]
160async fn load_task(id: u32, ticks_on: u64, ttl_ticks: u64) {
161 let mut last_print = Instant::now();
162 let mut last_tick = last_print;
163 let mut variance = 0;
164 let mut max_variance = 0;
165 loop {
166 let tgt = last_tick + Duration::from_ticks(ttl_ticks);
167 assert!(tgt > Instant::now(), "fell too behind!");
168
169 Timer::at(tgt).await;
170 let now = Instant::now();
171 // How late are we from the target?
172 let var = now.duration_since(tgt).as_ticks();
173 max_variance = max_variance.max(var);
174 variance += var;
175
176 // blocking work
177 while now.elapsed().as_ticks() < ticks_on {}
178
179 if last_print.elapsed() >= Duration::from_secs(1) {
180 defmt::trace!(
181 "Task {=u32} variance ticks (1s): {=u64}, max: {=u64}, act: {=u64}",
182 id,
183 variance,
184 max_variance,
185 ticks_on,
186 );
187 max_variance = 0;
188 variance = 0;
189 last_print = Instant::now();
190 }
191
192 last_tick = tgt;
193 }
194}
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml
index ac3d2006c..f6937c263 100644
--- a/examples/nrf52840-rtic/Cargo.toml
+++ b/examples/nrf52840-rtic/Cargo.toml
@@ -3,22 +3,28 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8rtic = { version = "2", features = ["thumbv7-backend"] } 9rtic = { version = "2", features = ["thumbv7-backend"] }
9 10
10embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 11embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
11embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime"] }
13embassy-time-queue-utils = { version = "0.1", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] } 14embassy-time-queue-utils = { version = "0.3.0", path = "../../embassy-time-queue-utils", features = ["generic-queue-8"] }
14embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 15embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = [ "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22 23
23[profile.release] 24[profile.release]
24debug = 2 25debug = 2
26
27[package.metadata.embassy]
28build = [
29 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840-rtic" }
30]
diff --git a/examples/nrf52840-rtic/src/bin/blinky.rs b/examples/nrf52840-rtic/src/bin/blinky.rs
index 719e22729..2adac7e0a 100644
--- a/examples/nrf52840-rtic/src/bin/blinky.rs
+++ b/examples/nrf52840-rtic/src/bin/blinky.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use {defmt_rtt as _, panic_probe as _}; 4use {defmt_rtt as _, panic_probe as _};
6 5
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 902193f3a..452e83b7e 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -3,29 +3,30 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embedded-io = { version = "0.6.0", features = ["defmt-03"] } 16embedded-io = { version = "0.6.0", features = ["defmt-03"] }
16embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 17embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
17embassy-net-esp-hosted = { version = "0.2.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } 18embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] }
18embassy-net-enc28j60 = { version = "0.2.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } 19embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] }
19 20
20defmt = "0.3" 21defmt = "1.0.1"
21defmt-rtt = "0.4" 22defmt-rtt = "1.0.0"
22 23
23fixed = "1.10.0" 24fixed = "1.10.0"
24static_cell = { version = "2" } 25static_cell = { version = "2" }
25cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 26cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
26cortex-m-rt = "0.7.0" 27cortex-m-rt = "0.7.0"
27panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
28rand = { version = "0.8.4", default-features = false } 29rand = { version = "0.9.0", default-features = false }
29embedded-storage = "0.3.1" 30embedded-storage = "0.3.1"
30usbd-hid = "0.8.1" 31usbd-hid = "0.8.1"
31serde = { version = "1.0.136", default-features = false } 32serde = { version = "1.0.136", default-features = false }
@@ -37,3 +38,8 @@ microfft = "0.5.0"
37 38
38[profile.release] 39[profile.release]
39debug = 2 40debug = 2
41
42[package.metadata.embassy]
43build = [
44 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840" }
45]
diff --git a/examples/nrf52840/src/bin/channel.rs b/examples/nrf52840/src/bin/channel.rs
index e06ba1c73..ffa539808 100644
--- a/examples/nrf52840/src/bin/channel.rs
+++ b/examples/nrf52840/src/bin/channel.rs
@@ -31,7 +31,7 @@ async fn main(spawner: Spawner) {
31 let p = embassy_nrf::init(Default::default()); 31 let p = embassy_nrf::init(Default::default());
32 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); 32 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
33 33
34 unwrap!(spawner.spawn(my_task())); 34 spawner.spawn(unwrap!(my_task()));
35 35
36 loop { 36 loop {
37 match CHANNEL.receive().await { 37 match CHANNEL.receive().await {
diff --git a/examples/nrf52840/src/bin/channel_sender_receiver.rs b/examples/nrf52840/src/bin/channel_sender_receiver.rs
index 74c62ca20..09050db68 100644
--- a/examples/nrf52840/src/bin/channel_sender_receiver.rs
+++ b/examples/nrf52840/src/bin/channel_sender_receiver.rs
@@ -45,6 +45,6 @@ async fn main(spawner: Spawner) {
45 let p = embassy_nrf::init(Default::default()); 45 let p = embassy_nrf::init(Default::default());
46 let channel = CHANNEL.init(Channel::new()); 46 let channel = CHANNEL.init(Channel::new());
47 47
48 unwrap!(spawner.spawn(send_task(channel.sender()))); 48 spawner.spawn(unwrap!(send_task(channel.sender())));
49 unwrap!(spawner.spawn(recv_task(p.P0_13.into(), channel.receiver()))); 49 spawner.spawn(unwrap!(recv_task(p.P0_13.into(), channel.receiver())));
50} 50}
diff --git a/examples/nrf52840/src/bin/ethernet_enc28j60.rs b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
index 0946492fe..3bb255a72 100644
--- a/examples/nrf52840/src/bin/ethernet_enc28j60.rs
+++ b/examples/nrf52840/src/bin/ethernet_enc28j60.rs
@@ -70,7 +70,7 @@ async fn main(spawner: Spawner) {
70 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 70 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
71 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 71 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
72 72
73 unwrap!(spawner.spawn(net_task(runner))); 73 spawner.spawn(unwrap!(net_task(runner)));
74 74
75 // And now we can use it! 75 // And now we can use it!
76 76
diff --git a/examples/nrf52840/src/bin/executor_fairness_test.rs b/examples/nrf52840/src/bin/executor_fairness_test.rs
index df6e7af3f..70c9405f0 100644
--- a/examples/nrf52840/src/bin/executor_fairness_test.rs
+++ b/examples/nrf52840/src/bin/executor_fairness_test.rs
@@ -36,7 +36,7 @@ async fn run3() {
36#[embassy_executor::main] 36#[embassy_executor::main]
37async fn main(spawner: Spawner) { 37async fn main(spawner: Spawner) {
38 let _p = embassy_nrf::init(Default::default()); 38 let _p = embassy_nrf::init(Default::default());
39 unwrap!(spawner.spawn(run1())); 39 spawner.spawn(unwrap!(run1()));
40 unwrap!(spawner.spawn(run2())); 40 spawner.spawn(unwrap!(run2()));
41 unwrap!(spawner.spawn(run3())); 41 spawner.spawn(unwrap!(run3()));
42} 42}
diff --git a/examples/nrf52840/src/bin/gpiote_port.rs b/examples/nrf52840/src/bin/gpiote_port.rs
index 0dddb1a97..66dbd32dc 100644
--- a/examples/nrf52840/src/bin/gpiote_port.rs
+++ b/examples/nrf52840/src/bin/gpiote_port.rs
@@ -26,8 +26,8 @@ async fn main(spawner: Spawner) {
26 let btn3 = Input::new(p.P0_24, Pull::Up); 26 let btn3 = Input::new(p.P0_24, Pull::Up);
27 let btn4 = Input::new(p.P0_25, Pull::Up); 27 let btn4 = Input::new(p.P0_25, Pull::Up);
28 28
29 unwrap!(spawner.spawn(button_task(1, btn1))); 29 spawner.spawn(unwrap!(button_task(1, btn1)));
30 unwrap!(spawner.spawn(button_task(2, btn2))); 30 spawner.spawn(unwrap!(button_task(2, btn2)));
31 unwrap!(spawner.spawn(button_task(3, btn3))); 31 spawner.spawn(unwrap!(button_task(3, btn3)));
32 unwrap!(spawner.spawn(button_task(4, btn4))); 32 spawner.spawn(unwrap!(button_task(4, btn4)));
33} 33}
diff --git a/examples/nrf52840/src/bin/ieee802154_receive.rs b/examples/nrf52840/src/bin/ieee802154_receive.rs
new file mode 100644
index 000000000..ede8fca65
--- /dev/null
+++ b/examples/nrf52840/src/bin/ieee802154_receive.rs
@@ -0,0 +1,38 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::config::{Config, HfclkSource};
6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_nrf::radio::ieee802154::{self, Packet};
8use embassy_nrf::{peripherals, radio};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12embassy_nrf::bind_interrupts!(struct Irqs {
13 RADIO => radio::InterruptHandler<peripherals::RADIO>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut config = Config::default();
19 config.hfclk_source = HfclkSource::ExternalXtal;
20 let peripherals = embassy_nrf::init(config);
21
22 // assumes LED on P0_15 with active-high polarity
23 let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard);
24
25 let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs);
26 let mut packet = Packet::new();
27
28 loop {
29 gpo_led.set_low();
30 let rv = radio.receive(&mut packet).await;
31 gpo_led.set_high();
32 match rv {
33 Err(_) => defmt::error!("receive() Err"),
34 Ok(_) => defmt::info!("receive() {:?}", *packet),
35 }
36 Timer::after_millis(100u64).await;
37 }
38}
diff --git a/examples/nrf52840/src/bin/ieee802154_send.rs b/examples/nrf52840/src/bin/ieee802154_send.rs
new file mode 100644
index 000000000..7af9d1d06
--- /dev/null
+++ b/examples/nrf52840/src/bin/ieee802154_send.rs
@@ -0,0 +1,39 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_nrf::config::{Config, HfclkSource};
6use embassy_nrf::gpio::{Level, Output, OutputDrive};
7use embassy_nrf::radio::ieee802154::{self, Packet};
8use embassy_nrf::{peripherals, radio};
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12embassy_nrf::bind_interrupts!(struct Irqs {
13 RADIO => radio::InterruptHandler<peripherals::RADIO>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut config = Config::default();
19 config.hfclk_source = HfclkSource::ExternalXtal;
20 let peripherals = embassy_nrf::init(config);
21
22 // assumes LED on P0_15 with active-high polarity
23 let mut gpo_led = Output::new(peripherals.P0_15, Level::Low, OutputDrive::Standard);
24
25 let mut radio = ieee802154::Radio::new(peripherals.RADIO, Irqs);
26 let mut packet = Packet::new();
27
28 loop {
29 packet.copy_from_slice(&[0_u8; 16]);
30 gpo_led.set_high();
31 let rv = radio.try_send(&mut packet).await;
32 gpo_led.set_low();
33 match rv {
34 Err(_) => defmt::error!("try_send() Err"),
35 Ok(_) => defmt::info!("try_send() {:?}", *packet),
36 }
37 Timer::after_millis(1000u64).await;
38 }
39}
diff --git a/examples/nrf52840/src/bin/manually_create_executor.rs b/examples/nrf52840/src/bin/manually_create_executor.rs
index 7ca39348e..f0639eb23 100644
--- a/examples/nrf52840/src/bin/manually_create_executor.rs
+++ b/examples/nrf52840/src/bin/manually_create_executor.rs
@@ -42,7 +42,7 @@ fn main() -> ! {
42 // `run` calls the closure then runs the executor forever. It never returns. 42 // `run` calls the closure then runs the executor forever. It never returns.
43 executor.run(|spawner| { 43 executor.run(|spawner| {
44 // Here we get access to a spawner to spawn the initial tasks. 44 // Here we get access to a spawner to spawn the initial tasks.
45 unwrap!(spawner.spawn(run1())); 45 spawner.spawn(unwrap!(run1()));
46 unwrap!(spawner.spawn(run2())); 46 spawner.spawn(unwrap!(run2()));
47 }); 47 });
48} 48}
diff --git a/examples/nrf52840/src/bin/multiprio.rs b/examples/nrf52840/src/bin/multiprio.rs
index d58613da4..4d9b986d4 100644
--- a/examples/nrf52840/src/bin/multiprio.rs
+++ b/examples/nrf52840/src/bin/multiprio.rs
@@ -130,16 +130,16 @@ fn main() -> ! {
130 // High-priority executor: EGU1_SWI1, priority level 6 130 // High-priority executor: EGU1_SWI1, priority level 6
131 interrupt::EGU1_SWI1.set_priority(Priority::P6); 131 interrupt::EGU1_SWI1.set_priority(Priority::P6);
132 let spawner = EXECUTOR_HIGH.start(interrupt::EGU1_SWI1); 132 let spawner = EXECUTOR_HIGH.start(interrupt::EGU1_SWI1);
133 unwrap!(spawner.spawn(run_high())); 133 spawner.spawn(unwrap!(run_high()));
134 134
135 // Medium-priority executor: EGU0_SWI0, priority level 7 135 // Medium-priority executor: EGU0_SWI0, priority level 7
136 interrupt::EGU0_SWI0.set_priority(Priority::P7); 136 interrupt::EGU0_SWI0.set_priority(Priority::P7);
137 let spawner = EXECUTOR_MED.start(interrupt::EGU0_SWI0); 137 let spawner = EXECUTOR_MED.start(interrupt::EGU0_SWI0);
138 unwrap!(spawner.spawn(run_med())); 138 spawner.spawn(unwrap!(run_med()));
139 139
140 // Low priority executor: runs in thread mode, using WFE/SEV 140 // Low priority executor: runs in thread mode, using WFE/SEV
141 let executor = EXECUTOR_LOW.init(Executor::new()); 141 let executor = EXECUTOR_LOW.init(Executor::new());
142 executor.run(|spawner| { 142 executor.run(|spawner| {
143 unwrap!(spawner.spawn(run_low())); 143 spawner.spawn(unwrap!(run_low()));
144 }); 144 });
145} 145}
diff --git a/examples/nrf52840/src/bin/mutex.rs b/examples/nrf52840/src/bin/mutex.rs
index 5c22279b5..a8e9a82cc 100644
--- a/examples/nrf52840/src/bin/mutex.rs
+++ b/examples/nrf52840/src/bin/mutex.rs
@@ -30,7 +30,7 @@ async fn my_task() {
30#[embassy_executor::main] 30#[embassy_executor::main]
31async fn main(spawner: Spawner) { 31async fn main(spawner: Spawner) {
32 let _p = embassy_nrf::init(Default::default()); 32 let _p = embassy_nrf::init(Default::default());
33 unwrap!(spawner.spawn(my_task())); 33 spawner.spawn(unwrap!(my_task()));
34 34
35 loop { 35 loop {
36 Timer::after_millis(300).await; 36 Timer::after_millis(300).await;
diff --git a/examples/nrf52840/src/bin/nfct.rs b/examples/nrf52840/src/bin/nfct.rs
index d559d006a..fafa37f48 100644
--- a/examples/nrf52840/src/bin/nfct.rs
+++ b/examples/nrf52840/src/bin/nfct.rs
@@ -1,11 +1,12 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::{todo, *};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_nrf::config::HfclkSource; 6use embassy_nrf::config::HfclkSource;
7use embassy_nrf::nfct::{Config as NfcConfig, NfcId, NfcT}; 7use embassy_nrf::nfct::{Config as NfcConfig, NfcId, NfcT};
8use embassy_nrf::{bind_interrupts, nfct}; 8use embassy_nrf::{bind_interrupts, nfct};
9use iso14443_4::{Card, IsoDep};
9use {defmt_rtt as _, embassy_nrf as _, panic_probe as _}; 10use {defmt_rtt as _, embassy_nrf as _, panic_probe as _};
10 11
11bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -30,12 +31,28 @@ async fn main(_spawner: Spawner) {
30 31
31 let mut buf = [0u8; 256]; 32 let mut buf = [0u8; 256];
32 33
34 let cc = &[
35 0x00, 0x0f, /* CCEN_HI, CCEN_LOW */
36 0x20, /* VERSION */
37 0x00, 0x7f, /* MLe_HI, MLe_LOW */
38 0x00, 0x7f, /* MLc_HI, MLc_LOW */
39 /* TLV */
40 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00,
41 ];
42
43 let ndef = &[
44 0x00, 0x10, 0xd1, 0x1, 0xc, 0x55, 0x4, 0x65, 0x6d, 0x62, 0x61, 0x73, 0x73, 0x79, 0x2e, 0x64, 0x65, 0x76,
45 ];
46 let mut selected: &[u8] = cc;
47
33 loop { 48 loop {
34 info!("activating"); 49 info!("activating");
35 nfc.activate().await; 50 nfc.activate().await;
51 info!("activated!");
52
53 let mut nfc = IsoDep::new(iso14443_3::Logger(&mut nfc));
36 54
37 loop { 55 loop {
38 info!("rxing");
39 let n = match nfc.receive(&mut buf).await { 56 let n = match nfc.receive(&mut buf).await {
40 Ok(n) => n, 57 Ok(n) => n,
41 Err(e) => { 58 Err(e) => {
@@ -44,25 +61,51 @@ async fn main(_spawner: Spawner) {
44 } 61 }
45 }; 62 };
46 let req = &buf[..n]; 63 let req = &buf[..n];
47 info!("received frame {:02x}", req); 64 info!("iso-dep rx {:02x}", req);
48 65
49 let mut deselect = false; 66 let Ok(apdu) = Apdu::parse(req) else {
50 let resp = match req { 67 error!("apdu parse error");
51 [0xe0, ..] => { 68 break;
52 info!("Got RATS, tx'ing ATS"); 69 };
53 &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80][..] 70
71 info!("apdu: {:?}", apdu);
72
73 let resp = match (apdu.cla, apdu.ins, apdu.p1, apdu.p2) {
74 (0, 0xa4, 4, 0) => {
75 info!("select app");
76 &[0x90, 0x00][..]
54 } 77 }
55 [0xc2] => { 78 (0, 0xa4, 0, 12) => {
56 info!("Got deselect!"); 79 info!("select df");
57 deselect = true; 80 match apdu.data {
58 &[0xc2] 81 [0xe1, 0x03] => {
82 selected = cc;
83 &[0x90, 0x00][..]
84 }
85 [0xe1, 0x04] => {
86 selected = ndef;
87 &[0x90, 0x00][..]
88 }
89 _ => todo!(), // return NOT FOUND
90 }
91 }
92 (0, 0xb0, p1, p2) => {
93 info!("read");
94 let offs = u16::from_be_bytes([p1 & 0x7f, p2]) as usize;
95 let len = if apdu.le == 0 { usize::MAX } else { apdu.le as usize };
96 let n = len.min(selected.len() - offs);
97 buf[..n].copy_from_slice(&selected[offs..][..n]);
98 buf[n..][..2].copy_from_slice(&[0x90, 0x00]);
99 &buf[..n + 2]
59 } 100 }
60 _ => { 101 _ => {
61 info!("Got unknown command!"); 102 info!("Got unknown command!");
62 &[0xFF] 103 &[0xFF, 0xFF]
63 } 104 }
64 }; 105 };
65 106
107 info!("iso-dep tx {:02x}", resp);
108
66 match nfc.transmit(resp).await { 109 match nfc.transmit(resp).await {
67 Ok(()) => {} 110 Ok(()) => {}
68 Err(e) => { 111 Err(e) => {
@@ -70,10 +113,211 @@ async fn main(_spawner: Spawner) {
70 break; 113 break;
71 } 114 }
72 } 115 }
116 }
117 }
118}
73 119
74 if deselect { 120#[derive(Debug, Clone, defmt::Format)]
75 break; 121struct Apdu<'a> {
122 pub cla: u8,
123 pub ins: u8,
124 pub p1: u8,
125 pub p2: u8,
126 pub data: &'a [u8],
127 pub le: u16,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
131struct ApduParseError;
132
133impl<'a> Apdu<'a> {
134 pub fn parse(apdu: &'a [u8]) -> Result<Self, ApduParseError> {
135 if apdu.len() < 4 {
136 return Err(ApduParseError);
137 }
138
139 let (data, le) = match apdu.len() - 4 {
140 0 => (&[][..], 0),
141 1 => (&[][..], apdu[4]),
142 n if n == 1 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], 0),
143 n if n == 2 + apdu[4] as usize && apdu[4] != 0 => (&apdu[5..][..apdu[4] as usize], apdu[apdu.len() - 1]),
144 _ => return Err(ApduParseError),
145 };
146
147 Ok(Apdu {
148 cla: apdu[0],
149 ins: apdu[1],
150 p1: apdu[2],
151 p2: apdu[3],
152 data,
153 le: le as _,
154 })
155 }
156}
157
158mod iso14443_3 {
159 use core::future::Future;
160
161 use defmt::info;
162 use embassy_nrf::nfct::{Error, NfcT};
163
164 pub trait Card {
165 type Error;
166 async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
167 async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
168 }
169
170 impl<'a, T: Card> Card for &'a mut T {
171 type Error = T::Error;
172
173 fn receive(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> {
174 T::receive(self, buf)
175 }
176
177 fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> {
178 T::transmit(self, buf)
179 }
180 }
181
182 impl<'a> Card for NfcT<'a> {
183 type Error = Error;
184
185 fn receive(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> {
186 self.receive(buf)
187 }
188
189 fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> {
190 self.transmit(buf)
191 }
192 }
193
194 pub struct Logger<T: Card>(pub T);
195
196 impl<T: Card> Card for Logger<T> {
197 type Error = T::Error;
198
199 async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
200 let n = T::receive(&mut self.0, buf).await?;
201 info!("<- {:02x}", &buf[..n]);
202 Ok(n)
203 }
204
205 fn transmit(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Self::Error>> {
206 info!("-> {:02x}", buf);
207 T::transmit(&mut self.0, buf)
208 }
209 }
210}
211
212mod iso14443_4 {
213 use defmt::info;
214
215 use crate::iso14443_3;
216
217 #[derive(defmt::Format)]
218 pub enum Error<T> {
219 Deselected,
220 Protocol,
221 Lower(T),
222 }
223
224 pub trait Card {
225 type Error;
226 async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
227 async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
228 }
229
230 pub struct IsoDep<T: iso14443_3::Card> {
231 nfc: T,
232
233 /// Block count spin bit: 0 or 1
234 block_num: u8,
235
236 /// true if deselected. This is permanent, you must create another IsoDep
237 /// instance if we get selected again.
238 deselected: bool,
239
240 /// last response, in case we need to retransmit.
241 resp: [u8; 256],
242 resp_len: usize,
243 }
244
245 impl<T: iso14443_3::Card> IsoDep<T> {
246 pub fn new(nfc: T) -> Self {
247 Self {
248 nfc,
249 block_num: 1,
250 deselected: false,
251 resp: [0u8; 256],
252 resp_len: 0,
76 } 253 }
77 } 254 }
78 } 255 }
256
257 impl<T: iso14443_3::Card> Card for IsoDep<T> {
258 type Error = Error<T::Error>;
259
260 async fn receive(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
261 if self.deselected {
262 return Err(Error::Deselected);
263 }
264
265 let mut temp = [0u8; 256];
266
267 loop {
268 let n = self.nfc.receive(&mut temp).await.map_err(Error::Lower)?;
269 assert!(n != 0);
270 match temp[0] {
271 0x02 | 0x03 => {
272 self.block_num ^= 0x01;
273 assert!(temp[0] == 0x02 | self.block_num);
274 buf[..n - 1].copy_from_slice(&temp[1..n]);
275 return Ok(n - 1);
276 }
277 0xb2 | 0xb3 => {
278 if temp[0] & 0x01 != self.block_num {
279 info!("Got NAK, transmitting ACK.");
280 let resp = &[0xA2 | self.block_num];
281 self.nfc.transmit(resp).await.map_err(Error::Lower)?;
282 } else {
283 info!("Got NAK, retransmitting.");
284 let resp: &[u8] = &self.resp[..self.resp_len];
285 self.nfc.transmit(resp).await.map_err(Error::Lower)?;
286 }
287 }
288 0xe0 => {
289 info!("Got RATS, tx'ing ATS");
290 let resp = &[0x06, 0x77, 0x77, 0x81, 0x02, 0x80];
291 self.nfc.transmit(resp).await.map_err(Error::Lower)?;
292 }
293 0xc2 => {
294 info!("Got deselect!");
295 self.deselected = true;
296 let resp = &[0xC2];
297 self.nfc.transmit(resp).await.map_err(Error::Lower)?;
298 return Err(Error::Deselected);
299 }
300 _ => {
301 info!("Got unknown command {:02x}!", temp[0]);
302 return Err(Error::Protocol);
303 }
304 };
305 }
306 }
307
308 async fn transmit(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
309 if self.deselected {
310 return Err(Error::Deselected);
311 }
312
313 self.resp[0] = 0x02 | self.block_num;
314 self.resp[1..][..buf.len()].copy_from_slice(buf);
315 self.resp_len = 1 + buf.len();
316
317 let resp: &[u8] = &self.resp[..self.resp_len];
318 self.nfc.transmit(resp).await.map_err(Error::Lower)?;
319
320 Ok(())
321 }
322 }
79} 323}
diff --git a/examples/nrf52840/src/bin/pubsub.rs b/examples/nrf52840/src/bin/pubsub.rs
index 5ebea9220..c0392b18c 100644
--- a/examples/nrf52840/src/bin/pubsub.rs
+++ b/examples/nrf52840/src/bin/pubsub.rs
@@ -26,9 +26,9 @@ async fn main(spawner: Spawner) {
26 // It's good to set up the subscribers before publishing anything. 26 // It's good to set up the subscribers before publishing anything.
27 // A subscriber will only yield messages that have been published after its creation. 27 // A subscriber will only yield messages that have been published after its creation.
28 28
29 spawner.must_spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber()))); 29 spawner.spawn(fast_logger(unwrap!(MESSAGE_BUS.subscriber())).unwrap());
30 spawner.must_spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber()))); 30 spawner.spawn(slow_logger(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap());
31 spawner.must_spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber()))); 31 spawner.spawn(slow_logger_pure(unwrap!(MESSAGE_BUS.dyn_subscriber())).unwrap());
32 32
33 // Get a publisher 33 // Get a publisher
34 let message_publisher = unwrap!(MESSAGE_BUS.publisher()); 34 let message_publisher = unwrap!(MESSAGE_BUS.publisher());
diff --git a/examples/nrf52840/src/bin/raw_spawn.rs b/examples/nrf52840/src/bin/raw_spawn.rs
index 717b0faa6..b80954408 100644
--- a/examples/nrf52840/src/bin/raw_spawn.rs
+++ b/examples/nrf52840/src/bin/raw_spawn.rs
@@ -42,8 +42,8 @@ fn main() -> ! {
42 let run2_task = unsafe { make_static(&run2_task) }; 42 let run2_task = unsafe { make_static(&run2_task) };
43 43
44 executor.run(|spawner| { 44 executor.run(|spawner| {
45 unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); 45 spawner.spawn(unwrap!(run1_task.spawn(|| run1())));
46 unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); 46 spawner.spawn(unwrap!(run2_task.spawn(|| run2())));
47 }); 47 });
48} 48}
49 49
diff --git a/examples/nrf52840/src/bin/rng.rs b/examples/nrf52840/src/bin/rng.rs
index 326054c9a..f32d17cd9 100644..100755
--- a/examples/nrf52840/src/bin/rng.rs
+++ b/examples/nrf52840/src/bin/rng.rs
@@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) {
22 defmt::info!("Some random bytes: {:?}", bytes); 22 defmt::info!("Some random bytes: {:?}", bytes);
23 23
24 // Sync API with `rand` 24 // Sync API with `rand`
25 defmt::info!("A random number from 1 to 10: {:?}", rng.gen_range(1..=10)); 25 defmt::info!("A random number from 1 to 10: {:?}", rng.random_range(1..=10));
26 26
27 let mut bytes = [0; 1024]; 27 let mut bytes = [0; 1024];
28 rng.fill_bytes(&mut bytes).await; 28 rng.fill_bytes(&mut bytes).await;
diff --git a/examples/nrf52840/src/bin/self_spawn.rs b/examples/nrf52840/src/bin/self_spawn.rs
index 5bfefc2af..acb44f98b 100644
--- a/examples/nrf52840/src/bin/self_spawn.rs
+++ b/examples/nrf52840/src/bin/self_spawn.rs
@@ -14,12 +14,12 @@ mod config {
14async fn my_task(spawner: Spawner, n: u32) { 14async fn my_task(spawner: Spawner, n: u32) {
15 Timer::after_secs(1).await; 15 Timer::after_secs(1).await;
16 info!("Spawning self! {}", n); 16 info!("Spawning self! {}", n);
17 unwrap!(spawner.spawn(my_task(spawner, n + 1))); 17 spawner.spawn(unwrap!(my_task(spawner, n + 1)));
18} 18}
19 19
20#[embassy_executor::main] 20#[embassy_executor::main]
21async fn main(spawner: Spawner) { 21async fn main(spawner: Spawner) {
22 let _p = embassy_nrf::init(Default::default()); 22 let _p = embassy_nrf::init(Default::default());
23 info!("Hello World!"); 23 info!("Hello World!");
24 unwrap!(spawner.spawn(my_task(spawner, 0))); 24 spawner.spawn(unwrap!(my_task(spawner, 0)));
25} 25}
diff --git a/examples/nrf52840/src/bin/self_spawn_current_executor.rs b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
index ec9569a64..d93067592 100644
--- a/examples/nrf52840/src/bin/self_spawn_current_executor.rs
+++ b/examples/nrf52840/src/bin/self_spawn_current_executor.rs
@@ -10,12 +10,13 @@ use {defmt_rtt as _, panic_probe as _};
10async fn my_task(n: u32) { 10async fn my_task(n: u32) {
11 Timer::after_secs(1).await; 11 Timer::after_secs(1).await;
12 info!("Spawning self! {}", n); 12 info!("Spawning self! {}", n);
13 unwrap!(Spawner::for_current_executor().await.spawn(my_task(n + 1))); 13 let spawner = unsafe { Spawner::for_current_executor().await };
14 spawner.spawn(unwrap!(my_task(n + 1)));
14} 15}
15 16
16#[embassy_executor::main] 17#[embassy_executor::main]
17async fn main(spawner: Spawner) { 18async fn main(spawner: Spawner) {
18 let _p = embassy_nrf::init(Default::default()); 19 let _p = embassy_nrf::init(Default::default());
19 info!("Hello World!"); 20 info!("Hello World!");
20 unwrap!(spawner.spawn(my_task(0))); 21 spawner.spawn(unwrap!(my_task(0)));
21} 22}
diff --git a/examples/nrf52840/src/bin/sixlowpan.rs b/examples/nrf52840/src/bin/sixlowpan.rs
new file mode 100644
index 000000000..00a597366
--- /dev/null
+++ b/examples/nrf52840/src/bin/sixlowpan.rs
@@ -0,0 +1,120 @@
1#![no_std]
2#![no_main]
3
4use core::net::Ipv6Addr;
5
6use defmt::{info, unwrap, warn};
7use embassy_executor::Spawner;
8use embassy_net::udp::{PacketMetadata, UdpMetadata, UdpSocket};
9use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint, Ipv6Cidr, StackResources, StaticConfigV6};
10use embassy_nrf::config::{Config, HfclkSource};
11use embassy_nrf::rng::Rng;
12use embassy_nrf::{bind_interrupts, embassy_net_802154_driver as net, peripherals, radio};
13use embassy_time::Delay;
14use embedded_hal_async::delay::DelayNs;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 RADIO => radio::InterruptHandler<peripherals::RADIO>;
20 RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
21});
22
23#[embassy_executor::task]
24async fn ieee802154_task(runner: net::Runner<'static, peripherals::RADIO>) -> ! {
25 runner.run().await
26}
27
28#[embassy_executor::task]
29async fn net_task(mut runner: embassy_net::Runner<'static, net::Device<'static>>) -> ! {
30 runner.run().await
31}
32
33#[embassy_executor::main]
34async fn main(spawner: Spawner) {
35 let mut config = Config::default();
36 // Necessary to run the radio nrf52840 v1.11 5.4.1
37 config.hfclk_source = HfclkSource::ExternalXtal;
38 let p = embassy_nrf::init(config);
39
40 let mac_addr: [u8; 8] = [2, 3, 4, 5, 6, 7, 8, 9];
41 static NRF802154_STATE: StaticCell<net::State<20, 20>> = StaticCell::new();
42 let (device, runner) = net::new(mac_addr, p.RADIO, Irqs, NRF802154_STATE.init(net::State::new()))
43 .await
44 .unwrap();
45
46 spawner.spawn(unwrap!(ieee802154_task(runner)));
47
48 // Swap these when flashing a second board
49 let peer = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a4);
50 let local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a5);
51
52 let config = embassy_net::Config::ipv6_static(StaticConfigV6 {
53 address: Ipv6Cidr::new(local, 64),
54 gateway: None,
55 dns_servers: Default::default(),
56 });
57
58 // Generate random seed
59 let mut rng = Rng::new(p.RNG, Irqs);
60 let mut seed = [0; 8];
61 rng.blocking_fill_bytes(&mut seed);
62 let seed = u64::from_le_bytes(seed);
63
64 // Init network stack
65 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
66 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
67
68 spawner.spawn(unwrap!(net_task(runner)));
69
70 let mut rx_buffer = [0; 2096];
71 let mut tx_buffer = [0; 2096];
72 let mut tx_m_buffer = [PacketMetadata::EMPTY; 5];
73 let mut rx_m_buffer = [PacketMetadata::EMPTY; 5];
74
75 let mut delay = Delay;
76 loop {
77 let mut socket = UdpSocket::new(
78 stack,
79 &mut tx_m_buffer,
80 &mut rx_buffer,
81 &mut rx_m_buffer,
82 &mut tx_buffer,
83 );
84 socket
85 .bind(IpListenEndpoint {
86 addr: Some(IpAddress::Ipv6(local)),
87 port: 1234,
88 })
89 .unwrap();
90 let rep = UdpMetadata {
91 endpoint: IpEndpoint {
92 addr: IpAddress::Ipv6(peer),
93 port: 1234,
94 },
95 local_address: Some(IpAddress::Ipv6(local)),
96 meta: Default::default(),
97 };
98
99 info!("Listening on {:?} UDP:1234...", local);
100
101 let mut recv_buf = [0; 12];
102 loop {
103 delay.delay_ms(2000).await;
104 if socket.may_recv() {
105 let n = match socket.recv_from(&mut recv_buf).await {
106 Ok((0, _)) => panic!(),
107 Ok((n, _)) => n,
108 Err(e) => {
109 warn!("read error: {:?}", e);
110 break;
111 }
112 };
113 info!("Received {:02x}", &recv_buf[..n]);
114 }
115
116 info!("Sending");
117 socket.send_to(b"Hello World", rep).await.unwrap();
118 }
119 }
120}
diff --git a/examples/nrf52840/src/bin/timer.rs b/examples/nrf52840/src/bin/timer.rs
index 365695a20..5331ac246 100644
--- a/examples/nrf52840/src/bin/timer.rs
+++ b/examples/nrf52840/src/bin/timer.rs
@@ -25,6 +25,6 @@ async fn run2() {
25#[embassy_executor::main] 25#[embassy_executor::main]
26async fn main(spawner: Spawner) { 26async fn main(spawner: Spawner) {
27 let _p = embassy_nrf::init(Default::default()); 27 let _p = embassy_nrf::init(Default::default());
28 unwrap!(spawner.spawn(run1())); 28 spawner.spawn(unwrap!(run1()));
29 unwrap!(spawner.spawn(run2())); 29 spawner.spawn(unwrap!(run2()));
30} 30}
diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs
index 46be8f636..51af90727 100644
--- a/examples/nrf52840/src/bin/uart_split.rs
+++ b/examples/nrf52840/src/bin/uart_split.rs
@@ -30,7 +30,7 @@ async fn main(spawner: Spawner) {
30 30
31 // Spawn a task responsible purely for reading 31 // Spawn a task responsible purely for reading
32 32
33 unwrap!(spawner.spawn(reader(rx))); 33 spawner.spawn(unwrap!(reader(rx)));
34 34
35 // Message must be in SRAM 35 // Message must be in SRAM
36 { 36 {
diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs
index 49856012d..87aa4c6c5 100644
--- a/examples/nrf52840/src/bin/usb_ethernet.rs
+++ b/examples/nrf52840/src/bin/usb_ethernet.rs
@@ -86,11 +86,11 @@ async fn main(spawner: Spawner) {
86 // Build the builder. 86 // Build the builder.
87 let usb = builder.build(); 87 let usb = builder.build();
88 88
89 unwrap!(spawner.spawn(usb_task(usb))); 89 spawner.spawn(unwrap!(usb_task(usb)));
90 90
91 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); 91 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
92 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); 92 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
93 unwrap!(spawner.spawn(usb_ncm_task(runner))); 93 spawner.spawn(unwrap!(usb_ncm_task(runner)));
94 94
95 let config = embassy_net::Config::dhcpv4(Default::default()); 95 let config = embassy_net::Config::dhcpv4(Default::default());
96 // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { 96 // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
@@ -109,7 +109,7 @@ async fn main(spawner: Spawner) {
109 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 109 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
110 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 110 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
111 111
112 unwrap!(spawner.spawn(net_task(runner))); 112 spawner.spawn(unwrap!(net_task(runner)));
113 113
114 // And now we can use it! 114 // And now we can use it!
115 115
diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs
index 5e5b4de35..00a91a233 100644
--- a/examples/nrf52840/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs
@@ -76,8 +76,8 @@ async fn main(spawner: Spawner) {
76 // Build the builder. 76 // Build the builder.
77 let usb = builder.build(); 77 let usb = builder.build();
78 78
79 unwrap!(spawner.spawn(usb_task(usb))); 79 spawner.spawn(unwrap!(usb_task(usb)));
80 unwrap!(spawner.spawn(echo_task(class))); 80 spawner.spawn(unwrap!(echo_task(class)));
81} 81}
82 82
83struct Disconnected {} 83struct Disconnected {}
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
index 26eaf485e..2dd9abfaa 100644
--- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs
+++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs
@@ -70,7 +70,7 @@ async fn main(spawner: Spawner) {
70 ) 70 )
71 .await; 71 .await;
72 72
73 unwrap!(spawner.spawn(wifi_task(runner))); 73 spawner.spawn(unwrap!(wifi_task(runner)));
74 74
75 unwrap!(control.init().await); 75 unwrap!(control.init().await);
76 unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await); 76 unwrap!(control.connect(WIFI_NETWORK, WIFI_PASSWORD).await);
@@ -92,7 +92,7 @@ async fn main(spawner: Spawner) {
92 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 92 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
93 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 93 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
94 94
95 unwrap!(spawner.spawn(net_task(runner))); 95 spawner.spawn(unwrap!(net_task(runner)));
96 96
97 // And now we can use it! 97 // And now we can use it!
98 98
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index 459c43221..425015667 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -3,28 +3,33 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 9embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } 13embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embedded-io-async = { version = "0.6.1" } 16embedded-io-async = { version = "0.6.1" }
16 17
17defmt = "0.3" 18defmt = "1.0.1"
18defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
19 20
20static_cell = "2" 21static_cell = "2"
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
23panic-probe = { version = "0.3", features = ["print-defmt"] } 24panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24rand = { version = "0.8.4", default-features = false }
25embedded-storage = "0.3.1" 25embedded-storage = "0.3.1"
26usbd-hid = "0.8.1" 26usbd-hid = "0.8.1"
27serde = { version = "1.0.136", default-features = false } 27serde = { version = "1.0.136", default-features = false }
28 28
29[profile.release] 29[profile.release]
30debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf5340" }
35]
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index 8848065d8..7f67b41f6 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -3,18 +3,26 @@ edition = "2021"
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
6 7
7[dependencies] 8[dependencies]
8embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
9embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
11 12
12defmt = "0.3" 13defmt = "1.0.1"
13defmt-rtt = "0.4" 14defmt-rtt = "1.0.0"
14panic-probe = { version = "0.3", features = ["print-defmt"] } 15panic-probe = { version = "1.0.0", features = ["print-defmt"] }
15 16
16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
17cortex-m-rt = "0.7.0" 18cortex-m-rt = "0.7.0"
18 19
20embedded-storage = "0.3.1"
21
19[profile.release] 22[profile.release]
20debug = 2 23debug = 2
24
25[package.metadata.embassy]
26build = [
27 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf54l15" }
28]
diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/nvmc.rs
new file mode 100644
index 000000000..f990604cd
--- /dev/null
+++ b/examples/nrf54l15/src/bin/nvmc.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE};
7use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Hello RRAMC NVMC!");
14
15 let mut f = Nvmc::new(p.RRAMC);
16
17 const ADDR: u32 = 0x80000;
18 let mut buf = [0u8; 4];
19
20 info!("Reading...");
21 unwrap!(f.read(ADDR, &mut buf));
22 info!("Read: {=[u8]:x}", buf);
23
24 info!("Erasing...");
25 unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32));
26
27 info!("Reading...");
28 unwrap!(f.read(ADDR, &mut buf));
29 info!("Read: {=[u8]:x}", buf);
30
31 info!("Writing...");
32 // 16 B (128-bit) write minimum
33 let out: [u8; 16] = [
34 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd,
35 ];
36 unwrap!(f.write(ADDR, &out));
37
38 info!("Reading...");
39 // Can read arbitrary sizes
40 for addr in (ADDR..ADDR + 16).step_by(4) {
41 unwrap!(f.read(addr, &mut buf));
42 info!("Read: {=[u8]:x}", buf);
43 }
44}
diff --git a/examples/nrf54l15/src/bin/temp.rs b/examples/nrf54l15/src/bin/temp.rs
new file mode 100644
index 000000000..1d28f8ecf
--- /dev/null
+++ b/examples/nrf54l15/src/bin/temp.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_nrf::temp::Temp;
7use embassy_nrf::{bind_interrupts, temp};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 TEMP => temp::InterruptHandler;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default());
18 let mut temp = Temp::new(p.TEMP, Irqs);
19
20 loop {
21 let value = temp.read().await;
22 info!("temperature: {}℃", value.to_num::<u16>());
23 Timer::after_secs(1).await;
24 }
25}
diff --git a/examples/nrf54l15/src/bin/wdt.rs b/examples/nrf54l15/src/bin/wdt.rs
new file mode 100644
index 000000000..9fe37d080
--- /dev/null
+++ b/examples/nrf54l15/src/bin/wdt.rs
@@ -0,0 +1,42 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_nrf::wdt::{Config, HaltConfig, Watchdog};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Hello WDT");
14
15 const TIMEOUT_S: u32 = 5;
16
17 let mut config = Config::default();
18 config.timeout_ticks = 32768 * TIMEOUT_S;
19
20 // This is needed for `probe-rs run` to be able to catch the panic message
21 // in the WDT interrupt. The core resets 2 ticks after firing the interrupt.
22 config.action_during_debug_halt = HaltConfig::PAUSE;
23
24 // The nrf54l15 has two watchdogs. Only one (WDT) is available in non-secure (ns) mode, as the
25 // other is reserved for the secure (s) environment. In secure mode, both are available as WDT0
26 // and WDT1.
27 info!("Watchdog launched with {} s timeout", TIMEOUT_S);
28 let (_wdt, [mut handle]) = match Watchdog::try_new(p.WDT1, config) {
29 Ok(x) => x,
30 Err(_) => {
31 info!("Watchdog already active with wrong config, waiting for it to timeout...");
32 loop {}
33 }
34 };
35
36 for wait in 1..=TIMEOUT_S {
37 info!("Waiting {} seconds ...", wait);
38 Timer::after_secs(wait as u64).await;
39 handle.pet();
40 info!("Pet watchdog");
41 }
42}
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml
index 03f38fd63..8e420477f 100644
--- a/examples/nrf9151/ns/Cargo.toml
+++ b/examples/nrf9151/ns/Cargo.toml
@@ -3,18 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
9embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
11 12
12defmt = "0.3" 13defmt = "1.0.1"
13defmt-rtt = "0.4" 14defmt-rtt = "1.0.0"
14 15
15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
16cortex-m-rt = "0.7.0" 17cortex-m-rt = "0.7.0"
17panic-probe = { version = "0.3", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18 19
19[profile.release] 20[profile.release]
20debug = 2 21debug = 2
22
23[package.metadata.embassy]
24build = [
25 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/ns" }
26]
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml
index ba88f6da3..e4ca85553 100644
--- a/examples/nrf9151/s/Cargo.toml
+++ b/examples/nrf9151/s/Cargo.toml
@@ -3,18 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-executor = { version = "0.7.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
9embassy-time = { version = "0.4.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.3.1", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.7.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
11 12
12defmt = "0.3" 13defmt = "1.0.1"
13defmt-rtt = "0.4" 14defmt-rtt = "1.0.0"
14 15
15cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
16cortex-m-rt = "0.7.0" 17cortex-m-rt = "0.7.0"
17panic-probe = { version = "0.3", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
18 19
19[profile.release] 20[profile.release]
20debug = 2 21debug = 2
22
23[package.metadata.embassy]
24build = [
25 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9151/s" }
26]
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml
index a720f2d61..d7b63a7ac 100644
--- a/examples/nrf9160/Cargo.toml
+++ b/examples/nrf9160/Cargo.toml
@@ -3,24 +3,30 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 9embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
9embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
10embassy-nrf = { version = "0.3.1", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 11embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf9160-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
11embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] } 12embassy-net-nrf91 = { version = "0.1.0", path = "../../embassy-net-nrf91", features = ["defmt"] }
12embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] } 13embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "proto-ipv4", "medium-ip"] }
13 14
14defmt = "0.3" 15defmt = "1.0.1"
15defmt-rtt = "0.4" 16defmt-rtt = "1.0.0"
16 17
17heapless = "0.8" 18heapless = "0.8"
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21static_cell = { version = "2" } 22static_cell = { version = "2" }
22embedded-io = "0.6.1" 23embedded-io = "0.6.1"
23embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 24embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
24 25
25[profile.release] 26[profile.release]
26debug = 2 27debug = 2
28
29[package.metadata.embassy]
30build = [
31 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/nrf9160" }
32]
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs
index a36b14626..7d4815699 100644
--- a/examples/nrf9160/src/bin/modem_tcp_client.rs
+++ b/examples/nrf9160/src/bin/modem_tcp_client.rs
@@ -112,7 +112,7 @@ async fn main(spawner: Spawner) {
112 112
113 info!("Hello World!"); 113 info!("Hello World!");
114 114
115 unwrap!(spawner.spawn(blink_task(p.P0_02.into()))); 115 spawner.spawn(unwrap!(blink_task(p.P0_02.into())));
116 116
117 let ipc_mem = unsafe { 117 let ipc_mem = unsafe {
118 let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit<u8>; 118 let ipc_start = &__start_ipc as *const u8 as *mut MaybeUninit<u8>;
@@ -138,8 +138,8 @@ async fn main(spawner: Spawner) {
138 static TRACE: StaticCell<TraceBuffer> = StaticCell::new(); 138 static TRACE: StaticCell<TraceBuffer> = StaticCell::new();
139 let (device, control, runner, tracer) = 139 let (device, control, runner, tracer) =
140 embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; 140 embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await;
141 unwrap!(spawner.spawn(modem_task(runner))); 141 spawner.spawn(unwrap!(modem_task(runner)));
142 unwrap!(spawner.spawn(trace_task(uart, tracer))); 142 spawner.spawn(unwrap!(trace_task(uart, tracer)));
143 143
144 let config = embassy_net::Config::default(); 144 let config = embassy_net::Config::default();
145 145
@@ -150,12 +150,12 @@ async fn main(spawner: Spawner) {
150 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); 150 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
151 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed); 151 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::<2>::new()), seed);
152 152
153 unwrap!(spawner.spawn(net_task(runner))); 153 spawner.spawn(unwrap!(net_task(runner)));
154 154
155 static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new(); 155 static CONTROL: StaticCell<context::Control<'static>> = StaticCell::new();
156 let control = CONTROL.init(context::Control::new(control, 0).await); 156 let control = CONTROL.init(context::Control::new(control, 0).await);
157 157
158 unwrap!(spawner.spawn(control_task( 158 spawner.spawn(unwrap!(control_task(
159 control, 159 control,
160 context::Config { 160 context::Config {
161 apn: b"iot.nat.es", 161 apn: b"iot.nat.es",
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 45ca30e4c..97e019cdf 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -4,23 +4,24 @@ name = "embassy-rp-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7publish = false
7 8
8[dependencies] 9[dependencies]
9embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } 10embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] } 14embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp2040"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] } 16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns", "proto-ipv4", "proto-ipv6", "multicast"] }
16embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } 19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" }
19cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } 20cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] }
20cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } 21cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] }
21 22
22defmt = "0.3" 23defmt = "1.0.1"
23defmt-rtt = "0.4" 24defmt-rtt = "1.0.0"
24fixed = "1.23.1" 25fixed = "1.23.1"
25fixed-macro = "1.2" 26fixed-macro = "1.2"
26 27
@@ -36,7 +37,7 @@ assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev
36cortex-m = { version = "0.7.6", features = ["inline-asm"] } 37cortex-m = { version = "0.7.6", features = ["inline-asm"] }
37cortex-m-rt = "0.7.0" 38cortex-m-rt = "0.7.0"
38critical-section = "1.1" 39critical-section = "1.1"
39panic-probe = { version = "0.3", features = ["print-defmt"] } 40panic-probe = { version = "1.0.0", features = ["print-defmt"] }
40display-interface-spi = "0.5.0" 41display-interface-spi = "0.5.0"
41embedded-graphics = "0.8.1" 42embedded-graphics = "0.8.1"
42mipidsi = "0.8.0" 43mipidsi = "0.8.0"
@@ -45,7 +46,6 @@ byte-slice-cast = { version = "1.2.0", default-features = false }
45smart-leds = "0.4.0" 46smart-leds = "0.4.0"
46heapless = "0.8" 47heapless = "0.8"
47usbd-hid = "0.8.1" 48usbd-hid = "0.8.1"
48rand_core = "0.6.4"
49 49
50embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 50embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
51embedded-hal-async = "1.0" 51embedded-hal-async = "1.0"
@@ -55,15 +55,14 @@ embedded-storage = { version = "0.3" }
55static_cell = "2.1" 55static_cell = "2.1"
56portable-atomic = { version = "1.5", features = ["critical-section"] } 56portable-atomic = { version = "1.5", features = ["critical-section"] }
57log = "0.4" 57log = "0.4"
58rand = { version = "0.8.5", default-features = false } 58rand = { version = "0.9.0", default-features = false }
59embedded-sdmmc = "0.7.0" 59embedded-sdmmc = "0.7.0"
60 60
61[profile.release] 61[profile.release]
62debug = 2 62# Enable generation of debug symbols even on release builds
63lto = true 63debug = true
64opt-level = 'z'
65 64
66[profile.dev] 65[package.metadata.embassy]
67debug = 2 66build = [
68lto = true 67 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/rp" }
69opt-level = "z" 68]
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs
index 1bb7c2249..015915586 100644
--- a/examples/rp/src/bin/adc.rs
+++ b/examples/rp/src/bin/adc.rs
@@ -12,9 +12,12 @@ use embassy_rp::gpio::Pull;
12use embassy_time::Timer; 12use embassy_time::Timer;
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs { 15bind_interrupts!(
16 ADC_IRQ_FIFO => InterruptHandler; 16 /// Binds the ADC interrupts.
17}); 17 struct Irqs {
18 ADC_IRQ_FIFO => InterruptHandler;
19 }
20);
18 21
19#[embassy_executor::main] 22#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
diff --git a/examples/rp/src/bin/assign_resources.rs b/examples/rp/src/bin/assign_resources.rs
index 341f54d22..4ee4278b5 100644
--- a/examples/rp/src/bin/assign_resources.rs
+++ b/examples/rp/src/bin/assign_resources.rs
@@ -26,15 +26,13 @@ async fn main(spawner: Spawner) {
26 let p = embassy_rp::init(Default::default()); 26 let p = embassy_rp::init(Default::default());
27 27
28 // 1) Assigning a resource to a task by passing parts of the peripherals. 28 // 1) Assigning a resource to a task by passing parts of the peripherals.
29 spawner 29 spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap());
30 .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21))
31 .unwrap();
32 30
33 // 2) Using the assign-resources macro to assign resources to a task. 31 // 2) Using the assign-resources macro to assign resources to a task.
34 // we perform the split, see further below for the definition of the resources struct 32 // we perform the split, see further below for the definition of the resources struct
35 let r = split_resources!(p); 33 let r = split_resources!(p);
36 // and then we can use them 34 // and then we can use them
37 spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); 35 spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap());
38} 36}
39 37
40// 1) Assigning a resource to a task by passing parts of the peripherals. 38// 1) Assigning a resource to a task by passing parts of the peripherals.
diff --git a/examples/rp/src/bin/blinky_two_channels.rs b/examples/rp/src/bin/blinky_two_channels.rs
index 51e139e94..87f3a3545 100644
--- a/examples/rp/src/bin/blinky_two_channels.rs
+++ b/examples/rp/src/bin/blinky_two_channels.rs
@@ -27,8 +27,8 @@ async fn main(spawner: Spawner) {
27 let dt = 100 * 1_000_000; 27 let dt = 100 * 1_000_000;
28 let k = 1.003; 28 let k = 1.003;
29 29
30 unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); 30 spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt))));
31 unwrap!(spawner.spawn(toggle_led( 31 spawner.spawn(unwrap!(toggle_led(
32 CHANNEL.sender(), 32 CHANNEL.sender(),
33 Duration::from_nanos((dt as f64 * k) as u64) 33 Duration::from_nanos((dt as f64 * k) as u64)
34 ))); 34 )));
diff --git a/examples/rp/src/bin/blinky_two_tasks.rs b/examples/rp/src/bin/blinky_two_tasks.rs
index 67a9108c0..aac7d928b 100644
--- a/examples/rp/src/bin/blinky_two_tasks.rs
+++ b/examples/rp/src/bin/blinky_two_tasks.rs
@@ -30,8 +30,8 @@ async fn main(spawner: Spawner) {
30 let dt = 100 * 1_000_000; 30 let dt = 100 * 1_000_000;
31 let k = 1.003; 31 let k = 1.003;
32 32
33 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); 33 spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt))));
34 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); 34 spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64))));
35} 35}
36 36
37#[embassy_executor::task(pool_size = 2)] 37#[embassy_executor::task(pool_size = 2)]
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp.rs b/examples/rp/src/bin/ethernet_w5500_icmp.rs
index 5c42b2dde..8c684a791 100644
--- a/examples/rp/src/bin/ethernet_w5500_icmp.rs
+++ b/examples/rp/src/bin/ethernet_w5500_icmp.rs
@@ -21,7 +21,6 @@ use embassy_rp::peripherals::SPI0;
21use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 21use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
22use embassy_time::{Delay, Instant, Timer}; 22use embassy_time::{Delay, Instant, Timer};
23use embedded_hal_bus::spi::ExclusiveDevice; 23use embedded_hal_bus::spi::ExclusiveDevice;
24use rand::RngCore;
25use static_cell::StaticCell; 24use static_cell::StaticCell;
26use {defmt_rtt as _, panic_probe as _}; 25use {defmt_rtt as _, panic_probe as _};
27 26
@@ -62,7 +61,7 @@ async fn main(spawner: Spawner) {
62 ) 61 )
63 .await 62 .await
64 .unwrap(); 63 .unwrap();
65 unwrap!(spawner.spawn(ethernet_task(runner))); 64 spawner.spawn(unwrap!(ethernet_task(runner)));
66 65
67 // Generate random seed 66 // Generate random seed
68 let seed = rng.next_u64(); 67 let seed = rng.next_u64();
@@ -77,7 +76,7 @@ async fn main(spawner: Spawner) {
77 ); 76 );
78 77
79 // Launch network task 78 // Launch network task
80 unwrap!(spawner.spawn(net_task(runner))); 79 spawner.spawn(unwrap!(net_task(runner)));
81 80
82 info!("Waiting for DHCP..."); 81 info!("Waiting for DHCP...");
83 let cfg = wait_for_config(stack).await; 82 let cfg = wait_for_config(stack).await;
diff --git a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
index 0724311f9..49d28071a 100644
--- a/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
+++ b/examples/rp/src/bin/ethernet_w5500_icmp_ping.rs
@@ -23,7 +23,6 @@ use embassy_rp::peripherals::SPI0;
23use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 23use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
24use embassy_time::{Delay, Duration}; 24use embassy_time::{Delay, Duration};
25use embedded_hal_bus::spi::ExclusiveDevice; 25use embedded_hal_bus::spi::ExclusiveDevice;
26use rand::RngCore;
27use static_cell::StaticCell; 26use static_cell::StaticCell;
28use {defmt_rtt as _, panic_probe as _}; 27use {defmt_rtt as _, panic_probe as _};
29 28
@@ -64,7 +63,7 @@ async fn main(spawner: Spawner) {
64 ) 63 )
65 .await 64 .await
66 .unwrap(); 65 .unwrap();
67 unwrap!(spawner.spawn(ethernet_task(runner))); 66 spawner.spawn(unwrap!(ethernet_task(runner)));
68 67
69 // Generate random seed 68 // Generate random seed
70 let seed = rng.next_u64(); 69 let seed = rng.next_u64();
@@ -79,7 +78,7 @@ async fn main(spawner: Spawner) {
79 ); 78 );
80 79
81 // Launch network task 80 // Launch network task
82 unwrap!(spawner.spawn(net_task(runner))); 81 spawner.spawn(unwrap!(net_task(runner)));
83 82
84 info!("Waiting for DHCP..."); 83 info!("Waiting for DHCP...");
85 let cfg = wait_for_config(stack).await; 84 let cfg = wait_for_config(stack).await;
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
index 2bea9fc9d..5c049ddca 100644
--- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs
+++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
@@ -18,7 +18,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
18use embassy_time::{Delay, Duration}; 18use embassy_time::{Delay, Duration};
19use embedded_hal_bus::spi::ExclusiveDevice; 19use embedded_hal_bus::spi::ExclusiveDevice;
20use embedded_io_async::Write; 20use embedded_io_async::Write;
21use rand::RngCore;
22use static_cell::StaticCell; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
@@ -65,7 +64,7 @@ async fn main(spawner: Spawner) {
65 ) 64 )
66 .await 65 .await
67 .unwrap(); 66 .unwrap();
68 unwrap!(spawner.spawn(ethernet_task(runner))); 67 spawner.spawn(unwrap!(ethernet_task(runner)));
69 68
70 // Generate random seed 69 // Generate random seed
71 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
@@ -80,7 +79,7 @@ async fn main(spawner: Spawner) {
80 ); 79 );
81 80
82 // Launch network task 81 // Launch network task
83 unwrap!(spawner.spawn(net_task(runner))); 82 spawner.spawn(unwrap!(net_task(runner)));
84 83
85 info!("Waiting for DHCP..."); 84 info!("Waiting for DHCP...");
86 let cfg = wait_for_config(stack).await; 85 let cfg = wait_for_config(stack).await;
@@ -88,8 +87,8 @@ async fn main(spawner: Spawner) {
88 info!("IP address: {:?}", local_addr); 87 info!("IP address: {:?}", local_addr);
89 88
90 // Create two sockets listening to the same port, to handle simultaneous connections 89 // Create two sockets listening to the same port, to handle simultaneous connections
91 unwrap!(spawner.spawn(listen_task(stack, 0, 1234))); 90 spawner.spawn(unwrap!(listen_task(stack, 0, 1234)));
92 unwrap!(spawner.spawn(listen_task(stack, 1, 1234))); 91 spawner.spawn(unwrap!(listen_task(stack, 1, 1234)));
93} 92}
94 93
95#[embassy_executor::task(pool_size = 2)] 94#[embassy_executor::task(pool_size = 2)]
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
index 78d1b0b83..7552e4f9b 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
@@ -20,7 +20,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::{Delay, Duration, Timer}; 20use embassy_time::{Delay, Duration, Timer};
21use embedded_hal_bus::spi::ExclusiveDevice; 21use embedded_hal_bus::spi::ExclusiveDevice;
22use embedded_io_async::Write; 22use embedded_io_async::Write;
23use rand::RngCore;
24use static_cell::StaticCell; 23use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
26 25
@@ -68,7 +67,7 @@ async fn main(spawner: Spawner) {
68 ) 67 )
69 .await 68 .await
70 .unwrap(); 69 .unwrap();
71 unwrap!(spawner.spawn(ethernet_task(runner))); 70 spawner.spawn(unwrap!(ethernet_task(runner)));
72 71
73 // Generate random seed 72 // Generate random seed
74 let seed = rng.next_u64(); 73 let seed = rng.next_u64();
@@ -83,7 +82,7 @@ async fn main(spawner: Spawner) {
83 ); 82 );
84 83
85 // Launch network task 84 // Launch network task
86 unwrap!(spawner.spawn(net_task(runner))); 85 spawner.spawn(unwrap!(net_task(runner)));
87 86
88 info!("Waiting for DHCP..."); 87 info!("Waiting for DHCP...");
89 let cfg = wait_for_config(stack).await; 88 let cfg = wait_for_config(stack).await;
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
index 25a38c714..7b6fecad4 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
@@ -19,7 +19,6 @@ use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::{Delay, Duration}; 19use embassy_time::{Delay, Duration};
20use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
21use embedded_io_async::Write; 21use embedded_io_async::Write;
22use rand::RngCore;
23use static_cell::StaticCell; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
@@ -67,7 +66,7 @@ async fn main(spawner: Spawner) {
67 ) 66 )
68 .await 67 .await
69 .unwrap(); 68 .unwrap();
70 unwrap!(spawner.spawn(ethernet_task(runner))); 69 spawner.spawn(unwrap!(ethernet_task(runner)));
71 70
72 // Generate random seed 71 // Generate random seed
73 let seed = rng.next_u64(); 72 let seed = rng.next_u64();
@@ -82,7 +81,7 @@ async fn main(spawner: Spawner) {
82 ); 81 );
83 82
84 // Launch network task 83 // Launch network task
85 unwrap!(spawner.spawn(net_task(runner))); 84 spawner.spawn(unwrap!(net_task(runner)));
86 85
87 info!("Waiting for DHCP..."); 86 info!("Waiting for DHCP...");
88 let cfg = wait_for_config(stack).await; 87 let cfg = wait_for_config(stack).await;
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs
index 683e29222..f099490f5 100644
--- a/examples/rp/src/bin/ethernet_w5500_udp.rs
+++ b/examples/rp/src/bin/ethernet_w5500_udp.rs
@@ -18,7 +18,6 @@ use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::Delay; 19use embassy_time::Delay;
20use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
21use rand::RngCore;
22use static_cell::StaticCell; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
@@ -65,7 +64,7 @@ async fn main(spawner: Spawner) {
65 ) 64 )
66 .await 65 .await
67 .unwrap(); 66 .unwrap();
68 unwrap!(spawner.spawn(ethernet_task(runner))); 67 spawner.spawn(unwrap!(ethernet_task(runner)));
69 68
70 // Generate random seed 69 // Generate random seed
71 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
@@ -80,7 +79,7 @@ async fn main(spawner: Spawner) {
80 ); 79 );
81 80
82 // Launch network task 81 // Launch network task
83 unwrap!(spawner.spawn(net_task(runner))); 82 spawner.spawn(unwrap!(net_task(runner)));
84 83
85 info!("Waiting for DHCP..."); 84 info!("Waiting for DHCP...");
86 let cfg = wait_for_config(stack).await; 85 let cfg = wait_for_config(stack).await;
diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
new file mode 100644
index 000000000..f51df2df9
--- /dev/null
+++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
@@ -0,0 +1,155 @@
1//! This example implements a TCP echo server on port 1234 and using DHCP.
2//! Send it some data, you should see it echoed back and printed in the console.
3//!
4//! Example written for the [`WIZnet W55RP20-EVB-Pico`](https://docs.wiznet.io/Product/ioNIC/W55RP20/w55rp20-evb-pico) board.
5//! Note: the W55RP20 is a single package that contains both a RP2040 and the Wiznet W5500 ethernet
6//! controller
7
8#![no_std]
9#![no_main]
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_futures::yield_now;
14use embassy_net::{Stack, StackResources};
15use embassy_net_wiznet::chip::W5500;
16use embassy_net_wiznet::*;
17use embassy_rp::clocks::RoscRng;
18use embassy_rp::gpio::{Input, Level, Output, Pull};
19use embassy_rp::peripherals::PIO0;
20use embassy_rp::pio_programs::spi::Spi;
21use embassy_rp::spi::{Async, Config as SpiConfig};
22use embassy_rp::{bind_interrupts, pio};
23use embassy_time::{Delay, Duration};
24use embedded_hal_bus::spi::ExclusiveDevice;
25use embedded_io_async::Write;
26use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _};
28
29bind_interrupts!(struct Irqs {
30 PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
31});
32
33#[embassy_executor::task]
34async fn ethernet_task(
35 runner: Runner<
36 'static,
37 W5500,
38 ExclusiveDevice<Spi<'static, PIO0, 0, Async>, Output<'static>, Delay>,
39 Input<'static>,
40 Output<'static>,
41 >,
42) -> ! {
43 runner.run().await
44}
45
46#[embassy_executor::task]
47async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
48 runner.run().await
49}
50
51#[embassy_executor::main]
52async fn main(spawner: Spawner) {
53 let p = embassy_rp::init(Default::default());
54 let mut rng = RoscRng;
55 let mut led = Output::new(p.PIN_19, Level::Low);
56
57 // The W55RP20 uses a PIO unit for SPI communication, once the SPI bus has been formed using a
58 // PIO statemachine everything else is generally unchanged from the other examples that use the W5500
59 let mosi = p.PIN_23;
60 let miso = p.PIN_22;
61 let clk = p.PIN_21;
62
63 let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs);
64
65 // Construct an SPI driver backed by a PIO state machine
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
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);
70
71 // Further control pins
72 let cs = Output::new(p.PIN_20, Level::High);
73 let w5500_int = Input::new(p.PIN_24, Pull::Up);
74 let w5500_reset = Output::new(p.PIN_25, Level::High);
75
76 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
77 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
78 let state = STATE.init(State::<8, 8>::new());
79 let (device, runner) = embassy_net_wiznet::new(
80 mac_addr,
81 state,
82 ExclusiveDevice::new(spi, cs, Delay),
83 w5500_int,
84 w5500_reset,
85 )
86 .await
87 .unwrap();
88 spawner.spawn(unwrap!(ethernet_task(runner)));
89
90 // Generate random seed
91 let seed = rng.next_u64();
92
93 // Init network stack
94 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
95 let (stack, runner) = embassy_net::new(
96 device,
97 embassy_net::Config::dhcpv4(Default::default()),
98 RESOURCES.init(StackResources::new()),
99 seed,
100 );
101
102 // Launch network task
103 spawner.spawn(unwrap!(net_task(runner)));
104
105 info!("Waiting for DHCP...");
106 let cfg = wait_for_config(stack).await;
107 let local_addr = cfg.address.address();
108 info!("IP address: {:?}", local_addr);
109
110 let mut rx_buffer = [0; 4096];
111 let mut tx_buffer = [0; 4096];
112 let mut buf = [0; 4096];
113 loop {
114 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
115 socket.set_timeout(Some(Duration::from_secs(10)));
116
117 led.set_low();
118 info!("Listening on TCP:1234...");
119 if let Err(e) = socket.accept(1234).await {
120 warn!("accept error: {:?}", e);
121 continue;
122 }
123 info!("Received connection from {:?}", socket.remote_endpoint());
124 led.set_high();
125
126 loop {
127 let n = match socket.read(&mut buf).await {
128 Ok(0) => {
129 warn!("read EOF");
130 break;
131 }
132 Ok(n) => n,
133 Err(e) => {
134 warn!("{:?}", e);
135 break;
136 }
137 };
138 info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap());
139
140 if let Err(e) = socket.write_all(&buf[..n]).await {
141 warn!("write error: {:?}", e);
142 break;
143 }
144 }
145 }
146}
147
148async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
149 loop {
150 if let Some(config) = stack.config_v4() {
151 return config.clone();
152 }
153 yield_now().await;
154 }
155}
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs
index c9c8a2760..317921374 100644
--- a/examples/rp/src/bin/i2c_blocking.rs
+++ b/examples/rp/src/bin/i2c_blocking.rs
@@ -49,7 +49,9 @@ async fn main(_spawner: Spawner) {
49 let scl = p.PIN_15; 49 let scl = p.PIN_15;
50 50
51 info!("set up i2c "); 51 info!("set up i2c ");
52 let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); 52 // Default I2C config enables internal pull-up resistors.
53 let config = Config::default();
54 let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, config);
53 55
54 use mcp23017::*; 56 use mcp23017::*;
55 57
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs
index 08f31001b..e2b8b0d06 100644
--- a/examples/rp/src/bin/i2c_slave.rs
+++ b/examples/rp/src/bin/i2c_slave.rs
@@ -105,7 +105,7 @@ async fn main(spawner: Spawner) {
105 config.addr = DEV_ADDR as u16; 105 config.addr = DEV_ADDR as u16;
106 let device = i2c_slave::I2cSlave::new(p.I2C1, d_scl, d_sda, Irqs, config); 106 let device = i2c_slave::I2cSlave::new(p.I2C1, d_scl, d_sda, Irqs, config);
107 107
108 unwrap!(spawner.spawn(device_task(device))); 108 spawner.spawn(unwrap!(device_task(device)));
109 109
110 let c_sda = p.PIN_0; 110 let c_sda = p.PIN_0;
111 let c_scl = p.PIN_1; 111 let c_scl = p.PIN_1;
@@ -113,5 +113,5 @@ async fn main(spawner: Spawner) {
113 config.frequency = 1_000_000; 113 config.frequency = 1_000_000;
114 let controller = i2c::I2c::new_async(p.I2C0, c_scl, c_sda, Irqs, config); 114 let controller = i2c::I2c::new_async(p.I2C0, c_scl, c_sda, Irqs, config);
115 115
116 unwrap!(spawner.spawn(controller_task(controller))); 116 spawner.spawn(unwrap!(controller_task(controller)));
117} 117}
diff --git a/examples/rp/src/bin/interrupt.rs b/examples/rp/src/bin/interrupt.rs
index 787cdc112..2748f778a 100644
--- a/examples/rp/src/bin/interrupt.rs
+++ b/examples/rp/src/bin/interrupt.rs
@@ -51,7 +51,7 @@ async fn main(spawner: Spawner) {
51 // No Mutex needed when sharing within the same executor/prio level 51 // No Mutex needed when sharing within the same executor/prio level
52 static AVG: StaticCell<Cell<u32>> = StaticCell::new(); 52 static AVG: StaticCell<Cell<u32>> = StaticCell::new();
53 let avg = AVG.init(Default::default()); 53 let avg = AVG.init(Default::default());
54 spawner.must_spawn(processing(avg)); 54 spawner.spawn(processing(avg).unwrap());
55 55
56 let mut ticker = Ticker::every(Duration::from_secs(1)); 56 let mut ticker = Ticker::every(Duration::from_secs(1));
57 loop { 57 loop {
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index 7cb546c91..3a6367420 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -35,12 +35,12 @@ fn main() -> ! {
35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, 35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
36 move || { 36 move || {
37 let executor1 = EXECUTOR1.init(Executor::new()); 37 let executor1 = EXECUTOR1.init(Executor::new());
38 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); 38 executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led))));
39 }, 39 },
40 ); 40 );
41 41
42 let executor0 = EXECUTOR0.init(Executor::new()); 42 let executor0 = EXECUTOR0.init(Executor::new());
43 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 43 executor0.run(|spawner| spawner.spawn(unwrap!(core0_task())));
44} 44}
45 45
46#[embassy_executor::task] 46#[embassy_executor::task]
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs
index 2b397f97d..96cdf8fb1 100644
--- a/examples/rp/src/bin/multiprio.rs
+++ b/examples/rp/src/bin/multiprio.rs
@@ -130,16 +130,16 @@ fn main() -> ! {
130 // High-priority executor: SWI_IRQ_1, priority level 2 130 // High-priority executor: SWI_IRQ_1, priority level 2
131 interrupt::SWI_IRQ_1.set_priority(Priority::P2); 131 interrupt::SWI_IRQ_1.set_priority(Priority::P2);
132 let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); 132 let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1);
133 unwrap!(spawner.spawn(run_high())); 133 spawner.spawn(unwrap!(run_high()));
134 134
135 // Medium-priority executor: SWI_IRQ_0, priority level 3 135 // Medium-priority executor: SWI_IRQ_0, priority level 3
136 interrupt::SWI_IRQ_0.set_priority(Priority::P3); 136 interrupt::SWI_IRQ_0.set_priority(Priority::P3);
137 let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); 137 let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0);
138 unwrap!(spawner.spawn(run_med())); 138 spawner.spawn(unwrap!(run_med()));
139 139
140 // Low priority executor: runs in thread mode, using WFE/SEV 140 // Low priority executor: runs in thread mode, using WFE/SEV
141 let executor = EXECUTOR_LOW.init(Executor::new()); 141 let executor = EXECUTOR_LOW.init(Executor::new());
142 executor.run(|spawner| { 142 executor.run(|spawner| {
143 unwrap!(spawner.spawn(run_low())); 143 spawner.spawn(unwrap!(run_low()));
144 }); 144 });
145} 145}
diff --git a/examples/rp/src/bin/orchestrate_tasks.rs b/examples/rp/src/bin/orchestrate_tasks.rs
index 5e2775793..9f25e1087 100644
--- a/examples/rp/src/bin/orchestrate_tasks.rs
+++ b/examples/rp/src/bin/orchestrate_tasks.rs
@@ -29,7 +29,6 @@ use 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};
31use embassy_time::{Duration, Timer}; 31use embassy_time::{Duration, Timer};
32use rand::RngCore;
33use {defmt_rtt as _, panic_probe as _}; 32use {defmt_rtt as _, panic_probe as _};
34 33
35// Hardware resource assignment. See other examples for different ways of doing this. 34// Hardware resource assignment. See other examples for different ways of doing this.
@@ -130,13 +129,13 @@ async fn main(spawner: Spawner) {
130 let p = embassy_rp::init(Default::default()); 129 let p = embassy_rp::init(Default::default());
131 let r = split_resources! {p}; 130 let r = split_resources! {p};
132 131
133 spawner.spawn(orchestrate(spawner)).unwrap(); 132 spawner.spawn(orchestrate(spawner).unwrap());
134 spawner.spawn(random_60s(spawner)).unwrap(); 133 spawner.spawn(random_60s(spawner).unwrap());
135 spawner.spawn(random_90s(spawner)).unwrap(); 134 spawner.spawn(random_90s(spawner).unwrap());
136 // `random_30s` is not spawned here, butin the orchestrate task depending on state 135 // `random_30s` is not spawned here, butin the orchestrate task depending on state
137 spawner.spawn(usb_power(spawner, r.vbus)).unwrap(); 136 spawner.spawn(usb_power(spawner, r.vbus).unwrap());
138 spawner.spawn(vsys_voltage(spawner, r.vsys)).unwrap(); 137 spawner.spawn(vsys_voltage(spawner, r.vsys).unwrap());
139 spawner.spawn(consumer(spawner)).unwrap(); 138 spawner.spawn(consumer(spawner).unwrap());
140} 139}
141 140
142/// Main task that processes all events and updates system state. 141/// Main task that processes all events and updates system state.
@@ -199,7 +198,7 @@ async fn orchestrate(spawner: Spawner) {
199 drop(state); 198 drop(state);
200 if respawn_first_random_seed_task { 199 if respawn_first_random_seed_task {
201 info!("(Re)-Starting the first random signal task"); 200 info!("(Re)-Starting the first random signal task");
202 spawner.spawn(random_30s(spawner)).unwrap(); 201 spawner.spawn(random_30s(spawner).unwrap());
203 } 202 }
204 } 203 }
205 _ => {} 204 _ => {}
diff --git a/examples/rp/src/bin/overclock.rs b/examples/rp/src/bin/overclock.rs
index 9c78e0c9d..83b17308b 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, ClockConfig}; 10use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig};
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};
@@ -18,10 +18,7 @@ const COUNT_TO: i64 = 10_000_000;
18#[embassy_executor::main] 18#[embassy_executor::main]
19async fn main(_spawner: Spawner) -> ! { 19async fn main(_spawner: Spawner) -> ! {
20 // Set up for clock frequency of 200 MHz, setting all necessary defaults. 20 // Set up for clock frequency of 200 MHz, setting all necessary defaults.
21 let config = Config::new(ClockConfig::system_freq(200_000_000)); 21 let config = Config::new(ClockConfig::system_freq(200_000_000).unwrap());
22
23 // Show the voltage scale for verification
24 info!("System core voltage: {}", Debug2Format(&config.clocks.core_voltage));
25 22
26 // Initialize the peripherals 23 // Initialize the peripherals
27 let p = embassy_rp::init(config); 24 let p = embassy_rp::init(config);
@@ -29,6 +26,9 @@ async fn main(_spawner: Spawner) -> ! {
29 // Show CPU frequency for verification 26 // Show CPU frequency for verification
30 let sys_freq = clk_sys_freq(); 27 let sys_freq = clk_sys_freq();
31 info!("System clock frequency: {} MHz", sys_freq / 1_000_000); 28 info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
29 // Show core voltage for verification
30 let core_voltage = core_voltage().unwrap();
31 info!("Core voltage: {}", core_voltage);
32 32
33 // LED to indicate the system is running 33 // LED to indicate the system is running
34 let mut led = Output::new(p.PIN_25, Level::Low); 34 let mut led = Output::new(p.PIN_25, Level::Low);
diff --git a/examples/rp/src/bin/overclock_manual.rs b/examples/rp/src/bin/overclock_manual.rs
index 35160b250..dea5cfb3c 100644
--- a/examples/rp/src/bin/overclock_manual.rs
+++ b/examples/rp/src/bin/overclock_manual.rs
@@ -7,8 +7,7 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::clocks; 10use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig};
11use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig};
12use embassy_rp::config::Config; 11use embassy_rp::config::Config;
13use embassy_rp::gpio::{Level, Output}; 12use embassy_rp::gpio::{Level, Output};
14use embassy_time::{Duration, Instant, Timer}; 13use embassy_time::{Duration, Instant, Timer};
@@ -41,9 +40,12 @@ async fn main(_spawner: Spawner) -> ! {
41 // Initialize with our manual overclock configuration 40 // Initialize with our manual overclock configuration
42 let p = embassy_rp::init(configure_manual_overclock()); 41 let p = embassy_rp::init(configure_manual_overclock());
43 42
44 // Verify the actual system clock frequency 43 // Show CPU frequency for verification
45 let sys_freq = clocks::clk_sys_freq(); 44 let sys_freq = clk_sys_freq();
46 info!("System clock frequency: {} MHz", sys_freq / 1_000_000); 45 info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
46 // Show core voltage for verification
47 let core_voltage = core_voltage().unwrap();
48 info!("Core voltage: {}", core_voltage);
47 49
48 // LED to indicate the system is running 50 // LED to indicate the system is running
49 let mut led = Output::new(p.PIN_25, Level::Low); 51 let mut led = Output::new(p.PIN_25, Level::Low);
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index bf6dbee69..1743a417e 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -125,7 +125,7 @@ async fn main(spawner: Spawner) {
125 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); 125 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0);
126 setup_pio_task_sm1(&mut common, &mut sm1); 126 setup_pio_task_sm1(&mut common, &mut sm1);
127 setup_pio_task_sm2(&mut common, &mut sm2); 127 setup_pio_task_sm2(&mut common, &mut sm2);
128 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 128 spawner.spawn(pio_task_sm0(sm0).unwrap());
129 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 129 spawner.spawn(pio_task_sm1(sm1).unwrap());
130 spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); 130 spawner.spawn(pio_task_sm2(irq3, sm2).unwrap());
131} 131}
diff --git a/examples/rp/src/bin/pio_i2s.rs b/examples/rp/src/bin/pio_i2s.rs
index 192c8f854..695a74cc3 100644
--- a/examples/rp/src/bin/pio_i2s.rs
+++ b/examples/rp/src/bin/pio_i2s.rs
@@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs {
27 27
28const SAMPLE_RATE: u32 = 48_000; 28const SAMPLE_RATE: u32 = 48_000;
29const BIT_DEPTH: u32 = 16; 29const BIT_DEPTH: u32 = 16;
30const CHANNELS: u32 = 2;
31 30
32#[embassy_executor::main] 31#[embassy_executor::main]
33async fn main(_spawner: Spawner) { 32async fn main(_spawner: Spawner) {
@@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) {
50 left_right_clock_pin, 49 left_right_clock_pin,
51 SAMPLE_RATE, 50 SAMPLE_RATE,
52 BIT_DEPTH, 51 BIT_DEPTH,
53 CHANNELS,
54 &program, 52 &program,
55 ); 53 );
56 54
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs
index 379e2b8f9..102f13c45 100644
--- a/examples/rp/src/bin/pio_onewire.rs
+++ b/examples/rp/src/bin/pio_onewire.rs
@@ -1,4 +1,5 @@
1//! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors. 1//! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors.
2//! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example.
2 3
3#![no_std] 4#![no_std]
4#![no_main] 5#![no_main]
diff --git a/examples/rp/src/bin/pio_onewire_parasite.rs b/examples/rp/src/bin/pio_onewire_parasite.rs
new file mode 100644
index 000000000..fd076dee0
--- /dev/null
+++ b/examples/rp/src/bin/pio_onewire_parasite.rs
@@ -0,0 +1,89 @@
1//! This example shows how you can use PIO to read one or more `DS18B20`
2//! one-wire temperature sensors using parasite power.
3//! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet.
4//! For externally powered sensors, use the pio_onewire.rs example.
5
6#![no_std]
7#![no_main]
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts;
11use embassy_rp::peripherals::PIO0;
12use embassy_rp::pio::{InterruptHandler, Pio};
13use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch};
14use embassy_time::Duration;
15use heapless::Vec;
16use {defmt_rtt as _, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 PIO0_IRQ_0 => InterruptHandler<PIO0>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_rp::init(Default::default());
25 let mut pio = Pio::new(p.PIO0, Irqs);
26
27 let prg = PioOneWireProgram::new(&mut pio.common);
28 let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg);
29
30 info!("Starting onewire search");
31
32 let mut devices = Vec::<u64, 10>::new();
33 let mut search = PioOneWireSearch::new();
34 for _ in 0..10 {
35 if !search.is_finished() {
36 if let Some(address) = search.next(&mut onewire).await {
37 if crc8(&address.to_le_bytes()) == 0 {
38 info!("Found address: {:x}", address);
39 let _ = devices.push(address);
40 } else {
41 warn!("Found invalid address: {:x}", address);
42 }
43 }
44 }
45 }
46
47 info!("Search done, found {} devices", devices.len());
48
49 loop {
50 // Read all devices one by one
51 for device in &devices {
52 onewire.reset().await;
53 onewire.write_bytes(&[0x55]).await; // Match rom
54 onewire.write_bytes(&device.to_le_bytes()).await;
55 // 750 ms delay required for default 12-bit resolution.
56 onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await;
57
58 onewire.reset().await;
59 onewire.write_bytes(&[0x55]).await; // Match rom
60 onewire.write_bytes(&device.to_le_bytes()).await;
61 onewire.write_bytes(&[0xBE]).await; // Read scratchpad
62
63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp);
68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data);
70 }
71 }
72 }
73}
74
75fn crc8(data: &[u8]) -> u8 {
76 let mut crc = 0;
77 for b in data {
78 let mut data_byte = *b;
79 for _ in 0..8 {
80 let temp = (crc ^ data_byte) & 0x01;
81 crc >>= 1;
82 if temp != 0 {
83 crc ^= 0x8C;
84 }
85 data_byte >>= 1;
86 }
87 }
88 crc
89}
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs
index 2750f61ae..2fc19970b 100644
--- a/examples/rp/src/bin/pio_rotary_encoder.rs
+++ b/examples/rp/src/bin/pio_rotary_encoder.rs
@@ -50,6 +50,6 @@ async fn main(spawner: Spawner) {
50 let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); 50 let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg);
51 let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); 51 let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg);
52 52
53 spawner.must_spawn(encoder_0(encoder0)); 53 spawner.spawn(encoder_0(encoder0).unwrap());
54 spawner.must_spawn(encoder_1(encoder1)); 54 spawner.spawn(encoder_1(encoder1).unwrap());
55} 55}
diff --git a/examples/rp/src/bin/pio_spi.rs b/examples/rp/src/bin/pio_spi.rs
new file mode 100644
index 000000000..4218327ec
--- /dev/null
+++ b/examples/rp/src/bin/pio_spi.rs
@@ -0,0 +1,48 @@
1//! This example shows how to use a PIO state machine as an additional SPI
2//! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is
3//! specified in this example.
4//!
5//! If you connect pin 6 and 7 you should get the same data back.
6
7#![no_std]
8#![no_main]
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_rp::peripherals::PIO0;
13use embassy_rp::pio_programs::spi::Spi;
14use embassy_rp::spi::Config;
15use embassy_rp::{bind_interrupts, pio};
16use embassy_time::Timer;
17use {defmt_rtt as _, panic_probe as _};
18
19bind_interrupts!(struct Irqs {
20 PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
21});
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 let p = embassy_rp::init(Default::default());
26 info!("Hello World!");
27
28 // These pins are routed to different hardware SPI peripherals, but we can
29 // use them together regardless
30 let mosi = p.PIN_6; // SPI0 SCLK
31 let miso = p.PIN_7; // SPI0 MOSI
32 let clk = p.PIN_8; // SPI1 MISO
33
34 let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs);
35
36 // Construct an SPI driver backed by a PIO state machine
37 let mut spi = Spi::new_blocking(&mut common, sm0, clk, mosi, miso, Config::default());
38
39 loop {
40 let tx_buf = [1_u8, 2, 3, 4, 5, 6];
41 let mut rx_buf = [0_u8; 6];
42
43 spi.blocking_transfer(&mut rx_buf, &tx_buf).unwrap();
44 info!("{:?}", rx_buf);
45
46 Timer::after_secs(1).await;
47 }
48}
diff --git a/examples/rp/src/bin/pio_spi_async.rs b/examples/rp/src/bin/pio_spi_async.rs
new file mode 100644
index 000000000..18b57d26e
--- /dev/null
+++ b/examples/rp/src/bin/pio_spi_async.rs
@@ -0,0 +1,57 @@
1//! This example shows how to use a PIO state machine as an additional SPI
2//! (Serial Peripheral Interface) on the RP2040 chip. No specific hardware is
3//! specified in this example.
4//!
5//! If you connect pin 6 and 7 you should get the same data back.
6
7#![no_std]
8#![no_main]
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_rp::peripherals::PIO0;
13use embassy_rp::pio_programs::spi::Spi;
14use embassy_rp::spi::Config;
15use embassy_rp::{bind_interrupts, pio};
16use embassy_time::Timer;
17use {defmt_rtt as _, panic_probe as _};
18
19bind_interrupts!(struct Irqs {
20 PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
21});
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 let p = embassy_rp::init(Default::default());
26 info!("Hello World!");
27
28 // These pins are routed to different hardware SPI peripherals, but we can
29 // use them together regardless
30 let mosi = p.PIN_6; // SPI0 SCLK
31 let miso = p.PIN_7; // SPI0 MOSI
32 let clk = p.PIN_8; // SPI1 MISO
33
34 let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs);
35
36 // Construct an SPI driver backed by a PIO state machine
37 let mut spi = Spi::new(
38 &mut common,
39 sm0,
40 clk,
41 mosi,
42 miso,
43 p.DMA_CH0,
44 p.DMA_CH1,
45 Config::default(),
46 );
47
48 loop {
49 let tx_buf = [1_u8, 2, 3, 4, 5, 6];
50 let mut rx_buf = [0_u8; 6];
51
52 spi.transfer(&mut rx_buf, &tx_buf).await.unwrap();
53 info!("{:?}", rx_buf);
54
55 Timer::after_secs(1).await;
56 }
57}
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs
index 04374323d..9dd07ab6e 100644
--- a/examples/rp/src/bin/pwm.rs
+++ b/examples/rp/src/bin/pwm.rs
@@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _};
18#[embassy_executor::main] 18#[embassy_executor::main]
19async fn main(spawner: Spawner) { 19async fn main(spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); 21 spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap());
22 spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); 22 spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap());
23} 23}
24 24
25/// Demonstrate PWM by modifying & applying the config 25/// Demonstrate PWM by modifying & applying the config
diff --git a/examples/rp/src/bin/shared_bus.rs b/examples/rp/src/bin/shared_bus.rs
index 9267dfccb..db7566b1a 100644
--- a/examples/rp/src/bin/shared_bus.rs
+++ b/examples/rp/src/bin/shared_bus.rs
@@ -35,8 +35,8 @@ async fn main(spawner: Spawner) {
35 static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); 35 static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new();
36 let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); 36 let i2c_bus = I2C_BUS.init(Mutex::new(i2c));
37 37
38 spawner.must_spawn(i2c_task_a(i2c_bus)); 38 spawner.spawn(i2c_task_a(i2c_bus).unwrap());
39 spawner.must_spawn(i2c_task_b(i2c_bus)); 39 spawner.spawn(i2c_task_b(i2c_bus).unwrap());
40 40
41 // Shared SPI bus 41 // Shared SPI bus
42 let spi_cfg = spi::Config::default(); 42 let spi_cfg = spi::Config::default();
@@ -48,8 +48,8 @@ async fn main(spawner: Spawner) {
48 let cs_a = Output::new(p.PIN_0, Level::High); 48 let cs_a = Output::new(p.PIN_0, Level::High);
49 let cs_b = Output::new(p.PIN_1, Level::High); 49 let cs_b = Output::new(p.PIN_1, Level::High);
50 50
51 spawner.must_spawn(spi_task_a(spi_bus, cs_a)); 51 spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap());
52 spawner.must_spawn(spi_task_b(spi_bus, cs_b)); 52 spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap());
53} 53}
54 54
55#[embassy_executor::task] 55#[embassy_executor::task]
diff --git a/examples/rp/src/bin/sharing.rs b/examples/rp/src/bin/sharing.rs
index 497c4f845..d4c89946b 100644
--- a/examples/rp/src/bin/sharing.rs
+++ b/examples/rp/src/bin/sharing.rs
@@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt};
27use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 27use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
28use embassy_sync::{blocking_mutex, mutex}; 28use embassy_sync::{blocking_mutex, mutex};
29use embassy_time::{Duration, Ticker}; 29use embassy_time::{Duration, Ticker};
30use rand::RngCore;
31use static_cell::{ConstStaticCell, StaticCell}; 30use static_cell::{ConstStaticCell, StaticCell};
32use {defmt_rtt as _, panic_probe as _}; 31use {defmt_rtt as _, panic_probe as _};
33 32
@@ -69,7 +68,7 @@ fn main() -> ! {
69 // High-priority executor: runs in interrupt mode 68 // High-priority executor: runs in interrupt mode
70 interrupt::SWI_IRQ_0.set_priority(Priority::P3); 69 interrupt::SWI_IRQ_0.set_priority(Priority::P3);
71 let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); 70 let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0);
72 spawner.must_spawn(task_a(uart)); 71 spawner.spawn(task_a(uart).unwrap());
73 72
74 // Low priority executor: runs in thread mode 73 // Low priority executor: runs in thread mode
75 let executor = EXECUTOR_LOW.init(Executor::new()); 74 let executor = EXECUTOR_LOW.init(Executor::new());
@@ -84,8 +83,8 @@ fn main() -> ! {
84 static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); 83 static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 }));
85 let ref_cell = REF_CELL.take(); 84 let ref_cell = REF_CELL.take();
86 85
87 spawner.must_spawn(task_b(uart, cell, ref_cell)); 86 spawner.spawn(task_b(uart, cell, ref_cell).unwrap());
88 spawner.must_spawn(task_c(cell, ref_cell)); 87 spawner.spawn(task_c(cell, ref_cell).unwrap());
89 }); 88 });
90} 89}
91 90
diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs
index 30afc253d..fdef09d4b 100644
--- a/examples/rp/src/bin/spi_gc9a01.rs
+++ b/examples/rp/src/bin/spi_gc9a01.rs
@@ -26,7 +26,6 @@ use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
26use mipidsi::models::GC9A01; 26use mipidsi::models::GC9A01;
27use mipidsi::options::{ColorInversion, ColorOrder}; 27use mipidsi::options::{ColorInversion, ColorOrder};
28use mipidsi::Builder; 28use mipidsi::Builder;
29use rand_core::RngCore;
30use {defmt_rtt as _, panic_probe as _}; 29use {defmt_rtt as _, panic_probe as _};
31 30
32const DISPLAY_FREQ: u32 = 64_000_000; 31const DISPLAY_FREQ: u32 = 64_000_000;
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs
index 3adbc18ab..820daed96 100644
--- a/examples/rp/src/bin/uart_buffered_split.rs
+++ b/examples/rp/src/bin/uart_buffered_split.rs
@@ -33,7 +33,7 @@ async fn main(spawner: Spawner) {
33 let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); 33 let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default());
34 let (mut tx, rx) = uart.split(); 34 let (mut tx, rx) = uart.split();
35 35
36 unwrap!(spawner.spawn(reader(rx))); 36 spawner.spawn(unwrap!(reader(rx)));
37 37
38 info!("Writing..."); 38 info!("Writing...");
39 loop { 39 loop {
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index c2c8dfad8..573b45b51 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -27,7 +27,7 @@ async fn main(spawner: Spawner) {
27 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); 27 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
28 let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); 28 let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default());
29 29
30 unwrap!(spawner.spawn(reader(uart_rx))); 30 spawner.spawn(unwrap!(reader(uart_rx)));
31 31
32 info!("Writing..."); 32 info!("Writing...");
33 loop { 33 loop {
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 2add20bc6..912e52e96 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -17,7 +17,6 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState
17use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 17use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
18use embassy_usb::{Builder, Config, UsbDevice}; 18use embassy_usb::{Builder, Config, UsbDevice};
19use embedded_io_async::Write; 19use embedded_io_async::Write;
20use rand::RngCore;
21use static_cell::StaticCell; 20use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
23 22
@@ -85,11 +84,11 @@ async fn main(spawner: Spawner) {
85 // Build the builder. 84 // Build the builder.
86 let usb = builder.build(); 85 let usb = builder.build();
87 86
88 unwrap!(spawner.spawn(usb_task(usb))); 87 spawner.spawn(unwrap!(usb_task(usb)));
89 88
90 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); 89 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
91 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); 90 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
92 unwrap!(spawner.spawn(usb_ncm_task(runner))); 91 spawner.spawn(unwrap!(usb_ncm_task(runner)));
93 92
94 let config = embassy_net::Config::dhcpv4(Default::default()); 93 let config = embassy_net::Config::dhcpv4(Default::default());
95 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { 94 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
@@ -105,7 +104,7 @@ async fn main(spawner: Spawner) {
105 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 104 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
106 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 105 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
107 106
108 unwrap!(spawner.spawn(net_task(runner))); 107 spawner.spawn(unwrap!(net_task(runner)));
109 108
110 // And now we can use it! 109 // And now we can use it!
111 110
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs
index 5ee650910..4454c593c 100644..100755
--- a/examples/rp/src/bin/usb_hid_mouse.rs
+++ b/examples/rp/src/bin/usb_hid_mouse.rs
@@ -85,8 +85,8 @@ async fn main(_spawner: Spawner) {
85 _ = Timer::after_secs(1).await; 85 _ = Timer::after_secs(1).await;
86 let report = MouseReport { 86 let report = MouseReport {
87 buttons: 0, 87 buttons: 0,
88 x: rng.gen_range(-100..100), // random small x movement 88 x: rng.random_range(-100..100), // random small x movement
89 y: rng.gen_range(-100..100), // random small y movement 89 y: rng.random_range(-100..100), // random small y movement
90 wheel: 0, 90 wheel: 0,
91 pan: 0, 91 pan: 0,
92 }; 92 };
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs
index af401ed63..ed2333efc 100644
--- a/examples/rp/src/bin/usb_logger.rs
+++ b/examples/rp/src/bin/usb_logger.rs
@@ -25,7 +25,7 @@ async fn logger_task(driver: Driver<'static, USB>) {
25async fn main(spawner: Spawner) { 25async fn main(spawner: Spawner) {
26 let p = embassy_rp::init(Default::default()); 26 let p = embassy_rp::init(Default::default());
27 let driver = Driver::new(p.USB, Irqs); 27 let driver = Driver::new(p.USB, Irqs);
28 spawner.spawn(logger_task(driver)).unwrap(); 28 spawner.spawn(logger_task(driver).unwrap());
29 29
30 let mut counter = 0; 30 let mut counter = 0;
31 loop { 31 loop {
diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs
index 103269791..0747901d1 100644
--- a/examples/rp/src/bin/usb_raw_bulk.rs
+++ b/examples/rp/src/bin/usb_raw_bulk.rs
@@ -96,8 +96,8 @@ async fn main(_spawner: Spawner) {
96 let mut function = builder.function(0xFF, 0, 0); 96 let mut function = builder.function(0xFF, 0, 0);
97 let mut interface = function.interface(); 97 let mut interface = function.interface();
98 let mut alt = interface.alt_setting(0xFF, 0, 0, None); 98 let mut alt = interface.alt_setting(0xFF, 0, 0, None);
99 let mut read_ep = alt.endpoint_bulk_out(64); 99 let mut read_ep = alt.endpoint_bulk_out(None, 64);
100 let mut write_ep = alt.endpoint_bulk_in(64); 100 let mut write_ep = alt.endpoint_bulk_in(None, 64);
101 drop(function); 101 drop(function);
102 102
103 // Build the builder. 103 // Build the builder.
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 5e3f0f378..b79012acb 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -69,7 +69,7 @@ async fn main(spawner: Spawner) {
69 let usb = builder.build(); 69 let usb = builder.build();
70 70
71 // Run the USB device. 71 // Run the USB device.
72 unwrap!(spawner.spawn(usb_task(usb))); 72 spawner.spawn(unwrap!(usb_task(usb)));
73 73
74 // Do stuff with the class! 74 // Do stuff with the class!
75 loop { 75 loop {
diff --git a/examples/rp/src/bin/usb_serial_with_handler.rs b/examples/rp/src/bin/usb_serial_with_handler.rs
index a9e65be70..b85c9029b 100644
--- a/examples/rp/src/bin/usb_serial_with_handler.rs
+++ b/examples/rp/src/bin/usb_serial_with_handler.rs
@@ -53,7 +53,7 @@ async fn logger_task(driver: Driver<'static, USB>) {
53async fn main(spawner: Spawner) { 53async fn main(spawner: Spawner) {
54 let p = embassy_rp::init(Default::default()); 54 let p = embassy_rp::init(Default::default());
55 let driver = Driver::new(p.USB, Irqs); 55 let driver = Driver::new(p.USB, Irqs);
56 spawner.spawn(logger_task(driver)).unwrap(); 56 spawner.spawn(logger_task(driver).unwrap());
57 57
58 let mut counter = 0; 58 let mut counter = 0;
59 loop { 59 loop {
diff --git a/examples/rp/src/bin/usb_webusb.rs b/examples/rp/src/bin/usb_webusb.rs
index a5dc94d5b..5cecb92f0 100644
--- a/examples/rp/src/bin/usb_webusb.rs
+++ b/examples/rp/src/bin/usb_webusb.rs
@@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> {
125 let mut iface = func.interface(); 125 let mut iface = func.interface();
126 let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); 126 let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None);
127 127
128 let write_ep = alt.endpoint_bulk_in(config.max_packet_size); 128 let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size);
129 let read_ep = alt.endpoint_bulk_out(config.max_packet_size); 129 let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size);
130 130
131 WebEndpoints { write_ep, read_ep } 131 WebEndpoints { write_ep, read_ep }
132 } 132 }
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs
index e97ddb4c1..128599e0d 100644
--- a/examples/rp/src/bin/wifi_ap_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs
@@ -19,7 +19,6 @@ use embassy_rp::peripherals::{DMA_CH0, PIO0};
19use embassy_rp::pio::{InterruptHandler, Pio}; 19use embassy_rp::pio::{InterruptHandler, Pio};
20use embassy_time::Duration; 20use embassy_time::Duration;
21use embedded_io_async::Write; 21use embedded_io_async::Write;
22use rand::RngCore;
23use static_cell::StaticCell; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
@@ -71,7 +70,7 @@ async fn main(spawner: Spawner) {
71 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 70 static STATE: StaticCell<cyw43::State> = StaticCell::new();
72 let state = STATE.init(cyw43::State::new()); 71 let state = STATE.init(cyw43::State::new());
73 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 72 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
74 unwrap!(spawner.spawn(cyw43_task(runner))); 73 spawner.spawn(unwrap!(cyw43_task(runner)));
75 74
76 control.init(clm).await; 75 control.init(clm).await;
77 control 76 control
@@ -92,7 +91,7 @@ async fn main(spawner: Spawner) {
92 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 91 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
93 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); 92 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed);
94 93
95 unwrap!(spawner.spawn(net_task(runner))); 94 spawner.spawn(unwrap!(net_task(runner)));
96 95
97 //control.start_ap_open("cyw43", 5).await; 96 //control.start_ap_open("cyw43", 5).await;
98 control.start_ap_wpa2("cyw43", "password", 5).await; 97 control.start_ap_wpa2("cyw43", "password", 5).await;
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs
index 6e91ce167..b2e08c517 100644
--- a/examples/rp/src/bin/wifi_blinky.rs
+++ b/examples/rp/src/bin/wifi_blinky.rs
@@ -55,7 +55,7 @@ async fn main(spawner: Spawner) {
55 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 55 static STATE: StaticCell<cyw43::State> = StaticCell::new();
56 let state = STATE.init(cyw43::State::new()); 56 let state = STATE.init(cyw43::State::new());
57 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 57 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
58 unwrap!(spawner.spawn(cyw43_task(runner))); 58 spawner.spawn(unwrap!(cyw43_task(runner)));
59 59
60 control.init(clm).await; 60 control.init(clm).await;
61 control 61 control
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs
index fe9c363d9..c884aa2ba 100644
--- a/examples/rp/src/bin/wifi_scan.rs
+++ b/examples/rp/src/bin/wifi_scan.rs
@@ -59,7 +59,7 @@ async fn main(spawner: Spawner) {
59 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 59 static STATE: StaticCell<cyw43::State> = StaticCell::new();
60 let state = STATE.init(cyw43::State::new()); 60 let state = STATE.init(cyw43::State::new());
61 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 61 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
62 unwrap!(spawner.spawn(cyw43_task(runner))); 62 spawner.spawn(unwrap!(cyw43_task(runner)));
63 63
64 control.init(clm).await; 64 control.init(clm).await;
65 control 65 control
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs
index 7e3c663fe..126475779 100644
--- a/examples/rp/src/bin/wifi_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_tcp_server.rs
@@ -18,9 +18,8 @@ use embassy_rp::clocks::RoscRng;
18use embassy_rp::gpio::{Level, Output}; 18use embassy_rp::gpio::{Level, Output};
19use embassy_rp::peripherals::{DMA_CH0, PIO0}; 19use embassy_rp::peripherals::{DMA_CH0, PIO0};
20use embassy_rp::pio::{InterruptHandler, Pio}; 20use embassy_rp::pio::{InterruptHandler, Pio};
21use embassy_time::{Duration, Timer}; 21use embassy_time::Duration;
22use embedded_io_async::Write; 22use embedded_io_async::Write;
23use rand::RngCore;
24use static_cell::StaticCell; 23use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
26 25
@@ -75,7 +74,7 @@ async fn main(spawner: Spawner) {
75 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 74 static STATE: StaticCell<cyw43::State> = StaticCell::new();
76 let state = STATE.init(cyw43::State::new()); 75 let state = STATE.init(cyw43::State::new());
77 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 76 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
78 unwrap!(spawner.spawn(cyw43_task(runner))); 77 spawner.spawn(unwrap!(cyw43_task(runner)));
79 78
80 control.init(clm).await; 79 control.init(clm).await;
81 control 80 control
@@ -96,28 +95,23 @@ async fn main(spawner: Spawner) {
96 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 95 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
97 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); 96 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed);
98 97
99 unwrap!(spawner.spawn(net_task(runner))); 98 spawner.spawn(unwrap!(net_task(runner)));
100 99
101 loop { 100 while let Err(err) = control
102 match control 101 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
103 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) 102 .await
104 .await 103 {
105 { 104 info!("join failed with status={}", err.status);
106 Ok(_) => break,
107 Err(err) => {
108 info!("join failed with status={}", err.status);
109 }
110 }
111 } 105 }
112 106
113 // Wait for DHCP, not necessary when using static IP 107 info!("waiting for link...");
108 stack.wait_link_up().await;
109
114 info!("waiting for DHCP..."); 110 info!("waiting for DHCP...");
115 while !stack.is_config_up() { 111 stack.wait_config_up().await;
116 Timer::after_millis(100).await;
117 }
118 info!("DHCP is now up!");
119 112
120 // And now we can use it! 113 // And now we can use it!
114 info!("Stack is up!");
121 115
122 let mut rx_buffer = [0; 4096]; 116 let mut rx_buffer = [0; 4096];
123 let mut tx_buffer = [0; 4096]; 117 let mut tx_buffer = [0; 4096];
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs
index f1b398b65..079def370 100644
--- a/examples/rp/src/bin/wifi_webrequest.rs
+++ b/examples/rp/src/bin/wifi_webrequest.rs
@@ -20,7 +20,6 @@ use embassy_rp::gpio::{Level, Output};
20use embassy_rp::peripherals::{DMA_CH0, PIO0}; 20use embassy_rp::peripherals::{DMA_CH0, PIO0};
21use embassy_rp::pio::{InterruptHandler, Pio}; 21use embassy_rp::pio::{InterruptHandler, Pio};
22use embassy_time::{Duration, Timer}; 22use embassy_time::{Duration, Timer};
23use rand::RngCore;
24use reqwless::client::{HttpClient, TlsConfig, TlsVerify}; 23use reqwless::client::{HttpClient, TlsConfig, TlsVerify};
25use reqwless::request::Method; 24use reqwless::request::Method;
26use serde::Deserialize; 25use serde::Deserialize;
@@ -77,7 +76,7 @@ async fn main(spawner: Spawner) {
77 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 76 static STATE: StaticCell<cyw43::State> = StaticCell::new();
78 let state = STATE.init(cyw43::State::new()); 77 let state = STATE.init(cyw43::State::new());
79 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 78 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
80 unwrap!(spawner.spawn(cyw43_task(runner))); 79 spawner.spawn(unwrap!(cyw43_task(runner)));
81 80
82 control.init(clm).await; 81 control.init(clm).await;
83 control 82 control
@@ -99,35 +98,22 @@ async fn main(spawner: Spawner) {
99 static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new(); 98 static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
100 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed); 99 let (stack, runner) = embassy_net::new(net_device, config, RESOURCES.init(StackResources::new()), seed);
101 100
102 unwrap!(spawner.spawn(net_task(runner))); 101 spawner.spawn(unwrap!(net_task(runner)));
103 102
104 loop { 103 while let Err(err) = control
105 match control 104 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes()))
106 .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) 105 .await
107 .await 106 {
108 { 107 info!("join failed with status={}", err.status);
109 Ok(_) => break,
110 Err(err) => {
111 info!("join failed with status={}", err.status);
112 }
113 }
114 }
115
116 // Wait for DHCP, not necessary when using static IP
117 info!("waiting for DHCP...");
118 while !stack.is_config_up() {
119 Timer::after_millis(100).await;
120 } 108 }
121 info!("DHCP is now up!");
122 109
123 info!("waiting for link up..."); 110 info!("waiting for link...");
124 while !stack.is_link_up() { 111 stack.wait_link_up().await;
125 Timer::after_millis(500).await;
126 }
127 info!("Link is up!");
128 112
129 info!("waiting for stack to be up..."); 113 info!("waiting for DHCP...");
130 stack.wait_config_up().await; 114 stack.wait_config_up().await;
115
116 // And now we can use it!
131 info!("Stack is up!"); 117 info!("Stack is up!");
132 118
133 // And now we can use it! 119 // And now we can use it!
diff --git a/examples/rp/src/bin/zerocopy.rs b/examples/rp/src/bin/zerocopy.rs
index d1fb0eb00..d603e1ed3 100644
--- a/examples/rp/src/bin/zerocopy.rs
+++ b/examples/rp/src/bin/zerocopy.rs
@@ -52,8 +52,8 @@ async fn main(spawner: Spawner) {
52 let channel = CHANNEL.init(Channel::new(buf)); 52 let channel = CHANNEL.init(Channel::new(buf));
53 let (sender, receiver) = channel.split(); 53 let (sender, receiver) = channel.split();
54 54
55 spawner.must_spawn(consumer(receiver)); 55 spawner.spawn(consumer(receiver).unwrap());
56 spawner.must_spawn(producer(sender, adc_parts)); 56 spawner.spawn(producer(sender, adc_parts).unwrap());
57 57
58 let mut ticker = Ticker::every(Duration::from_secs(1)); 58 let mut ticker = Ticker::every(Duration::from_secs(1));
59 loop { 59 loop {
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml
index 345a915af..40fbb5798 100644
--- a/examples/rp235x/Cargo.toml
+++ b/examples/rp235x/Cargo.toml
@@ -4,23 +4,24 @@ name = "embassy-rp2350-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7publish = false
7 8
8[dependencies] 9[dependencies]
9embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal", features = ["defmt"] } 10embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal", features = ["defmt"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.4.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } 14embassy-rp = { version = "0.8.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } 16embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] }
16embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 17embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.4.0", path = "../../embassy-usb-logger" } 19embassy-usb-logger = { version = "0.5.1", path = "../../embassy-usb-logger" }
19cyw43 = { version = "0.3.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] } 20cyw43 = { version = "0.5.0", path = "../../cyw43", features = ["defmt", "firmware-logs"] }
20cyw43-pio = { version = "0.4.0", path = "../../cyw43-pio", features = ["defmt"] } 21cyw43-pio = { version = "0.8.0", path = "../../cyw43-pio", features = ["defmt"] }
21 22
22defmt = "0.3" 23defmt = "1.0.1"
23defmt-rtt = "0.4" 24defmt-rtt = "1.0.0"
24fixed = "1.23.1" 25fixed = "1.23.1"
25fixed-macro = "1.2" 26fixed-macro = "1.2"
26 27
@@ -37,7 +38,7 @@ tb6612fng = "1.0.0"
37cortex-m = { version = "0.7.6", features = ["inline-asm"] } 38cortex-m = { version = "0.7.6", features = ["inline-asm"] }
38cortex-m-rt = "0.7.0" 39cortex-m-rt = "0.7.0"
39critical-section = "1.1" 40critical-section = "1.1"
40panic-probe = { version = "0.3", features = ["print-defmt"] } 41panic-probe = { version = "1.0.0", features = ["print-defmt"] }
41display-interface-spi = "0.5.0" 42display-interface-spi = "0.5.0"
42embedded-graphics = "0.8.1" 43embedded-graphics = "0.8.1"
43mipidsi = "0.8.0" 44mipidsi = "0.8.0"
@@ -55,12 +56,13 @@ embedded-storage = { version = "0.3" }
55static_cell = "2.1" 56static_cell = "2.1"
56portable-atomic = { version = "1.5", features = ["critical-section"] } 57portable-atomic = { version = "1.5", features = ["critical-section"] }
57log = "0.4" 58log = "0.4"
58rand = { version = "0.8.5", default-features = false }
59embedded-sdmmc = "0.7.0" 59embedded-sdmmc = "0.7.0"
60 60
61[profile.release] 61[profile.release]
62debug = 2 62# Enable generation of debug symbols even on release builds
63debug = true
63 64
64[profile.dev] 65[package.metadata.embassy]
65lto = true 66build = [
66opt-level = "z" 67 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/rp235x" }
68]
diff --git a/examples/rp235x/memory.x b/examples/rp235x/memory.x
index c803896f6..4382e2065 100644
--- a/examples/rp235x/memory.x
+++ b/examples/rp235x/memory.x
@@ -17,8 +17,8 @@ MEMORY {
17 * of access times. 17 * of access times.
18 * Example: Separate stacks for core0 and core1. 18 * Example: Separate stacks for core0 and core1.
19 */ 19 */
20 SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K 20 SRAM8 : ORIGIN = 0x20080000, LENGTH = 4K
21 SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K 21 SRAM9 : ORIGIN = 0x20081000, LENGTH = 4K
22} 22}
23 23
24SECTIONS { 24SECTIONS {
diff --git a/examples/rp235x/src/bin/assign_resources.rs b/examples/rp235x/src/bin/assign_resources.rs
index 341f54d22..4ee4278b5 100644
--- a/examples/rp235x/src/bin/assign_resources.rs
+++ b/examples/rp235x/src/bin/assign_resources.rs
@@ -26,15 +26,13 @@ async fn main(spawner: Spawner) {
26 let p = embassy_rp::init(Default::default()); 26 let p = embassy_rp::init(Default::default());
27 27
28 // 1) Assigning a resource to a task by passing parts of the peripherals. 28 // 1) Assigning a resource to a task by passing parts of the peripherals.
29 spawner 29 spawner.spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21).unwrap());
30 .spawn(double_blinky_manually_assigned(spawner, p.PIN_20, p.PIN_21))
31 .unwrap();
32 30
33 // 2) Using the assign-resources macro to assign resources to a task. 31 // 2) Using the assign-resources macro to assign resources to a task.
34 // we perform the split, see further below for the definition of the resources struct 32 // we perform the split, see further below for the definition of the resources struct
35 let r = split_resources!(p); 33 let r = split_resources!(p);
36 // and then we can use them 34 // and then we can use them
37 spawner.spawn(double_blinky_macro_assigned(spawner, r.leds)).unwrap(); 35 spawner.spawn(double_blinky_macro_assigned(spawner, r.leds).unwrap());
38} 36}
39 37
40// 1) Assigning a resource to a task by passing parts of the peripherals. 38// 1) Assigning a resource to a task by passing parts of the peripherals.
diff --git a/examples/rp235x/src/bin/blinky_two_channels.rs b/examples/rp235x/src/bin/blinky_two_channels.rs
index 51e139e94..87f3a3545 100644
--- a/examples/rp235x/src/bin/blinky_two_channels.rs
+++ b/examples/rp235x/src/bin/blinky_two_channels.rs
@@ -27,8 +27,8 @@ async fn main(spawner: Spawner) {
27 let dt = 100 * 1_000_000; 27 let dt = 100 * 1_000_000;
28 let k = 1.003; 28 let k = 1.003;
29 29
30 unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt)))); 30 spawner.spawn(unwrap!(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt))));
31 unwrap!(spawner.spawn(toggle_led( 31 spawner.spawn(unwrap!(toggle_led(
32 CHANNEL.sender(), 32 CHANNEL.sender(),
33 Duration::from_nanos((dt as f64 * k) as u64) 33 Duration::from_nanos((dt as f64 * k) as u64)
34 ))); 34 )));
diff --git a/examples/rp235x/src/bin/blinky_two_tasks.rs b/examples/rp235x/src/bin/blinky_two_tasks.rs
index 67a9108c0..aac7d928b 100644
--- a/examples/rp235x/src/bin/blinky_two_tasks.rs
+++ b/examples/rp235x/src/bin/blinky_two_tasks.rs
@@ -30,8 +30,8 @@ async fn main(spawner: Spawner) {
30 let dt = 100 * 1_000_000; 30 let dt = 100 * 1_000_000;
31 let k = 1.003; 31 let k = 1.003;
32 32
33 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt)))); 33 spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos(dt))));
34 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64)))); 34 spawner.spawn(unwrap!(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64))));
35} 35}
36 36
37#[embassy_executor::task(pool_size = 2)] 37#[embassy_executor::task(pool_size = 2)]
diff --git a/examples/rp235x/src/bin/blinky_wifi.rs b/examples/rp235x/src/bin/blinky_wifi.rs
index 8c352ebc4..b2201f0ae 100644
--- a/examples/rp235x/src/bin/blinky_wifi.rs
+++ b/examples/rp235x/src/bin/blinky_wifi.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::{PioSpi, RM2_CLOCK_DIVIDER};
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_rp::bind_interrupts; 11use embassy_rp::bind_interrupts;
@@ -58,7 +58,9 @@ async fn main(spawner: Spawner) {
58 let spi = PioSpi::new( 58 let spi = PioSpi::new(
59 &mut pio.common, 59 &mut pio.common,
60 pio.sm0, 60 pio.sm0,
61 DEFAULT_CLOCK_DIVIDER, 61 // SPI communication won't work if the speed is too high, so we use a divider larger than `DEFAULT_CLOCK_DIVIDER`.
62 // See: https://github.com/embassy-rs/embassy/issues/3960.
63 RM2_CLOCK_DIVIDER,
62 pio.irq0, 64 pio.irq0,
63 cs, 65 cs,
64 p.PIN_24, 66 p.PIN_24,
@@ -69,7 +71,7 @@ async fn main(spawner: Spawner) {
69 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 71 static STATE: StaticCell<cyw43::State> = StaticCell::new();
70 let state = STATE.init(cyw43::State::new()); 72 let state = STATE.init(cyw43::State::new());
71 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 73 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
72 unwrap!(spawner.spawn(cyw43_task(runner))); 74 spawner.spawn(unwrap!(cyw43_task(runner)));
73 75
74 control.init(clm).await; 76 control.init(clm).await;
75 control 77 control
diff --git a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs
index 0a5bccfb3..e6d6f687b 100644
--- a/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs
+++ b/examples/rp235x/src/bin/blinky_wifi_pico_plus_2.rs
@@ -68,7 +68,7 @@ async fn main(spawner: Spawner) {
68 static STATE: StaticCell<cyw43::State> = StaticCell::new(); 68 static STATE: StaticCell<cyw43::State> = StaticCell::new();
69 let state = STATE.init(cyw43::State::new()); 69 let state = STATE.init(cyw43::State::new());
70 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 70 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
71 unwrap!(spawner.spawn(cyw43_task(runner))); 71 spawner.spawn(unwrap!(cyw43_task(runner)));
72 72
73 control.init(clm).await; 73 control.init(clm).await;
74 control 74 control
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs
new file mode 100644
index 000000000..f012c9589
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs
@@ -0,0 +1,143 @@
1//! This example implements an echo (ping) with an ICMP Socket and using defmt to report the results.
2//!
3//! Although there is a better way to execute pings using the child module ping of the icmp module,
4//! this example allows for other icmp messages like `Destination unreachable` to be sent aswell.
5//!
6//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
7
8#![no_std]
9#![no_main]
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_futures::yield_now;
14use embassy_net::icmp::{ChecksumCapabilities, IcmpEndpoint, IcmpSocket, Icmpv4Packet, Icmpv4Repr, PacketMetadata};
15use embassy_net::{Stack, StackResources};
16use embassy_net_wiznet::chip::W5500;
17use embassy_net_wiznet::*;
18use embassy_rp::clocks::RoscRng;
19use embassy_rp::gpio::{Input, Level, Output, Pull};
20use embassy_rp::peripherals::SPI0;
21use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
22use embassy_time::{Delay, Instant, Timer};
23use embedded_hal_bus::spi::ExclusiveDevice;
24use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _};
26
27type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>;
28
29#[embassy_executor::task]
30async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! {
31 runner.run().await
32}
33
34#[embassy_executor::task]
35async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
36 runner.run().await
37}
38
39#[embassy_executor::main]
40async fn main(spawner: Spawner) {
41 let p = embassy_rp::init(Default::default());
42 let mut rng = RoscRng;
43
44 let mut spi_cfg = SpiConfig::default();
45 spi_cfg.frequency = 50_000_000;
46 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
47 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
48 let cs = Output::new(p.PIN_17, Level::High);
49 let w5500_int = Input::new(p.PIN_21, Pull::Up);
50 let w5500_reset = Output::new(p.PIN_20, Level::High);
51
52 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
53 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
54 let state = STATE.init(State::<8, 8>::new());
55 let (device, runner) = embassy_net_wiznet::new(
56 mac_addr,
57 state,
58 ExclusiveDevice::new(spi, cs, Delay),
59 w5500_int,
60 w5500_reset,
61 )
62 .await
63 .unwrap();
64 spawner.spawn(unwrap!(ethernet_task(runner)));
65
66 // Generate random seed
67 let seed = rng.next_u64();
68
69 // Init network stack
70 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
71 let (stack, runner) = embassy_net::new(
72 device,
73 embassy_net::Config::dhcpv4(Default::default()),
74 RESOURCES.init(StackResources::new()),
75 seed,
76 );
77
78 // Launch network task
79 spawner.spawn(unwrap!(net_task(runner)));
80
81 info!("Waiting for DHCP...");
82 let cfg = wait_for_config(stack).await;
83 let local_addr = cfg.address.address();
84 info!("IP address: {:?}", local_addr);
85
86 // Then we can use it!
87 let mut rx_buffer = [0; 256];
88 let mut tx_buffer = [0; 256];
89 let mut rx_meta = [PacketMetadata::EMPTY];
90 let mut tx_meta = [PacketMetadata::EMPTY];
91
92 // Identifier used for the ICMP socket
93 let ident = 42;
94
95 // Create and bind the socket
96 let mut socket = IcmpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
97 socket.bind(IcmpEndpoint::Ident(ident)).unwrap();
98
99 // Create the repr for the packet
100 let icmp_repr = Icmpv4Repr::EchoRequest {
101 ident,
102 seq_no: 0,
103 data: b"Hello, icmp!",
104 };
105
106 // Send the packet and store the starting instant to mesure latency later
107 let start = socket
108 .send_to_with(icmp_repr.buffer_len(), cfg.gateway.unwrap(), |buf| {
109 // Create and populate the packet buffer allocated by `send_to_with`
110 let mut icmp_packet = Icmpv4Packet::new_unchecked(buf);
111 icmp_repr.emit(&mut icmp_packet, &ChecksumCapabilities::default());
112 Instant::now() // Return the instant where the packet was sent
113 })
114 .await
115 .unwrap();
116
117 // Recieve and log the data of the reply
118 socket
119 .recv_from_with(|(buf, addr)| {
120 let packet = Icmpv4Packet::new_checked(buf).unwrap();
121 info!(
122 "Recieved {:?} from {} in {}ms",
123 packet.data(),
124 addr,
125 start.elapsed().as_millis()
126 );
127 })
128 .await
129 .unwrap();
130
131 loop {
132 Timer::after_secs(10).await;
133 }
134}
135
136async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
137 loop {
138 if let Some(config) = stack.config_v4() {
139 return config.clone();
140 }
141 yield_now().await;
142 }
143}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
new file mode 100644
index 000000000..309d3e4f7
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
@@ -0,0 +1,134 @@
1//! This example implements a LAN ping scan with the ping utilities in the icmp module of embassy-net.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use core::net::Ipv4Addr;
9use core::ops::Not;
10use core::str::FromStr;
11
12use defmt::*;
13use embassy_executor::Spawner;
14use embassy_futures::yield_now;
15use embassy_net::icmp::ping::{PingManager, PingParams};
16use embassy_net::icmp::PacketMetadata;
17use embassy_net::{Ipv4Cidr, Stack, StackResources};
18use embassy_net_wiznet::chip::W5500;
19use embassy_net_wiznet::*;
20use embassy_rp::clocks::RoscRng;
21use embassy_rp::gpio::{Input, Level, Output, Pull};
22use embassy_rp::peripherals::SPI0;
23use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
24use embassy_time::{Delay, Duration};
25use embedded_hal_bus::spi::ExclusiveDevice;
26use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _};
28
29type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>;
30
31#[embassy_executor::task]
32async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! {
33 runner.run().await
34}
35
36#[embassy_executor::task]
37async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
38 runner.run().await
39}
40
41#[embassy_executor::main]
42async fn main(spawner: Spawner) {
43 let p = embassy_rp::init(Default::default());
44 let mut rng = RoscRng;
45
46 let mut spi_cfg = SpiConfig::default();
47 spi_cfg.frequency = 50_000_000;
48 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
49 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
50 let cs = Output::new(p.PIN_17, Level::High);
51 let w5500_int = Input::new(p.PIN_21, Pull::Up);
52 let w5500_reset = Output::new(p.PIN_20, Level::High);
53
54 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
55 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
56 let state = STATE.init(State::<8, 8>::new());
57 let (device, runner) = embassy_net_wiznet::new(
58 mac_addr,
59 state,
60 ExclusiveDevice::new(spi, cs, Delay),
61 w5500_int,
62 w5500_reset,
63 )
64 .await
65 .unwrap();
66 spawner.spawn(unwrap!(ethernet_task(runner)));
67
68 // Generate random seed
69 let seed = rng.next_u64();
70
71 // Init network stack
72 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
73 let (stack, runner) = embassy_net::new(
74 device,
75 embassy_net::Config::dhcpv4(Default::default()),
76 RESOURCES.init(StackResources::new()),
77 seed,
78 );
79
80 // Launch network task
81 spawner.spawn(unwrap!(net_task(runner)));
82
83 info!("Waiting for DHCP...");
84 let cfg = wait_for_config(stack).await;
85 let local_addr = cfg.address.address();
86 info!("IP address: {:?}", local_addr);
87 let gateway = cfg.gateway.unwrap();
88 let mask = cfg.address.netmask();
89 let lower_bound = (gateway.to_bits() & mask.to_bits()) + 1;
90 let upper_bound = gateway.to_bits() | mask.to_bits().not();
91 let addr_range = lower_bound..=upper_bound;
92
93 // Then we can use it!
94 let mut rx_buffer = [0; 256];
95 let mut tx_buffer = [0; 256];
96 let mut rx_meta = [PacketMetadata::EMPTY];
97 let mut tx_meta = [PacketMetadata::EMPTY];
98
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);
101 let addr = "192.168.8.1"; // Address to ping to
102 // Create the PingParams with the target address
103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap());
104 // (optional) Set custom properties of the ping
105 ping_params.set_payload(b"Hello, Ping!"); // custom payload
106 ping_params.set_count(1); // ping 1 times per ping call
107 ping_params.set_timeout(Duration::from_millis(500)); // wait .5 seconds instead of 4
108
109 info!("Online hosts in {}:", Ipv4Cidr::from_netmask(gateway, mask).unwrap());
110 let mut total_online_hosts = 0u32;
111 for addr in addr_range {
112 let ip_addr = Ipv4Addr::from_bits(addr);
113 // Set the target address in the ping params
114 ping_params.set_target(ip_addr);
115 // Execute the ping with the given parameters and wait for the reply
116 match ping_manager.ping(&ping_params).await {
117 Ok(time) => {
118 info!("{} is online\n- latency: {}ms\n", ip_addr, time.as_millis());
119 total_online_hosts += 1;
120 }
121 _ => continue,
122 }
123 }
124 info!("Ping scan complete, total online hosts: {}", total_online_hosts);
125}
126
127async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
128 loop {
129 if let Some(config) = stack.config_v4() {
130 return config.clone();
131 }
132 yield_now().await;
133 }
134}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs
new file mode 100644
index 000000000..7cfc00776
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs
@@ -0,0 +1,139 @@
1//! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_futures::yield_now;
11use embassy_net::{Stack, StackResources};
12use embassy_net_wiznet::chip::W5500;
13use embassy_net_wiznet::*;
14use embassy_rp::clocks::RoscRng;
15use embassy_rp::gpio::{Input, Level, Output, Pull};
16use embassy_rp::peripherals::SPI0;
17use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
18use embassy_time::{Delay, Duration};
19use embedded_hal_bus::spi::ExclusiveDevice;
20use embedded_io_async::Write;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24#[embassy_executor::task]
25async fn ethernet_task(
26 runner: Runner<
27 'static,
28 W5500,
29 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
30 Input<'static>,
31 Output<'static>,
32 >,
33) -> ! {
34 runner.run().await
35}
36
37#[embassy_executor::task]
38async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
39 runner.run().await
40}
41
42#[embassy_executor::main]
43async fn main(spawner: Spawner) {
44 let p = embassy_rp::init(Default::default());
45 let mut rng = RoscRng;
46
47 let mut spi_cfg = SpiConfig::default();
48 spi_cfg.frequency = 50_000_000;
49 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
50 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
51 let cs = Output::new(p.PIN_17, Level::High);
52 let w5500_int = Input::new(p.PIN_21, Pull::Up);
53 let w5500_reset = Output::new(p.PIN_20, Level::High);
54
55 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
56 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
57 let state = STATE.init(State::<8, 8>::new());
58 let (device, runner) = embassy_net_wiznet::new(
59 mac_addr,
60 state,
61 ExclusiveDevice::new(spi, cs, Delay),
62 w5500_int,
63 w5500_reset,
64 )
65 .await
66 .unwrap();
67 spawner.spawn(unwrap!(ethernet_task(runner)));
68
69 // Generate random seed
70 let seed = rng.next_u64();
71
72 // Init network stack
73 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
74 let (stack, runner) = embassy_net::new(
75 device,
76 embassy_net::Config::dhcpv4(Default::default()),
77 RESOURCES.init(StackResources::new()),
78 seed,
79 );
80
81 // Launch network task
82 spawner.spawn(unwrap!(net_task(runner)));
83
84 info!("Waiting for DHCP...");
85 let cfg = wait_for_config(stack).await;
86 let local_addr = cfg.address.address();
87 info!("IP address: {:?}", local_addr);
88
89 // Create two sockets listening to the same port, to handle simultaneous connections
90 spawner.spawn(unwrap!(listen_task(stack, 0, 1234)));
91 spawner.spawn(unwrap!(listen_task(stack, 1, 1234)));
92}
93
94#[embassy_executor::task(pool_size = 2)]
95async fn listen_task(stack: Stack<'static>, id: u8, port: u16) {
96 let mut rx_buffer = [0; 4096];
97 let mut tx_buffer = [0; 4096];
98 let mut buf = [0; 4096];
99 loop {
100 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
101 socket.set_timeout(Some(Duration::from_secs(10)));
102
103 info!("SOCKET {}: Listening on TCP:{}...", id, port);
104 if let Err(e) = socket.accept(port).await {
105 warn!("accept error: {:?}", e);
106 continue;
107 }
108 info!("SOCKET {}: Received connection from {:?}", id, socket.remote_endpoint());
109
110 loop {
111 let n = match socket.read(&mut buf).await {
112 Ok(0) => {
113 warn!("read EOF");
114 break;
115 }
116 Ok(n) => n,
117 Err(e) => {
118 warn!("SOCKET {}: {:?}", id, e);
119 break;
120 }
121 };
122 info!("SOCKET {}: rxd {}", id, core::str::from_utf8(&buf[..n]).unwrap());
123
124 if let Err(e) = socket.write_all(&buf[..n]).await {
125 warn!("write error: {:?}", e);
126 break;
127 }
128 }
129 }
130}
131
132async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
133 loop {
134 if let Some(config) = stack.config_v4() {
135 return config.clone();
136 }
137 yield_now().await;
138 }
139}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs
new file mode 100644
index 000000000..254aada9a
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs
@@ -0,0 +1,127 @@
1//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use core::str::FromStr;
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_futures::yield_now;
13use embassy_net::{Stack, StackResources};
14use embassy_net_wiznet::chip::W5500;
15use embassy_net_wiznet::*;
16use embassy_rp::clocks::RoscRng;
17use embassy_rp::gpio::{Input, Level, Output, Pull};
18use embassy_rp::peripherals::SPI0;
19use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::{Delay, Duration, Timer};
21use embedded_hal_bus::spi::ExclusiveDevice;
22use embedded_io_async::Write;
23use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _};
25
26#[embassy_executor::task]
27async fn ethernet_task(
28 runner: Runner<
29 'static,
30 W5500,
31 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
32 Input<'static>,
33 Output<'static>,
34 >,
35) -> ! {
36 runner.run().await
37}
38
39#[embassy_executor::task]
40async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
41 runner.run().await
42}
43
44#[embassy_executor::main]
45async fn main(spawner: Spawner) {
46 let p = embassy_rp::init(Default::default());
47 let mut rng = RoscRng;
48 let mut led = Output::new(p.PIN_25, Level::Low);
49
50 let mut spi_cfg = SpiConfig::default();
51 spi_cfg.frequency = 50_000_000;
52 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
53 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
54 let cs = Output::new(p.PIN_17, Level::High);
55 let w5500_int = Input::new(p.PIN_21, Pull::Up);
56 let w5500_reset = Output::new(p.PIN_20, Level::High);
57
58 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
59 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
60 let state = STATE.init(State::<8, 8>::new());
61 let (device, runner) = embassy_net_wiznet::new(
62 mac_addr,
63 state,
64 ExclusiveDevice::new(spi, cs, Delay),
65 w5500_int,
66 w5500_reset,
67 )
68 .await
69 .unwrap();
70 spawner.spawn(unwrap!(ethernet_task(runner)));
71
72 // Generate random seed
73 let seed = rng.next_u64();
74
75 // Init network stack
76 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
77 let (stack, runner) = embassy_net::new(
78 device,
79 embassy_net::Config::dhcpv4(Default::default()),
80 RESOURCES.init(StackResources::new()),
81 seed,
82 );
83
84 // Launch network task
85 spawner.spawn(unwrap!(net_task(runner)));
86
87 info!("Waiting for DHCP...");
88 let cfg = wait_for_config(stack).await;
89 let local_addr = cfg.address.address();
90 info!("IP address: {:?}", local_addr);
91
92 let mut rx_buffer = [0; 4096];
93 let mut tx_buffer = [0; 4096];
94 loop {
95 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
96 socket.set_timeout(Some(Duration::from_secs(10)));
97
98 led.set_low();
99 info!("Connecting...");
100 let host_addr = embassy_net::Ipv4Address::from_str("192.168.0.118").unwrap();
101 if let Err(e) = socket.connect((host_addr, 1234)).await {
102 warn!("connect error: {:?}", e);
103 continue;
104 }
105 info!("Connected to {:?}", socket.remote_endpoint());
106 led.set_high();
107
108 let msg = b"Hello world!\n";
109 loop {
110 if let Err(e) = socket.write_all(msg).await {
111 warn!("write error: {:?}", e);
112 break;
113 }
114 info!("txd: {}", core::str::from_utf8(msg).unwrap());
115 Timer::after_secs(1).await;
116 }
117 }
118}
119
120async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
121 loop {
122 if let Some(config) = stack.config_v4() {
123 return config.clone();
124 }
125 yield_now().await;
126 }
127}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs
new file mode 100644
index 000000000..ba812f4fd
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs
@@ -0,0 +1,136 @@
1//! This example implements a TCP echo server on port 1234 and using DHCP.
2//! Send it some data, you should see it echoed back and printed in the console.
3//!
4//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_futures::yield_now;
12use embassy_net::{Stack, StackResources};
13use embassy_net_wiznet::chip::W5500;
14use embassy_net_wiznet::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::{Delay, Duration};
20use embedded_hal_bus::spi::ExclusiveDevice;
21use embedded_io_async::Write;
22use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _};
24
25#[embassy_executor::task]
26async fn ethernet_task(
27 runner: Runner<
28 'static,
29 W5500,
30 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
31 Input<'static>,
32 Output<'static>,
33 >,
34) -> ! {
35 runner.run().await
36}
37
38#[embassy_executor::task]
39async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
40 runner.run().await
41}
42
43#[embassy_executor::main]
44async fn main(spawner: Spawner) {
45 let p = embassy_rp::init(Default::default());
46 let mut rng = RoscRng;
47 let mut led = Output::new(p.PIN_25, Level::Low);
48
49 let mut spi_cfg = SpiConfig::default();
50 spi_cfg.frequency = 50_000_000;
51 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
52 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
53 let cs = Output::new(p.PIN_17, Level::High);
54 let w5500_int = Input::new(p.PIN_21, Pull::Up);
55 let w5500_reset = Output::new(p.PIN_20, Level::High);
56
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
59 let state = STATE.init(State::<8, 8>::new());
60 let (device, runner) = embassy_net_wiznet::new(
61 mac_addr,
62 state,
63 ExclusiveDevice::new(spi, cs, Delay),
64 w5500_int,
65 w5500_reset,
66 )
67 .await
68 .unwrap();
69 spawner.spawn(unwrap!(ethernet_task(runner)));
70
71 // Generate random seed
72 let seed = rng.next_u64();
73
74 // Init network stack
75 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
76 let (stack, runner) = embassy_net::new(
77 device,
78 embassy_net::Config::dhcpv4(Default::default()),
79 RESOURCES.init(StackResources::new()),
80 seed,
81 );
82
83 // Launch network task
84 spawner.spawn(unwrap!(net_task(runner)));
85
86 info!("Waiting for DHCP...");
87 let cfg = wait_for_config(stack).await;
88 let local_addr = cfg.address.address();
89 info!("IP address: {:?}", local_addr);
90
91 let mut rx_buffer = [0; 4096];
92 let mut tx_buffer = [0; 4096];
93 let mut buf = [0; 4096];
94 loop {
95 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
96 socket.set_timeout(Some(Duration::from_secs(10)));
97
98 led.set_low();
99 info!("Listening on TCP:1234...");
100 if let Err(e) = socket.accept(1234).await {
101 warn!("accept error: {:?}", e);
102 continue;
103 }
104 info!("Received connection from {:?}", socket.remote_endpoint());
105 led.set_high();
106
107 loop {
108 let n = match socket.read(&mut buf).await {
109 Ok(0) => {
110 warn!("read EOF");
111 break;
112 }
113 Ok(n) => n,
114 Err(e) => {
115 warn!("{:?}", e);
116 break;
117 }
118 };
119 info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap());
120
121 if let Err(e) = socket.write_all(&buf[..n]).await {
122 warn!("write error: {:?}", e);
123 break;
124 }
125 }
126 }
127}
128
129async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
130 loop {
131 if let Some(config) = stack.config_v4() {
132 return config.clone();
133 }
134 yield_now().await;
135 }
136}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_udp.rs b/examples/rp235x/src/bin/ethernet_w5500_udp.rs
new file mode 100644
index 000000000..ae74ad518
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_udp.rs
@@ -0,0 +1,116 @@
1//! This example implements a UDP server listening on port 1234 and echoing back the data.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_futures::yield_now;
11use embassy_net::udp::{PacketMetadata, UdpSocket};
12use embassy_net::{Stack, StackResources};
13use embassy_net_wiznet::chip::W5500;
14use embassy_net_wiznet::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::Delay;
20use embedded_hal_bus::spi::ExclusiveDevice;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24#[embassy_executor::task]
25async fn ethernet_task(
26 runner: Runner<
27 'static,
28 W5500,
29 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
30 Input<'static>,
31 Output<'static>,
32 >,
33) -> ! {
34 runner.run().await
35}
36
37#[embassy_executor::task]
38async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
39 runner.run().await
40}
41
42#[embassy_executor::main]
43async fn main(spawner: Spawner) {
44 let p = embassy_rp::init(Default::default());
45 let mut rng = RoscRng;
46
47 let mut spi_cfg = SpiConfig::default();
48 spi_cfg.frequency = 50_000_000;
49 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
50 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
51 let cs = Output::new(p.PIN_17, Level::High);
52 let w5500_int = Input::new(p.PIN_21, Pull::Up);
53 let w5500_reset = Output::new(p.PIN_20, Level::High);
54
55 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
56 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
57 let state = STATE.init(State::<8, 8>::new());
58 let (device, runner) = embassy_net_wiznet::new(
59 mac_addr,
60 state,
61 ExclusiveDevice::new(spi, cs, Delay),
62 w5500_int,
63 w5500_reset,
64 )
65 .await
66 .unwrap();
67 spawner.spawn(unwrap!(ethernet_task(runner)));
68
69 // Generate random seed
70 let seed = rng.next_u64();
71
72 // Init network stack
73 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
74 let (stack, runner) = embassy_net::new(
75 device,
76 embassy_net::Config::dhcpv4(Default::default()),
77 RESOURCES.init(StackResources::new()),
78 seed,
79 );
80
81 // Launch network task
82 spawner.spawn(unwrap!(net_task(runner)));
83
84 info!("Waiting for DHCP...");
85 let cfg = wait_for_config(stack).await;
86 let local_addr = cfg.address.address();
87 info!("IP address: {:?}", local_addr);
88
89 // Then we can use it!
90 let mut rx_buffer = [0; 4096];
91 let mut tx_buffer = [0; 4096];
92 let mut rx_meta = [PacketMetadata::EMPTY; 16];
93 let mut tx_meta = [PacketMetadata::EMPTY; 16];
94 let mut buf = [0; 4096];
95 loop {
96 let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
97 socket.bind(1234).unwrap();
98
99 loop {
100 let (n, ep) = socket.recv_from(&mut buf).await.unwrap();
101 if let Ok(s) = core::str::from_utf8(&buf[..n]) {
102 info!("rxd from {}: {}", ep, s);
103 }
104 socket.send_to(&buf[..n], ep).await.unwrap();
105 }
106 }
107}
108
109async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
110 loop {
111 if let Some(config) = stack.config_v4() {
112 return config.clone();
113 }
114 yield_now().await;
115 }
116}
diff --git a/examples/rp235x/src/bin/i2c_slave.rs b/examples/rp235x/src/bin/i2c_slave.rs
index 9fffb4646..02ad9a003 100644
--- a/examples/rp235x/src/bin/i2c_slave.rs
+++ b/examples/rp235x/src/bin/i2c_slave.rs
@@ -105,7 +105,7 @@ async fn main(spawner: Spawner) {
105 config.addr = DEV_ADDR as u16; 105 config.addr = DEV_ADDR as u16;
106 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); 106 let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config);
107 107
108 unwrap!(spawner.spawn(device_task(device))); 108 spawner.spawn(unwrap!(device_task(device)));
109 109
110 let c_sda = p.PIN_1; 110 let c_sda = p.PIN_1;
111 let c_scl = p.PIN_0; 111 let c_scl = p.PIN_0;
@@ -113,5 +113,5 @@ async fn main(spawner: Spawner) {
113 config.frequency = 1_000_000; 113 config.frequency = 1_000_000;
114 let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); 114 let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config);
115 115
116 unwrap!(spawner.spawn(controller_task(controller))); 116 spawner.spawn(unwrap!(controller_task(controller)));
117} 117}
diff --git a/examples/rp235x/src/bin/interrupt.rs b/examples/rp235x/src/bin/interrupt.rs
index e9ac76486..88513180c 100644
--- a/examples/rp235x/src/bin/interrupt.rs
+++ b/examples/rp235x/src/bin/interrupt.rs
@@ -51,7 +51,7 @@ async fn main(spawner: Spawner) {
51 // No Mutex needed when sharing within the same executor/prio level 51 // No Mutex needed when sharing within the same executor/prio level
52 static AVG: StaticCell<Cell<u32>> = StaticCell::new(); 52 static AVG: StaticCell<Cell<u32>> = StaticCell::new();
53 let avg = AVG.init(Default::default()); 53 let avg = AVG.init(Default::default());
54 spawner.must_spawn(processing(avg)); 54 spawner.spawn(processing(avg).unwrap());
55 55
56 let mut ticker = Ticker::every(Duration::from_secs(1)); 56 let mut ticker = Ticker::every(Duration::from_secs(1));
57 loop { 57 loop {
diff --git a/examples/rp235x/src/bin/multicore.rs b/examples/rp235x/src/bin/multicore.rs
index f02dc3876..4f82801d6 100644
--- a/examples/rp235x/src/bin/multicore.rs
+++ b/examples/rp235x/src/bin/multicore.rs
@@ -35,12 +35,12 @@ fn main() -> ! {
35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, 35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
36 move || { 36 move || {
37 let executor1 = EXECUTOR1.init(Executor::new()); 37 let executor1 = EXECUTOR1.init(Executor::new());
38 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); 38 executor1.run(|spawner| spawner.spawn(unwrap!(core1_task(led))));
39 }, 39 },
40 ); 40 );
41 41
42 let executor0 = EXECUTOR0.init(Executor::new()); 42 let executor0 = EXECUTOR0.init(Executor::new());
43 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 43 executor0.run(|spawner| spawner.spawn(unwrap!(core0_task())));
44} 44}
45 45
46#[embassy_executor::task] 46#[embassy_executor::task]
diff --git a/examples/rp235x/src/bin/multiprio.rs b/examples/rp235x/src/bin/multiprio.rs
index 2b397f97d..96cdf8fb1 100644
--- a/examples/rp235x/src/bin/multiprio.rs
+++ b/examples/rp235x/src/bin/multiprio.rs
@@ -130,16 +130,16 @@ fn main() -> ! {
130 // High-priority executor: SWI_IRQ_1, priority level 2 130 // High-priority executor: SWI_IRQ_1, priority level 2
131 interrupt::SWI_IRQ_1.set_priority(Priority::P2); 131 interrupt::SWI_IRQ_1.set_priority(Priority::P2);
132 let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); 132 let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1);
133 unwrap!(spawner.spawn(run_high())); 133 spawner.spawn(unwrap!(run_high()));
134 134
135 // Medium-priority executor: SWI_IRQ_0, priority level 3 135 // Medium-priority executor: SWI_IRQ_0, priority level 3
136 interrupt::SWI_IRQ_0.set_priority(Priority::P3); 136 interrupt::SWI_IRQ_0.set_priority(Priority::P3);
137 let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); 137 let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0);
138 unwrap!(spawner.spawn(run_med())); 138 spawner.spawn(unwrap!(run_med()));
139 139
140 // Low priority executor: runs in thread mode, using WFE/SEV 140 // Low priority executor: runs in thread mode, using WFE/SEV
141 let executor = EXECUTOR_LOW.init(Executor::new()); 141 let executor = EXECUTOR_LOW.init(Executor::new());
142 executor.run(|spawner| { 142 executor.run(|spawner| {
143 unwrap!(spawner.spawn(run_low())); 143 spawner.spawn(unwrap!(run_low()));
144 }); 144 });
145} 145}
diff --git a/examples/rp235x/src/bin/overclock.rs b/examples/rp235x/src/bin/overclock.rs
new file mode 100644
index 000000000..5fd97ef97
--- /dev/null
+++ b/examples/rp235x/src/bin/overclock.rs
@@ -0,0 +1,74 @@
1//! # Overclocking the RP2350 to 200 MHz
2//!
3//! This example demonstrates how to configure the RP2350 to run at 200 MHz instead of the default 150 MHz.
4//!
5//! ## Note
6//!
7//! As of yet there is no official support for running the RP235x at higher clock frequencies and/or other core voltages than the default.
8//! Doing so may cause unexpected behavior and/or damage the chip.
9
10#![no_std]
11#![no_main]
12
13use defmt::*;
14use embassy_executor::Spawner;
15use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage};
16use embassy_rp::config::Config;
17use embassy_rp::gpio::{Level, Output};
18use embassy_time::{Duration, Instant, Timer};
19use {defmt_rtt as _, panic_probe as _};
20
21const COUNT_TO: i64 = 10_000_000;
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) -> ! {
25 // Set up for clock frequency of 200 MHz, setting all necessary defaults.
26 let mut config = Config::new(ClockConfig::system_freq(200_000_000).unwrap());
27
28 // since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us.
29 // We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on
30 // what we know about the RP2040. This is not guaranteed to be correct.
31 config.clocks.core_voltage = CoreVoltage::V1_15;
32
33 // Initialize the peripherals
34 let p = embassy_rp::init(config);
35
36 // Show CPU frequency for verification
37 let sys_freq = clk_sys_freq();
38 info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
39 // Show core voltage for verification
40 let core_voltage = core_voltage().unwrap();
41 info!("Core voltage: {}", core_voltage);
42
43 // LED to indicate the system is running
44 let mut led = Output::new(p.PIN_25, Level::Low);
45
46 loop {
47 // Reset the counter at the start of measurement period
48 let mut counter = 0;
49
50 // Turn LED on while counting
51 led.set_high();
52
53 let start = Instant::now();
54
55 // This is a busy loop that will take some time to complete
56 while counter < COUNT_TO {
57 counter += 1;
58 }
59
60 let elapsed = Instant::now() - start;
61
62 // Report the elapsed time
63 led.set_low();
64 info!(
65 "At {}Mhz: Elapsed time to count to {}: {}ms",
66 sys_freq / 1_000_000,
67 counter,
68 elapsed.as_millis()
69 );
70
71 // Wait 2 seconds before starting the next measurement
72 Timer::after(Duration::from_secs(2)).await;
73 }
74}
diff --git a/examples/rp235x/src/bin/pio_async.rs b/examples/rp235x/src/bin/pio_async.rs
index a519b8a50..d76930f5c 100644
--- a/examples/rp235x/src/bin/pio_async.rs
+++ b/examples/rp235x/src/bin/pio_async.rs
@@ -125,7 +125,7 @@ async fn main(spawner: Spawner) {
125 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); 125 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0);
126 setup_pio_task_sm1(&mut common, &mut sm1); 126 setup_pio_task_sm1(&mut common, &mut sm1);
127 setup_pio_task_sm2(&mut common, &mut sm2); 127 setup_pio_task_sm2(&mut common, &mut sm2);
128 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 128 spawner.spawn(pio_task_sm0(sm0).unwrap());
129 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 129 spawner.spawn(pio_task_sm1(sm1).unwrap());
130 spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); 130 spawner.spawn(pio_task_sm2(irq3, sm2).unwrap());
131} 131}
diff --git a/examples/rp235x/src/bin/pio_i2s.rs b/examples/rp235x/src/bin/pio_i2s.rs
index 5a4bcfcac..cfcb0221d 100644
--- a/examples/rp235x/src/bin/pio_i2s.rs
+++ b/examples/rp235x/src/bin/pio_i2s.rs
@@ -27,7 +27,6 @@ bind_interrupts!(struct Irqs {
27 27
28const SAMPLE_RATE: u32 = 48_000; 28const SAMPLE_RATE: u32 = 48_000;
29const BIT_DEPTH: u32 = 16; 29const BIT_DEPTH: u32 = 16;
30const CHANNELS: u32 = 2;
31 30
32#[embassy_executor::main] 31#[embassy_executor::main]
33async fn main(_spawner: Spawner) { 32async fn main(_spawner: Spawner) {
@@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) {
50 left_right_clock_pin, 49 left_right_clock_pin,
51 SAMPLE_RATE, 50 SAMPLE_RATE,
52 BIT_DEPTH, 51 BIT_DEPTH,
53 CHANNELS,
54 &program, 52 &program,
55 ); 53 );
56 54
diff --git a/examples/rp235x/src/bin/pio_i2s_rx.rs b/examples/rp235x/src/bin/pio_i2s_rx.rs
new file mode 100644
index 000000000..c3f505b13
--- /dev/null
+++ b/examples/rp235x/src/bin/pio_i2s_rx.rs
@@ -0,0 +1,81 @@
1//! This example shows receiving audio from a connected I2S microphone (or other audio source)
2//! using the PIO module of the RP235x.
3//!
4//!
5//! Connect the i2s microphone as follows:
6//! bclk : GPIO 18
7//! lrc : GPIO 19
8//! din : GPIO 20
9//! Then hold down the boot select button to begin receiving audio. Received I2S words will be written to
10//! buffers for the left and right channels for use in your application, whether that's storage or
11//! further processing
12//!
13//! Note the const USE_ONBOARD_PULLDOWN is by default set to false, meaning an external
14//! pull-down resistor is being used on the data pin if required by the mic being used.
15
16#![no_std]
17#![no_main]
18use core::mem;
19
20use defmt::*;
21use embassy_executor::Spawner;
22use embassy_rp::bind_interrupts;
23use embassy_rp::peripherals::PIO0;
24use embassy_rp::pio::{InterruptHandler, Pio};
25use embassy_rp::pio_programs::i2s::{PioI2sIn, PioI2sInProgram};
26use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _};
28
29bind_interrupts!(struct Irqs {
30 PIO0_IRQ_0 => InterruptHandler<PIO0>;
31});
32
33const SAMPLE_RATE: u32 = 48_000;
34const BIT_DEPTH: u32 = 16;
35const CHANNELS: u32 = 2;
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
38#[embassy_executor::main]
39async fn main(_spawner: Spawner) {
40 let p = embassy_rp::init(Default::default());
41
42 // Setup pio state machine for i2s input
43 let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs);
44
45 let bit_clock_pin = p.PIN_18;
46 let left_right_clock_pin = p.PIN_19;
47 let data_pin = p.PIN_20;
48
49 let program = PioI2sInProgram::new(&mut common);
50 let mut i2s = PioI2sIn::new(
51 &mut common,
52 sm0,
53 p.DMA_CH0,
54 USE_ONBOARD_PULLDOWN,
55 data_pin,
56 bit_clock_pin,
57 left_right_clock_pin,
58 SAMPLE_RATE,
59 BIT_DEPTH,
60 CHANNELS,
61 &program,
62 );
63
64 // create two audio buffers (back and front) which will take turns being
65 // filled with new audio data from the PIO fifo using DMA
66 const BUFFER_SIZE: usize = 960;
67 static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new();
68 let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]);
69 let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE);
70
71 loop {
72 // trigger transfer of front buffer data to the pio fifo
73 // but don't await the returned future, yet
74 let dma_future = i2s.read(front_buffer);
75 // now await the dma future. once the dma finishes, the next buffer needs to be queued
76 // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us
77 dma_future.await;
78 info!("Received I2S data word: {:?}", &front_buffer);
79 mem::swap(&mut back_buffer, &mut front_buffer);
80 }
81}
diff --git a/examples/rp235x/src/bin/pio_onewire.rs b/examples/rp235x/src/bin/pio_onewire.rs
index 991510851..102f13c45 100644
--- a/examples/rp235x/src/bin/pio_onewire.rs
+++ b/examples/rp235x/src/bin/pio_onewire.rs
@@ -1,4 +1,5 @@
1//! This example shows how you can use PIO to read a `DS18B20` one-wire temperature sensor. 1//! This example shows how you can use PIO to read one or more `DS18B20` one-wire temperature sensors.
2//! This uses externally powered sensors. For parasite power, see the pio_onewire_parasite.rs example.
2 3
3#![no_std] 4#![no_std]
4#![no_main] 5#![no_main]
@@ -6,9 +7,10 @@ use defmt::*;
6use embassy_executor::Spawner; 7use embassy_executor::Spawner;
7use embassy_rp::bind_interrupts; 8use embassy_rp::bind_interrupts;
8use embassy_rp::peripherals::PIO0; 9use embassy_rp::peripherals::PIO0;
9use embassy_rp::pio::{self, InterruptHandler, Pio}; 10use embassy_rp::pio::{InterruptHandler, Pio};
10use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram}; 11use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch};
11use embassy_time::Timer; 12use embassy_time::Timer;
13use heapless::Vec;
12use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
13 15
14bind_interrupts!(struct Irqs { 16bind_interrupts!(struct Irqs {
@@ -21,63 +23,66 @@ async fn main(_spawner: Spawner) {
21 let mut pio = Pio::new(p.PIO0, Irqs); 23 let mut pio = Pio::new(p.PIO0, Irqs);
22 24
23 let prg = PioOneWireProgram::new(&mut pio.common); 25 let prg = PioOneWireProgram::new(&mut pio.common);
24 let onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg); 26 let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg);
25 27
26 let mut sensor = Ds18b20::new(onewire); 28 info!("Starting onewire search");
27 29
28 loop { 30 let mut devices = Vec::<u64, 10>::new();
29 sensor.start().await; // Start a new measurement 31 let mut search = PioOneWireSearch::new();
30 Timer::after_secs(1).await; // Allow 1s for the measurement to finish 32 for _ in 0..10 {
31 match sensor.temperature().await { 33 if !search.is_finished() {
32 Ok(temp) => info!("temp = {:?} deg C", temp), 34 if let Some(address) = search.next(&mut onewire).await {
33 _ => error!("sensor error"), 35 if crc8(&address.to_le_bytes()) == 0 {
36 info!("Found addres: {:x}", address);
37 let _ = devices.push(address);
38 } else {
39 warn!("Found invalid address: {:x}", address);
40 }
41 }
34 } 42 }
35 Timer::after_secs(1).await;
36 } 43 }
37}
38 44
39/// DS18B20 temperature sensor driver 45 info!("Search done, found {} devices", devices.len());
40pub struct Ds18b20<'d, PIO: pio::Instance, const SM: usize> {
41 wire: PioOneWire<'d, PIO, SM>,
42}
43 46
44impl<'d, PIO: pio::Instance, const SM: usize> Ds18b20<'d, PIO, SM> { 47 loop {
45 pub fn new(wire: PioOneWire<'d, PIO, SM>) -> Self { 48 onewire.reset().await;
46 Self { wire } 49 // Skip rom and trigger conversion, we can trigger all devices on the bus immediately
47 } 50 onewire.write_bytes(&[0xCC, 0x44]).await;
48 51
49 /// Calculate CRC8 of the data 52 Timer::after_secs(1).await; // Allow 1s for the measurement to finish
50 fn crc8(data: &[u8]) -> u8 { 53
51 let mut temp; 54 // Read all devices one by one
52 let mut data_byte; 55 for device in &devices {
53 let mut crc = 0; 56 onewire.reset().await;
54 for b in data { 57 onewire.write_bytes(&[0x55]).await; // Match rom
55 data_byte = *b; 58 onewire.write_bytes(&device.to_le_bytes()).await;
56 for _ in 0..8 { 59 onewire.write_bytes(&[0xBE]).await; // Read scratchpad
57 temp = (crc ^ data_byte) & 0x01; 60
58 crc >>= 1; 61 let mut data = [0; 9];
59 if temp != 0 { 62 onewire.read_bytes(&mut data).await;
60 crc ^= 0x8C; 63 if crc8(&data) == 0 {
61 } 64 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.;
62 data_byte >>= 1; 65 info!("Read device {:x}: {} deg C", device, temp);
66 } else {
67 warn!("Reading device {:x} failed", device);
63 } 68 }
64 } 69 }
65 crc 70 Timer::after_secs(1).await;
66 }
67
68 /// Start a new measurement. Allow at least 1000ms before getting `temperature`.
69 pub async fn start(&mut self) {
70 self.wire.write_bytes(&[0xCC, 0x44]).await;
71 } 71 }
72}
72 73
73 /// Read the temperature. Ensure >1000ms has passed since `start` before calling this. 74fn crc8(data: &[u8]) -> u8 {
74 pub async fn temperature(&mut self) -> Result<f32, ()> { 75 let mut crc = 0;
75 self.wire.write_bytes(&[0xCC, 0xBE]).await; 76 for b in data {
76 let mut data = [0; 9]; 77 let mut data_byte = *b;
77 self.wire.read_bytes(&mut data).await; 78 for _ in 0..8 {
78 match Self::crc8(&data) == 0 { 79 let temp = (crc ^ data_byte) & 0x01;
79 true => Ok(((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.), 80 crc >>= 1;
80 false => Err(()), 81 if temp != 0 {
82 crc ^= 0x8C;
83 }
84 data_byte >>= 1;
81 } 85 }
82 } 86 }
87 crc
83} 88}
diff --git a/examples/rp235x/src/bin/pio_onewire_parasite.rs b/examples/rp235x/src/bin/pio_onewire_parasite.rs
new file mode 100644
index 000000000..fd076dee0
--- /dev/null
+++ b/examples/rp235x/src/bin/pio_onewire_parasite.rs
@@ -0,0 +1,89 @@
1//! This example shows how you can use PIO to read one or more `DS18B20`
2//! one-wire temperature sensors using parasite power.
3//! It applies a strong pullup during conversion, see "Powering the DS18B20" in the datasheet.
4//! For externally powered sensors, use the pio_onewire.rs example.
5
6#![no_std]
7#![no_main]
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts;
11use embassy_rp::peripherals::PIO0;
12use embassy_rp::pio::{InterruptHandler, Pio};
13use embassy_rp::pio_programs::onewire::{PioOneWire, PioOneWireProgram, PioOneWireSearch};
14use embassy_time::Duration;
15use heapless::Vec;
16use {defmt_rtt as _, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 PIO0_IRQ_0 => InterruptHandler<PIO0>;
20});
21
22#[embassy_executor::main]
23async fn main(_spawner: Spawner) {
24 let p = embassy_rp::init(Default::default());
25 let mut pio = Pio::new(p.PIO0, Irqs);
26
27 let prg = PioOneWireProgram::new(&mut pio.common);
28 let mut onewire = PioOneWire::new(&mut pio.common, pio.sm0, p.PIN_2, &prg);
29
30 info!("Starting onewire search");
31
32 let mut devices = Vec::<u64, 10>::new();
33 let mut search = PioOneWireSearch::new();
34 for _ in 0..10 {
35 if !search.is_finished() {
36 if let Some(address) = search.next(&mut onewire).await {
37 if crc8(&address.to_le_bytes()) == 0 {
38 info!("Found address: {:x}", address);
39 let _ = devices.push(address);
40 } else {
41 warn!("Found invalid address: {:x}", address);
42 }
43 }
44 }
45 }
46
47 info!("Search done, found {} devices", devices.len());
48
49 loop {
50 // Read all devices one by one
51 for device in &devices {
52 onewire.reset().await;
53 onewire.write_bytes(&[0x55]).await; // Match rom
54 onewire.write_bytes(&device.to_le_bytes()).await;
55 // 750 ms delay required for default 12-bit resolution.
56 onewire.write_bytes_pullup(&[0x44], Duration::from_millis(750)).await;
57
58 onewire.reset().await;
59 onewire.write_bytes(&[0x55]).await; // Match rom
60 onewire.write_bytes(&device.to_le_bytes()).await;
61 onewire.write_bytes(&[0xBE]).await; // Read scratchpad
62
63 let mut data = [0; 9];
64 onewire.read_bytes(&mut data).await;
65 if crc8(&data) == 0 {
66 let temp = ((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.;
67 info!("Read device {:x}: {} deg C", device, temp);
68 } else {
69 warn!("Reading device {:x} failed. {:02x}", device, data);
70 }
71 }
72 }
73}
74
75fn crc8(data: &[u8]) -> u8 {
76 let mut crc = 0;
77 for b in data {
78 let mut data_byte = *b;
79 for _ in 0..8 {
80 let temp = (crc ^ data_byte) & 0x01;
81 crc >>= 1;
82 if temp != 0 {
83 crc ^= 0x8C;
84 }
85 data_byte >>= 1;
86 }
87 }
88 crc
89}
diff --git a/examples/rp235x/src/bin/pio_rotary_encoder.rs b/examples/rp235x/src/bin/pio_rotary_encoder.rs
index e820d316d..610d1a40b 100644
--- a/examples/rp235x/src/bin/pio_rotary_encoder.rs
+++ b/examples/rp235x/src/bin/pio_rotary_encoder.rs
@@ -50,6 +50,6 @@ async fn main(spawner: Spawner) {
50 let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg); 50 let encoder0 = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5, &prg);
51 let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg); 51 let encoder1 = PioEncoder::new(&mut common, sm1, p.PIN_6, p.PIN_7, &prg);
52 52
53 spawner.must_spawn(encoder_0(encoder0)); 53 spawner.spawn(encoder_0(encoder0).unwrap());
54 spawner.must_spawn(encoder_1(encoder1)); 54 spawner.spawn(encoder_1(encoder1).unwrap());
55} 55}
diff --git a/examples/rp235x/src/bin/psram.rs b/examples/rp235x/src/bin/psram.rs
new file mode 100644
index 000000000..716ac7695
--- /dev/null
+++ b/examples/rp235x/src/bin/psram.rs
@@ -0,0 +1,49 @@
1//! This example tests an APS6404L PSRAM chip connected to the RP235x
2//! It fills the PSRAM with alternating patterns and reads back a value
3//!
4//! In this example, the PSRAM CS is connected to Pin 0.
5
6#![no_std]
7#![no_main]
8
9use core::slice;
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _};
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let config = embassy_rp::config::Config::default();
19 let p = embassy_rp::init(config);
20 let psram_config = embassy_rp::psram::Config::aps6404l();
21 let psram = embassy_rp::psram::Psram::new(embassy_rp::qmi_cs1::QmiCs1::new(p.QMI_CS1, p.PIN_0), psram_config);
22
23 let Ok(psram) = psram else {
24 error!("PSRAM not found");
25 loop {
26 Timer::after_secs(1).await;
27 }
28 };
29
30 let psram_slice = unsafe {
31 let psram_ptr = psram.base_address();
32 let slice: &'static mut [u8] = slice::from_raw_parts_mut(psram_ptr, psram.size() as usize);
33 slice
34 };
35
36 loop {
37 psram_slice.fill(0x55);
38 info!("PSRAM filled with 0x55");
39 let at_addr = psram_slice[0x100];
40 info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr);
41 Timer::after_secs(1).await;
42
43 psram_slice.fill(0xAA);
44 info!("PSRAM filled with 0xAA");
45 let at_addr = psram_slice[0x100];
46 info!("Read from PSRAM at address 0x100: 0x{:02x}", at_addr);
47 Timer::after_secs(1).await;
48 }
49}
diff --git a/examples/rp235x/src/bin/pwm.rs b/examples/rp235x/src/bin/pwm.rs
index da1acc18a..289480c85 100644
--- a/examples/rp235x/src/bin/pwm.rs
+++ b/examples/rp235x/src/bin/pwm.rs
@@ -18,8 +18,8 @@ use {defmt_rtt as _, panic_probe as _};
18#[embassy_executor::main] 18#[embassy_executor::main]
19async fn main(spawner: Spawner) { 19async fn main(spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25)).unwrap(); 21 spawner.spawn(pwm_set_config(p.PWM_SLICE4, p.PIN_25).unwrap());
22 spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4)).unwrap(); 22 spawner.spawn(pwm_set_dutycycle(p.PWM_SLICE2, p.PIN_4).unwrap());
23} 23}
24 24
25/// Demonstrate PWM by modifying & applying the config 25/// Demonstrate PWM by modifying & applying the config
diff --git a/examples/rp235x/src/bin/shared_bus.rs b/examples/rp235x/src/bin/shared_bus.rs
index 9267dfccb..db7566b1a 100644
--- a/examples/rp235x/src/bin/shared_bus.rs
+++ b/examples/rp235x/src/bin/shared_bus.rs
@@ -35,8 +35,8 @@ async fn main(spawner: Spawner) {
35 static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new(); 35 static I2C_BUS: StaticCell<I2c1Bus> = StaticCell::new();
36 let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); 36 let i2c_bus = I2C_BUS.init(Mutex::new(i2c));
37 37
38 spawner.must_spawn(i2c_task_a(i2c_bus)); 38 spawner.spawn(i2c_task_a(i2c_bus).unwrap());
39 spawner.must_spawn(i2c_task_b(i2c_bus)); 39 spawner.spawn(i2c_task_b(i2c_bus).unwrap());
40 40
41 // Shared SPI bus 41 // Shared SPI bus
42 let spi_cfg = spi::Config::default(); 42 let spi_cfg = spi::Config::default();
@@ -48,8 +48,8 @@ async fn main(spawner: Spawner) {
48 let cs_a = Output::new(p.PIN_0, Level::High); 48 let cs_a = Output::new(p.PIN_0, Level::High);
49 let cs_b = Output::new(p.PIN_1, Level::High); 49 let cs_b = Output::new(p.PIN_1, Level::High);
50 50
51 spawner.must_spawn(spi_task_a(spi_bus, cs_a)); 51 spawner.spawn(spi_task_a(spi_bus, cs_a).unwrap());
52 spawner.must_spawn(spi_task_b(spi_bus, cs_b)); 52 spawner.spawn(spi_task_b(spi_bus, cs_b).unwrap());
53} 53}
54 54
55#[embassy_executor::task] 55#[embassy_executor::task]
diff --git a/examples/rp235x/src/bin/sharing.rs b/examples/rp235x/src/bin/sharing.rs
index 497c4f845..d4c89946b 100644
--- a/examples/rp235x/src/bin/sharing.rs
+++ b/examples/rp235x/src/bin/sharing.rs
@@ -27,7 +27,6 @@ use embassy_rp::{bind_interrupts, interrupt};
27use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 27use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
28use embassy_sync::{blocking_mutex, mutex}; 28use embassy_sync::{blocking_mutex, mutex};
29use embassy_time::{Duration, Ticker}; 29use embassy_time::{Duration, Ticker};
30use rand::RngCore;
31use static_cell::{ConstStaticCell, StaticCell}; 30use static_cell::{ConstStaticCell, StaticCell};
32use {defmt_rtt as _, panic_probe as _}; 31use {defmt_rtt as _, panic_probe as _};
33 32
@@ -69,7 +68,7 @@ fn main() -> ! {
69 // High-priority executor: runs in interrupt mode 68 // High-priority executor: runs in interrupt mode
70 interrupt::SWI_IRQ_0.set_priority(Priority::P3); 69 interrupt::SWI_IRQ_0.set_priority(Priority::P3);
71 let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0); 70 let spawner = EXECUTOR_HI.start(interrupt::SWI_IRQ_0);
72 spawner.must_spawn(task_a(uart)); 71 spawner.spawn(task_a(uart).unwrap());
73 72
74 // Low priority executor: runs in thread mode 73 // Low priority executor: runs in thread mode
75 let executor = EXECUTOR_LOW.init(Executor::new()); 74 let executor = EXECUTOR_LOW.init(Executor::new());
@@ -84,8 +83,8 @@ fn main() -> ! {
84 static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 })); 83 static REF_CELL: ConstStaticCell<RefCell<MyType>> = ConstStaticCell::new(RefCell::new(MyType { inner: 0 }));
85 let ref_cell = REF_CELL.take(); 84 let ref_cell = REF_CELL.take();
86 85
87 spawner.must_spawn(task_b(uart, cell, ref_cell)); 86 spawner.spawn(task_b(uart, cell, ref_cell).unwrap());
88 spawner.must_spawn(task_c(cell, ref_cell)); 87 spawner.spawn(task_c(cell, ref_cell).unwrap());
89 }); 88 });
90} 89}
91 90
diff --git a/examples/rp235x/src/bin/trng.rs b/examples/rp235x/src/bin/trng.rs
index ad19aef3e..100d6b104 100644
--- a/examples/rp235x/src/bin/trng.rs
+++ b/examples/rp235x/src/bin/trng.rs
@@ -10,7 +10,6 @@ use embassy_rp::gpio::{Level, Output};
10use embassy_rp::peripherals::TRNG; 10use embassy_rp::peripherals::TRNG;
11use embassy_rp::trng::Trng; 11use embassy_rp::trng::Trng;
12use embassy_time::Timer; 12use embassy_time::Timer;
13use rand::RngCore;
14use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
15 14
16bind_interrupts!(struct Irqs { 15bind_interrupts!(struct Irqs {
@@ -33,8 +32,8 @@ async fn main(_spawner: Spawner) {
33 info!("Random bytes async {}", &randomness); 32 info!("Random bytes async {}", &randomness);
34 trng.blocking_fill_bytes(&mut randomness); 33 trng.blocking_fill_bytes(&mut randomness);
35 info!("Random bytes blocking {}", &randomness); 34 info!("Random bytes blocking {}", &randomness);
36 let random_u32 = trng.next_u32(); 35 let random_u32 = trng.blocking_next_u32();
37 let random_u64 = trng.next_u64(); 36 let random_u64 = trng.blocking_next_u64();
38 info!("Random u32 {} u64 {}", random_u32, random_u64); 37 info!("Random u32 {} u64 {}", random_u32, random_u64);
39 // Random number of blinks between 0 and 31 38 // Random number of blinks between 0 and 31
40 let blinks = random_u32 % 32; 39 let blinks = random_u32 % 32;
diff --git a/examples/rp235x/src/bin/uart_buffered_split.rs b/examples/rp235x/src/bin/uart_buffered_split.rs
index 7cad09f9b..061be873d 100644
--- a/examples/rp235x/src/bin/uart_buffered_split.rs
+++ b/examples/rp235x/src/bin/uart_buffered_split.rs
@@ -33,7 +33,7 @@ async fn main(spawner: Spawner) {
33 let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default()); 33 let uart = BufferedUart::new(uart, tx_pin, rx_pin, Irqs, tx_buf, rx_buf, Config::default());
34 let (mut tx, rx) = uart.split(); 34 let (mut tx, rx) = uart.split();
35 35
36 unwrap!(spawner.spawn(reader(rx))); 36 spawner.spawn(unwrap!(reader(rx)));
37 37
38 info!("Writing..."); 38 info!("Writing...");
39 loop { 39 loop {
diff --git a/examples/rp235x/src/bin/uart_unidir.rs b/examples/rp235x/src/bin/uart_unidir.rs
index 45c9c8407..0c80d24c9 100644
--- a/examples/rp235x/src/bin/uart_unidir.rs
+++ b/examples/rp235x/src/bin/uart_unidir.rs
@@ -27,7 +27,7 @@ async fn main(spawner: Spawner) {
27 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); 27 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
28 let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); 28 let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default());
29 29
30 unwrap!(spawner.spawn(reader(uart_rx))); 30 spawner.spawn(unwrap!(reader(uart_rx)));
31 31
32 info!("Writing..."); 32 info!("Writing...");
33 loop { 33 loop {
diff --git a/examples/rp235x/src/bin/usb_webusb.rs b/examples/rp235x/src/bin/usb_webusb.rs
index 75d28c853..a68163b61 100644
--- a/examples/rp235x/src/bin/usb_webusb.rs
+++ b/examples/rp235x/src/bin/usb_webusb.rs
@@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> {
125 let mut iface = func.interface(); 125 let mut iface = func.interface();
126 let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None); 126 let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None);
127 127
128 let write_ep = alt.endpoint_bulk_in(config.max_packet_size); 128 let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size);
129 let read_ep = alt.endpoint_bulk_out(config.max_packet_size); 129 let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size);
130 130
131 WebEndpoints { write_ep, read_ep } 131 WebEndpoints { write_ep, read_ep }
132 } 132 }
diff --git a/examples/rp235x/src/bin/zerocopy.rs b/examples/rp235x/src/bin/zerocopy.rs
index 086c86cac..62ba4cfb8 100644
--- a/examples/rp235x/src/bin/zerocopy.rs
+++ b/examples/rp235x/src/bin/zerocopy.rs
@@ -52,8 +52,8 @@ async fn main(spawner: Spawner) {
52 let channel = CHANNEL.init(Channel::new(buf)); 52 let channel = CHANNEL.init(Channel::new(buf));
53 let (sender, receiver) = channel.split(); 53 let (sender, receiver) = channel.split();
54 54
55 spawner.must_spawn(consumer(receiver)); 55 spawner.spawn(consumer(receiver).unwrap());
56 spawner.must_spawn(producer(sender, adc_parts)); 56 spawner.spawn(producer(sender, adc_parts).unwrap());
57 57
58 let mut ticker = Ticker::every(Duration::from_secs(1)); 58 let mut ticker = Ticker::every(Duration::from_secs(1));
59 loop { 59 loop {
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index f00953167..449c5ddca 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -3,14 +3,15 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } 9embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log"] }
10embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "std", ] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "std", ] }
11embassy-net = { version = "0.7.0", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } 12embassy-net = { version = "0.7.1", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] }
12embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } 13embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" }
13embassy-net-ppp = { version = "0.2.0", path = "../../embassy-net-ppp", features = ["log"]} 14embassy-net-ppp = { version = "0.2.1", path = "../../embassy-net-ppp", features = ["log"]}
14embedded-io-async = { version = "0.6.1" } 15embedded-io-async = { version = "0.6.1" }
15embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] } 16embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] }
16critical-section = { version = "1.1", features = ["std"] } 17critical-section = { version = "1.1", features = ["std"] }
@@ -21,9 +22,14 @@ futures = { version = "0.3.17" }
21log = "0.4.14" 22log = "0.4.14"
22nix = "0.26.2" 23nix = "0.26.2"
23clap = { version = "3.0.0-beta.5", features = ["derive"] } 24clap = { version = "3.0.0-beta.5", features = ["derive"] }
24rand_core = { version = "0.6.3", features = ["std"] } 25rand_core = { version = "0.9.1", features = ["std", "os_rng"] }
25heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
26static_cell = "2" 27static_cell = "2"
27 28
28[profile.release] 29[profile.release]
29debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { artifact-dir = "out/examples/std" }
35]
diff --git a/examples/std/README.md b/examples/std/README.md
index dcc152fc2..ac2c2a1a6 100644
--- a/examples/std/README.md
+++ b/examples/std/README.md
@@ -1,19 +1,128 @@
1 1
2## Running the `embassy-net` examples 2## Running the `embassy-net` examples
3 3
4First, create the tap99 interface. (The number was chosen to 4To run `net`, `tcp_accept`, `net_udp` and `net_dns` examples you will need a tap interface. Before running these examples, create the tap99 interface. (The number was chosen to
5hopefully not collide with anything.) You only need to do 5hopefully not collide with anything.) You only need to do this once every time you reboot your computer.
6this once.
7 6
8```sh 7```sh
8cd $EMBASSY_ROOT/examples/std/
9sudo sh tap.sh 9sudo sh tap.sh
10``` 10```
11 11
12Second, have something listening there. For example `nc -lp 8000` 12The example `net_ppp` requires different steps that are detailed in its section.
13
14### `net` example
15
16For this example, you need to have something listening in the correct port. For example `nc -lp 8000`.
13 17
14Then run the example located in the `examples` folder: 18Then run the example located in the `examples` folder:
15 19
16```sh 20```sh
17cd $EMBASSY_ROOT/examples/std/ 21cd $EMBASSY_ROOT/examples/std/
18sudo cargo run --bin net -- --tap tap99 --static-ip 22cargo run --bin net -- --tap tap99 --static-ip
23```
24### `tcp_accept` example
25
26This example listen for a tcp connection.
27
28First run the example located in the `examples` folder:
29
30```sh
31cd $EMBASSY_ROOT/examples/std/
32cargo run --bin tcp_accept -- --tap tap99 --static-ip
33```
34
35Then open a connection to the port. For example `nc 192.168.69.2 9999`.
36
37### `net_udp` example
38
39This example listen for a udp connection.
40
41First run the example located in the `examples` folder:
42
43```sh
44cd $EMBASSY_ROOT/examples/std/
45cargo run --bin net_udp -- --tap tap99 --static-ip
46```
47
48Then open a connection to the port. For example `nc -u 192.168.69.2 9400`.
49
50### `net_dns` example
51
52This example queries a `DNS` for the IP address of `www.example.com`.
53
54In order to achieve this, the `tap99` interface requires configuring tap99 as a gateway device temporarily.
55
56For example, in Ubuntu you can do this by:
57
581. Identifying your default route device. In the next example `eth0`
59
60```sh
61ip r | grep "default"
62default via 192.168.2.1 dev eth0 proto kernel metric 35
63```
64
652. Enabling temporarily IP Forwarding:
66
67```sh
68sudo sysctl -w net.ipv4.ip_forward=1
69```
70
713. Configuring NAT to mascarade traffic from `tap99` to `eth0`
72
73```sh
74sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
75sudo iptables -A FORWARD -i tap99 -j ACCEPT
76sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
77```
78
794. Then you can run the example located in the `examples` folder:
80
81```sh
82cd $EMBASSY_ROOT/examples/std/
83cargo run --bin net_dns -- --tap tap99 --static-ip
84```
85
86### `net_ppp` example
87
88This example establish a Point-to-Point Protocol (PPP) connection that can be used, for example, for connecting to internet through a 4G modem via a serial channel.
89
90The example creates a PPP bridge over a virtual serial channel between `pty1` and `pty2` for the example code and a PPP server running on the same computer.
91
92To run this example you will need:
93- ppp (pppd server)
94- socat (socket CAT)
95
96To run the examples you may follow the next steps:
97
981. Save the PPP server configuration:
99```sh
100sudo sh -c 'echo "myuser $(hostname) mypass 192.168.7.10" >> /etc/ppp/pap-secrets'
101```
102
1032. Create a files `pty1` and `pty2` and link them
104```sh
105cd $EMBASSY_ROOT/examples/std/
106socat -v -x PTY,link=pty1,rawer PTY,link=pty2,rawer
107```
108
1093. open a second terminal and start the PPP server:
110```sh
111cd $EMBASSY_ROOT/examples/std/
112sudo pppd $PWD/pty1 115200 192.168.7.1: ms-dns 8.8.4.4 ms-dns 8.8.8.8 nodetach debug local persist silent
113```
114
1154. Open a third terminal and run the example
116```sh
117cd $EMBASSY_ROOT/examples/std/
118RUST_LOG=trace cargo run --bin net_ppp -- --device pty2
119```
1205. Observe the output in the second and third terminal
1216. Open one last terminal to interact with `net_ppp` example through the PPP connection
122```sh
123# ping the net_ppp client
124ping 192.168.7.10
125# open an tcp connection
126nc 192.168.7.10 1234
127# Type anything and observe the output in the different terminals
19``` 128```
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs
index 6e50b1a01..fd7b6c930 100644
--- a/examples/std/src/bin/net.rs
+++ b/examples/std/src/bin/net.rs
@@ -9,7 +9,7 @@ use embassy_time::Duration;
9use embedded_io_async::Write; 9use embedded_io_async::Write;
10use heapless::Vec; 10use heapless::Vec;
11use log::*; 11use log::*;
12use rand_core::{OsRng, RngCore}; 12use rand_core::{OsRng, TryRngCore};
13use static_cell::StaticCell; 13use static_cell::StaticCell;
14 14
15#[derive(Parser)] 15#[derive(Parser)]
@@ -48,7 +48,7 @@ async fn main_task(spawner: Spawner) {
48 48
49 // Generate random seed 49 // Generate random seed
50 let mut seed = [0; 8]; 50 let mut seed = [0; 8];
51 OsRng.fill_bytes(&mut seed); 51 OsRng.try_fill_bytes(&mut seed).unwrap();
52 let seed = u64::from_le_bytes(seed); 52 let seed = u64::from_le_bytes(seed);
53 53
54 // Init network stack 54 // Init network stack
@@ -56,7 +56,7 @@ async fn main_task(spawner: Spawner) {
56 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 56 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
57 57
58 // Launch network task 58 // Launch network task
59 spawner.spawn(net_task(runner)).unwrap(); 59 spawner.spawn(net_task(runner).unwrap());
60 60
61 // Then we can use it! 61 // Then we can use it!
62 let mut rx_buffer = [0; 4096]; 62 let mut rx_buffer = [0; 4096];
@@ -95,6 +95,6 @@ fn main() {
95 95
96 let executor = EXECUTOR.init(Executor::new()); 96 let executor = EXECUTOR.init(Executor::new());
97 executor.run(|spawner| { 97 executor.run(|spawner| {
98 spawner.spawn(main_task(spawner)).unwrap(); 98 spawner.spawn(main_task(spawner).unwrap());
99 }); 99 });
100} 100}
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs
index a42c5dbb7..dff704b86 100644
--- a/examples/std/src/bin/net_dns.rs
+++ b/examples/std/src/bin/net_dns.rs
@@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources};
5use embassy_net_tuntap::TunTapDevice; 5use embassy_net_tuntap::TunTapDevice;
6use heapless::Vec; 6use heapless::Vec;
7use log::*; 7use log::*;
8use rand_core::{OsRng, RngCore}; 8use rand_core::{OsRng, TryRngCore};
9use static_cell::StaticCell; 9use static_cell::StaticCell;
10 10
11#[derive(Parser)] 11#[derive(Parser)]
@@ -45,7 +45,7 @@ async fn main_task(spawner: Spawner) {
45 45
46 // Generate random seed 46 // Generate random seed
47 let mut seed = [0; 8]; 47 let mut seed = [0; 8];
48 OsRng.fill_bytes(&mut seed); 48 OsRng.try_fill_bytes(&mut seed).unwrap();
49 let seed = u64::from_le_bytes(seed); 49 let seed = u64::from_le_bytes(seed);
50 50
51 // Init network stack 51 // Init network stack
@@ -53,7 +53,7 @@ async fn main_task(spawner: Spawner) {
53 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 53 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
54 54
55 // Launch network task 55 // Launch network task
56 spawner.spawn(net_task(runner)).unwrap(); 56 spawner.spawn(net_task(runner).unwrap());
57 57
58 let host = "example.com"; 58 let host = "example.com";
59 info!("querying host {:?}...", host); 59 info!("querying host {:?}...", host);
@@ -78,6 +78,6 @@ fn main() {
78 78
79 let executor = EXECUTOR.init(Executor::new()); 79 let executor = EXECUTOR.init(Executor::new());
80 executor.run(|spawner| { 80 executor.run(|spawner| {
81 spawner.spawn(main_task(spawner)).unwrap(); 81 spawner.spawn(main_task(spawner).unwrap());
82 }); 82 });
83} 83}
diff --git a/examples/std/src/bin/net_ppp.rs b/examples/std/src/bin/net_ppp.rs
index f667e8d4c..82272c798 100644
--- a/examples/std/src/bin/net_ppp.rs
+++ b/examples/std/src/bin/net_ppp.rs
@@ -23,7 +23,7 @@ use futures::io::BufReader;
23use heapless::Vec; 23use heapless::Vec;
24use log::*; 24use log::*;
25use nix::sys::termios; 25use nix::sys::termios;
26use rand_core::{OsRng, RngCore}; 26use rand_core::{OsRng, TryRngCore};
27use static_cell::StaticCell; 27use static_cell::StaticCell;
28 28
29use crate::serial_port::SerialPort; 29use crate::serial_port::SerialPort;
@@ -89,7 +89,7 @@ async fn main_task(spawner: Spawner) {
89 89
90 // Generate random seed 90 // Generate random seed
91 let mut seed = [0; 8]; 91 let mut seed = [0; 8];
92 OsRng.fill_bytes(&mut seed); 92 OsRng.try_fill_bytes(&mut seed).unwrap();
93 let seed = u64::from_le_bytes(seed); 93 let seed = u64::from_le_bytes(seed);
94 94
95 // Init network stack 95 // Init network stack
@@ -102,8 +102,8 @@ async fn main_task(spawner: Spawner) {
102 ); 102 );
103 103
104 // Launch network task 104 // Launch network task
105 spawner.spawn(net_task(net_runner)).unwrap(); 105 spawner.spawn(net_task(net_runner).unwrap());
106 spawner.spawn(ppp_task(stack, runner, port)).unwrap(); 106 spawner.spawn(ppp_task(stack, runner, port).unwrap());
107 107
108 // Then we can use it! 108 // Then we can use it!
109 let mut rx_buffer = [0; 4096]; 109 let mut rx_buffer = [0; 4096];
@@ -160,6 +160,6 @@ fn main() {
160 160
161 let executor = EXECUTOR.init(Executor::new()); 161 let executor = EXECUTOR.init(Executor::new());
162 executor.run(|spawner| { 162 executor.run(|spawner| {
163 spawner.spawn(main_task(spawner)).unwrap(); 163 spawner.spawn(main_task(spawner).unwrap());
164 }); 164 });
165} 165}
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs
index 02d4d3efb..c5c4da65f 100644
--- a/examples/std/src/bin/net_udp.rs
+++ b/examples/std/src/bin/net_udp.rs
@@ -5,7 +5,7 @@ use embassy_net::{Config, Ipv4Address, Ipv4Cidr, StackResources};
5use embassy_net_tuntap::TunTapDevice; 5use embassy_net_tuntap::TunTapDevice;
6use heapless::Vec; 6use heapless::Vec;
7use log::*; 7use log::*;
8use rand_core::{OsRng, RngCore}; 8use rand_core::{OsRng, TryRngCore};
9use static_cell::StaticCell; 9use static_cell::StaticCell;
10 10
11#[derive(Parser)] 11#[derive(Parser)]
@@ -44,7 +44,7 @@ async fn main_task(spawner: Spawner) {
44 44
45 // Generate random seed 45 // Generate random seed
46 let mut seed = [0; 8]; 46 let mut seed = [0; 8];
47 OsRng.fill_bytes(&mut seed); 47 OsRng.try_fill_bytes(&mut seed).unwrap();
48 let seed = u64::from_le_bytes(seed); 48 let seed = u64::from_le_bytes(seed);
49 49
50 // Init network stack 50 // Init network stack
@@ -52,7 +52,7 @@ async fn main_task(spawner: Spawner) {
52 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 52 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
53 53
54 // Launch network task 54 // Launch network task
55 spawner.spawn(net_task(runner)).unwrap(); 55 spawner.spawn(net_task(runner).unwrap());
56 56
57 // Then we can use it! 57 // Then we can use it!
58 let mut rx_meta = [PacketMetadata::EMPTY; 16]; 58 let mut rx_meta = [PacketMetadata::EMPTY; 16];
@@ -86,6 +86,6 @@ fn main() {
86 86
87 let executor = EXECUTOR.init(Executor::new()); 87 let executor = EXECUTOR.init(Executor::new());
88 executor.run(|spawner| { 88 executor.run(|spawner| {
89 spawner.spawn(main_task(spawner)).unwrap(); 89 spawner.spawn(main_task(spawner).unwrap());
90 }); 90 });
91} 91}
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs
index 10c85511d..1ed9997c4 100644
--- a/examples/std/src/bin/serial.rs
+++ b/examples/std/src/bin/serial.rs
@@ -50,6 +50,6 @@ fn main() {
50 50
51 let executor = EXECUTOR.init(Executor::new()); 51 let executor = EXECUTOR.init(Executor::new());
52 executor.run(|spawner| { 52 executor.run(|spawner| {
53 spawner.spawn(run()).unwrap(); 53 spawner.spawn(run().unwrap());
54 }); 54 });
55} 55}
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
index 18646a083..77886f471 100644
--- a/examples/std/src/bin/tcp_accept.rs
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -7,7 +7,7 @@ use embassy_time::{Duration, Timer};
7use embedded_io_async::Write as _; 7use embedded_io_async::Write as _;
8use heapless::Vec; 8use heapless::Vec;
9use log::*; 9use log::*;
10use rand_core::{OsRng, RngCore}; 10use rand_core::{OsRng, TryRngCore};
11use static_cell::StaticCell; 11use static_cell::StaticCell;
12 12
13#[derive(Parser)] 13#[derive(Parser)]
@@ -46,7 +46,7 @@ async fn main_task(spawner: Spawner) {
46 46
47 // Generate random seed 47 // Generate random seed
48 let mut seed = [0; 8]; 48 let mut seed = [0; 8];
49 OsRng.fill_bytes(&mut seed); 49 OsRng.try_fill_bytes(&mut seed).unwrap();
50 let seed = u64::from_le_bytes(seed); 50 let seed = u64::from_le_bytes(seed);
51 51
52 // Init network stack 52 // Init network stack
@@ -54,7 +54,7 @@ async fn main_task(spawner: Spawner) {
54 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 54 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
55 55
56 // Launch network task 56 // Launch network task
57 spawner.spawn(net_task(runner)).unwrap(); 57 spawner.spawn(net_task(runner).unwrap());
58 58
59 // Then we can use it! 59 // Then we can use it!
60 let mut rx_buffer = [0; 4096]; 60 let mut rx_buffer = [0; 4096];
@@ -101,6 +101,6 @@ fn main() {
101 101
102 let executor = EXECUTOR.init(Executor::new()); 102 let executor = EXECUTOR.init(Executor::new());
103 executor.run(|spawner| { 103 executor.run(|spawner| {
104 spawner.spawn(main_task(spawner)).unwrap(); 104 spawner.spawn(main_task(spawner).unwrap());
105 }); 105 });
106} 106}
diff --git a/examples/std/src/bin/tick.rs b/examples/std/src/bin/tick.rs
index f23cf3549..16b82c82b 100644
--- a/examples/std/src/bin/tick.rs
+++ b/examples/std/src/bin/tick.rs
@@ -17,5 +17,5 @@ async fn main(spawner: Spawner) {
17 .format_timestamp_nanos() 17 .format_timestamp_nanos()
18 .init(); 18 .init();
19 19
20 spawner.spawn(run()).unwrap(); 20 spawner.spawn(run().unwrap());
21} 21}
diff --git a/examples/std/tap.sh b/examples/std/tap.sh
index 39d92a099..fb89d2381 100644
--- a/examples/std/tap.sh
+++ b/examples/std/tap.sh
@@ -1,4 +1,4 @@
1ip tuntap add name tap99 mode tap user $USER 1ip tuntap add name tap99 mode tap user $SUDO_USER
2ip link set tap99 up 2ip link set tap99 up
3ip addr add 192.168.69.100/24 dev tap99 3ip addr add 192.168.69.100/24 dev tap99
4ip -6 addr add fe80::100/64 dev tap99 4ip -6 addr add fe80::100/64 dev tap99
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml
index 767b742f7..bb7b57496 100644
--- a/examples/stm32c0/Cargo.toml
+++ b/examples/stm32c0/Cargo.toml
@@ -3,22 +3,29 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32c031c6 to your chip name, if necessary. 9# Change stm32c031c6 to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13 14
14defmt = "0.3" 15defmt = "1.0.1"
15defmt-rtt = "0.4" 16defmt-rtt = "1.0.0"
16 17
17cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 18cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
18cortex-m-rt = "0.7.0" 19cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6" 20embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21heapless = { version = "0.8", default-features = false } 22heapless = { version = "0.8", default-features = false }
23chrono = { version = "^0.4", default-features = false}
22 24
23[profile.release] 25[profile.release]
24debug = 2 26debug = 2
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32c0" }
31]
diff --git a/examples/stm32c0/src/bin/rtc.rs b/examples/stm32c0/src/bin/rtc.rs
new file mode 100644
index 000000000..82d8a37ba
--- /dev/null
+++ b/examples/stm32c0/src/bin/rtc.rs
@@ -0,0 +1,35 @@
1#![no_std]
2#![no_main]
3
4use chrono::{NaiveDate, NaiveDateTime};
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::rtc::{Rtc, RtcConfig};
8use embassy_stm32::Config;
9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let config = Config::default();
15 let p = embassy_stm32::init(config);
16
17 info!("Hello World!");
18
19 let now = NaiveDate::from_ymd_opt(2020, 5, 15)
20 .unwrap()
21 .and_hms_opt(10, 30, 15)
22 .unwrap();
23
24 let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
25
26 rtc.set_datetime(now.into()).expect("datetime not set");
27
28 loop {
29 let now: NaiveDateTime = rtc.now().unwrap().into();
30
31 info!("{}", now.and_utc().timestamp());
32
33 Timer::after_millis(1000).await;
34 }
35}
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 932a97dc8..11ecbe3c2 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -3,20 +3,26 @@ name = "embassy-stm32f0-examples"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f091rc to your chip name, if necessary. 9# Change stm32f091rc to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "memory-x", "stm32f091rc", "time-driver-tim2", "exti", "unstable-pac"] }
10cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 11cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
11cortex-m-rt = "0.7.0" 12cortex-m-rt = "0.7.0"
12defmt = "0.3" 13defmt = "1.0.1"
13defmt-rtt = "0.4" 14defmt-rtt = "1.0.0"
14panic-probe = { version = "0.3", features = ["print-defmt"] } 15panic-probe = { version = "1.0.0", features = ["print-defmt"] }
15embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 16embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
16embassy-executor = { version = "0.7.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"] }
17embassy-time = { version = "0.4.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"] }
18static_cell = "2" 19static_cell = "2"
19portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 20portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
20 21
21[profile.release] 22[profile.release]
22debug = 2 23debug = 2
24
25[package.metadata.embassy]
26build = [
27 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32f0" }
28]
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs
new file mode 100644
index 000000000..ff98aac8e
--- /dev/null
+++ b/examples/stm32f0/src/bin/adc-watchdog.rs
@@ -0,0 +1,34 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::adc::{self, Adc, WatchdogChannels};
7use embassy_stm32::bind_interrupts;
8use embassy_stm32::peripherals::ADC1;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 ADC1_COMP => adc::InterruptHandler<ADC1>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default());
18 info!("ADC watchdog example");
19
20 let mut adc = Adc::new(p.ADC1, Irqs);
21 let pin = p.PC1;
22
23 loop {
24 // Wait for pin to go high
25 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F);
26 let v_high = adc.monitor_watchdog().await;
27 info!("ADC sample is high {}", v_high);
28
29 // Wait for pin to go low
30 adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF);
31 let v_low = adc.monitor_watchdog().await;
32 info!("ADC sample is low {}", v_low);
33 }
34}
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs
index 744df3e3b..f232e3290 100644
--- a/examples/stm32f0/src/bin/button_controlled_blink.rs
+++ b/examples/stm32f0/src/bin/button_controlled_blink.rs
@@ -46,7 +46,7 @@ async fn main(spawner: Spawner) {
46 BLINK_MS.store(del_var, Ordering::Relaxed); 46 BLINK_MS.store(del_var, Ordering::Relaxed);
47 47
48 // Spawn LED blinking task 48 // Spawn LED blinking task
49 spawner.spawn(led_task(p.PA5.into())).unwrap(); 49 spawner.spawn(led_task(p.PA5.into()).unwrap());
50 50
51 loop { 51 loop {
52 // Check if button got pressed 52 // Check if button got pressed
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs
index 84e4077ef..b5244afc8 100644
--- a/examples/stm32f0/src/bin/multiprio.rs
+++ b/examples/stm32f0/src/bin/multiprio.rs
@@ -134,16 +134,16 @@ fn main() -> ! {
134 // High-priority executor: USART1, priority level 6 134 // High-priority executor: USART1, priority level 6
135 interrupt::USART1.set_priority(Priority::P6); 135 interrupt::USART1.set_priority(Priority::P6);
136 let spawner = EXECUTOR_HIGH.start(interrupt::USART1); 136 let spawner = EXECUTOR_HIGH.start(interrupt::USART1);
137 unwrap!(spawner.spawn(run_high())); 137 spawner.spawn(unwrap!(run_high()));
138 138
139 // Medium-priority executor: USART2, priority level 7 139 // Medium-priority executor: USART2, priority level 7
140 interrupt::USART2.set_priority(Priority::P7); 140 interrupt::USART2.set_priority(Priority::P7);
141 let spawner = EXECUTOR_MED.start(interrupt::USART2); 141 let spawner = EXECUTOR_MED.start(interrupt::USART2);
142 unwrap!(spawner.spawn(run_med())); 142 spawner.spawn(unwrap!(run_med()));
143 143
144 // Low priority executor: runs in thread mode, using WFE/SEV 144 // Low priority executor: runs in thread mode, using WFE/SEV
145 let executor = EXECUTOR_LOW.init(Executor::new()); 145 let executor = EXECUTOR_LOW.init(Executor::new());
146 executor.run(|spawner| { 146 executor.run(|spawner| {
147 unwrap!(spawner.spawn(run_low())); 147 spawner.spawn(unwrap!(run_low()));
148 }); 148 });
149} 149}
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index fe800bc80..dcb58796b 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f103c8 to your chip name, if necessary. 9# Change stm32f103c8 to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any" ] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24nb = "1.0.0" 25nb = "1.0.0"
25static_cell = "2.0.0" 26static_cell = "2.0.0"
@@ -29,3 +30,8 @@ opt-level = "s"
29 30
30[profile.release] 31[profile.release]
31debug = 2 32debug = 2
33
34[package.metadata.embassy]
35build = [
36 { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f1" }
37]
diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs
index 6fe8e0b50..b5b26938d 100644
--- a/examples/stm32f1/src/bin/input_capture.rs
+++ b/examples/stm32f1/src/bin/input_capture.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{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::input_capture::{CapturePin, InputCapture}; 8use embassy_stm32::timer::input_capture::{CapturePin, InputCapture};
9use embassy_stm32::timer::{self, Channel}; 9use embassy_stm32::timer::{self, Channel};
@@ -37,10 +37,11 @@ async fn main(spawner: Spawner) {
37 let p = embassy_stm32::init(Default::default()); 37 let p = embassy_stm32::init(Default::default());
38 info!("Hello World!"); 38 info!("Hello World!");
39 39
40 unwrap!(spawner.spawn(blinky(p.PC13))); 40 spawner.spawn(unwrap!(blinky(p.PC13)));
41 41
42 let ch3 = CapturePin::new_ch3(p.PA2, Pull::None); 42 let ch3 = CapturePin::new(p.PA2, Pull::None);
43 let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); 43 let mut ic =
44 InputCapture::new::<AfioRemap<0>>(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
44 45
45 loop { 46 loop {
46 info!("wait for rising edge"); 47 info!("wait for rising edge");
diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs
index afbef3edb..9ae747018 100644
--- a/examples/stm32f1/src/bin/pwm_input.rs
+++ b/examples/stm32f1/src/bin/pwm_input.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{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::{bind_interrupts, peripherals, timer, Peri};
@@ -36,9 +36,9 @@ async fn main(spawner: Spawner) {
36 let p = embassy_stm32::init(Default::default()); 36 let p = embassy_stm32::init(Default::default());
37 info!("Hello World!"); 37 info!("Hello World!");
38 38
39 unwrap!(spawner.spawn(blinky(p.PC13))); 39 spawner.spawn(unwrap!(blinky(p.PC13)));
40 40
41 let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(10)); 41 let mut pwm_input = PwmInput::new_ch1::<AfioRemap<0>>(p.TIM2, p.PA0, Pull::None, khz(10));
42 pwm_input.enable(); 42 pwm_input.enable();
43 43
44 loop { 44 loop {
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 26be3f485..498c20d84 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -3,23 +3,29 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f207zg to your chip name, if necessary. 9# Change stm32f207zg to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13 14
14defmt = "0.3" 15defmt = "1.0.1"
15defmt-rtt = "0.4" 16defmt-rtt = "1.0.0"
16 17
17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
18cortex-m-rt = "0.7.0" 19cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6" 20embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21heapless = { version = "0.8", default-features = false } 22heapless = { version = "0.8", default-features = false }
22nb = "1.0.0" 23nb = "1.0.0"
23 24
24[profile.release] 25[profile.release]
25debug = 2 26debug = 2
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32f2" }
31]
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 31bf040b0..23025ef0b 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f303ze to your chip name, if necessary. 9# Change stm32f303ze to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-tim2", "exti"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24nb = "1.0.0" 25nb = "1.0.0"
25embedded-storage = "0.3.1" 26embedded-storage = "0.3.1"
@@ -27,3 +28,8 @@ static_cell = "2"
27 28
28[profile.release] 29[profile.release]
29debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f3" }
35]
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index f5ed5d2c9..a54d03212 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -113,8 +113,8 @@ async fn main(spawner: Spawner) {
113 ]; 113 ];
114 let leds = Leds::new(leds); 114 let leds = Leds::new(leds);
115 115
116 spawner.spawn(button_waiter(button)).unwrap(); 116 spawner.spawn(button_waiter(button).unwrap());
117 spawner.spawn(led_blinker(leds)).unwrap(); 117 spawner.spawn(led_blinker(leds).unwrap());
118} 118}
119 119
120#[embassy_executor::task] 120#[embassy_executor::task]
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index b4620888f..2f2ffdea2 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -135,16 +135,16 @@ fn main() -> ! {
135 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
136 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
138 unwrap!(spawner.spawn(run_high())); 138 spawner.spawn(unwrap!(run_high()));
139 139
140 // Medium-priority executor: UART5, priority level 7 140 // Medium-priority executor: UART5, priority level 7
141 interrupt::UART5.set_priority(Priority::P7); 141 interrupt::UART5.set_priority(Priority::P7);
142 let spawner = EXECUTOR_MED.start(interrupt::UART5); 142 let spawner = EXECUTOR_MED.start(interrupt::UART5);
143 unwrap!(spawner.spawn(run_med())); 143 spawner.spawn(unwrap!(run_med()));
144 144
145 // Low priority executor: runs in thread mode, using WFE/SEV 145 // Low priority executor: runs in thread mode, using WFE/SEV
146 let executor = EXECUTOR_LOW.init(Executor::new()); 146 let executor = EXECUTOR_LOW.init(Executor::new());
147 executor.run(|spawner| { 147 executor.run(|spawner| {
148 unwrap!(spawner.spawn(run_low())); 148 spawner.spawn(unwrap!(run_low()));
149 }); 149 });
150} 150}
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml
index 5fb6d60c5..3495b118c 100644
--- a/examples/stm32f334/Cargo.toml
+++ b/examples/stm32f334/Cargo.toml
@@ -3,23 +3,29 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.7.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.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 12embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
12embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17 18
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
20embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
21panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22heapless = { version = "0.8", default-features = false } 23heapless = { version = "0.8", default-features = false }
23nb = "1.0.0" 24nb = "1.0.0"
24embedded-storage = "0.3.1" 25embedded-storage = "0.3.1"
25static_cell = "2" 26static_cell = "2"
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f334" }
31]
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 7aa4354ca..fb5f86aac 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -3,20 +3,21 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f429zi to your chip name, if necessary. 9# Change stm32f429zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim4", "exti", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt" ] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt" ] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] }
15embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.2.1", path = "../../embassy-net-wiznet", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20 21
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
@@ -24,7 +25,7 @@ embedded-hal = "0.2.6"
24embedded-hal-bus = { version = "0.2", features = ["async"] } 25embedded-hal-bus = { version = "0.2", features = ["async"] }
25embedded-io = { version = "0.6.0" } 26embedded-io = { version = "0.6.0" }
26embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.6.1" }
27panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
28futures-util = { version = "0.3.30", default-features = false } 29futures-util = { version = "0.3.30", default-features = false }
29heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 31critical-section = "1.1"
@@ -37,3 +38,8 @@ chrono = { version = "^0.4", default-features = false}
37 38
38[profile.release] 39[profile.release]
39debug = 2 40debug = 2
41
42[package.metadata.embassy]
43build = [
44 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f4" }
45]
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs
index 43a761e6d..2ec48640e 100644
--- a/examples/stm32f4/src/bin/adc_dma.rs
+++ b/examples/stm32f4/src/bin/adc_dma.rs
@@ -11,7 +11,7 @@ use {defmt_rtt as _, panic_probe as _};
11#[embassy_executor::main] 11#[embassy_executor::main]
12async fn main(spawner: Spawner) { 12async fn main(spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
14 spawner.must_spawn(adc_task(p)); 14 spawner.spawn(adc_task(p).unwrap());
15} 15}
16 16
17#[embassy_executor::task] 17#[embassy_executor::task]
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs
index 634d8e2c6..f41a60529 100644
--- a/examples/stm32f4/src/bin/eth.rs
+++ b/examples/stm32f4/src/bin/eth.rs
@@ -91,7 +91,7 @@ async fn main(spawner: Spawner) -> ! {
91 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 91 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
92 92
93 // Launch network task 93 // Launch network task
94 unwrap!(spawner.spawn(net_task(runner))); 94 spawner.spawn(unwrap!(net_task(runner)));
95 95
96 // Ensure DHCP configuration is up before trying connect 96 // Ensure DHCP configuration is up before trying connect
97 stack.wait_config_up().await; 97 stack.wait_config_up().await;
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs
index 6e6bef08c..7ce3bfe75 100644
--- a/examples/stm32f4/src/bin/eth_w5500.rs
+++ b/examples/stm32f4/src/bin/eth_w5500.rs
@@ -83,7 +83,7 @@ async fn main(spawner: Spawner) -> ! {
83 let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset) 83 let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset)
84 .await 84 .await
85 .unwrap(); 85 .unwrap();
86 unwrap!(spawner.spawn(ethernet_task(runner))); 86 spawner.spawn(unwrap!(ethernet_task(runner)));
87 87
88 let config = embassy_net::Config::dhcpv4(Default::default()); 88 let config = embassy_net::Config::dhcpv4(Default::default());
89 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { 89 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
@@ -96,7 +96,7 @@ async fn main(spawner: Spawner) -> ! {
96 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 96 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
97 97
98 // Launch network task 98 // Launch network task
99 unwrap!(spawner.spawn(net_task(runner))); 99 spawner.spawn(unwrap!(net_task(runner)));
100 100
101 // Ensure DHCP configuration is up before trying connect 101 // Ensure DHCP configuration is up before trying connect
102 stack.wait_config_up().await; 102 stack.wait_config_up().await;
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs
index 755713542..2feb9de09 100644
--- a/examples/stm32f4/src/bin/flash_async.rs
+++ b/examples/stm32f4/src/bin/flash_async.rs
@@ -21,7 +21,7 @@ async fn main(spawner: Spawner) {
21 let mut f = Flash::new(p.FLASH, Irqs); 21 let mut f = Flash::new(p.FLASH, Irqs);
22 22
23 // Led should blink uninterrupted during ~2sec erase operation 23 // Led should blink uninterrupted during ~2sec erase operation
24 spawner.spawn(blinky(p.PB7.into())).unwrap(); 24 spawner.spawn(blinky(p.PB7.into()).unwrap());
25 25
26 // Test on bank 2 in order not to stall CPU. 26 // Test on bank 2 in order not to stall CPU.
27 test_flash(&mut f, 1024 * 1024, 128 * 1024).await; 27 test_flash(&mut f, 1024 * 1024, 128 * 1024).await;
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
index 4a96357a4..49710a92a 100644
--- a/examples/stm32f4/src/bin/i2c.rs
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::{Error, I2c}; 6use embassy_stm32::i2c::{Error, I2c};
7use embassy_stm32::time::Hertz;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10const ADDRESS: u8 = 0x5F; 9const ADDRESS: u8 = 0x5F;
@@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) {
15 info!("Hello world!"); 14 info!("Hello world!");
16 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
17 16
18 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); 17 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default());
19 18
20 let mut data = [0u8; 1]; 19 let mut data = [0u8; 1];
21 20
diff --git a/examples/stm32f4/src/bin/i2c_async.rs b/examples/stm32f4/src/bin/i2c_async.rs
index 90d11d4b4..0065e92f3 100644
--- a/examples/stm32f4/src/bin/i2c_async.rs
+++ b/examples/stm32f4/src/bin/i2c_async.rs
@@ -7,7 +7,6 @@
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::i2c::I2c; 9use embassy_stm32::i2c::I2c;
10use embassy_stm32::time::Hertz;
11use embassy_stm32::{bind_interrupts, i2c, peripherals}; 10use embassy_stm32::{bind_interrupts, i2c, peripherals};
12use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
13 12
@@ -23,16 +22,7 @@ async fn main(_spawner: Spawner) {
23 info!("Hello world!"); 22 info!("Hello world!");
24 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
25 24
26 let mut i2c = I2c::new( 25 let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default());
27 p.I2C1,
28 p.PB8,
29 p.PB7,
30 Irqs,
31 p.DMA1_CH6,
32 p.DMA1_CH0,
33 Hertz(100_000),
34 Default::default(),
35 );
36 26
37 loop { 27 loop {
38 let a1454_read_sensor_command = [0x1F]; 28 let a1454_read_sensor_command = [0x1F];
diff --git a/examples/stm32f4/src/bin/i2c_comparison.rs b/examples/stm32f4/src/bin/i2c_comparison.rs
index 55c4891e3..59bdb8b67 100644
--- a/examples/stm32f4/src/bin/i2c_comparison.rs
+++ b/examples/stm32f4/src/bin/i2c_comparison.rs
@@ -10,7 +10,6 @@
10use defmt::*; 10use defmt::*;
11use embassy_executor::Spawner; 11use embassy_executor::Spawner;
12use embassy_stm32::i2c::I2c; 12use embassy_stm32::i2c::I2c;
13use embassy_stm32::time::Hertz;
14use embassy_stm32::{bind_interrupts, i2c, peripherals}; 13use embassy_stm32::{bind_interrupts, i2c, peripherals};
15use embassy_time::Instant; 14use embassy_time::Instant;
16use futures_util::future::try_join3; 15use futures_util::future::try_join3;
@@ -48,38 +47,11 @@ async fn main(_spawner: Spawner) {
48 info!("Setting up peripherals."); 47 info!("Setting up peripherals.");
49 let p = embassy_stm32::init(Default::default()); 48 let p = embassy_stm32::init(Default::default());
50 49
51 let mut i2c1 = I2c::new( 50 let mut i2c1 = I2c::new(p.I2C1, p.PB8, p.PB7, Irqs, p.DMA1_CH6, p.DMA1_CH0, Default::default());
52 p.I2C1,
53 p.PB8,
54 p.PB7,
55 Irqs,
56 p.DMA1_CH6,
57 p.DMA1_CH0,
58 Hertz(100_000),
59 Default::default(),
60 );
61 51
62 let mut i2c2 = I2c::new( 52 let mut i2c2 = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH7, p.DMA1_CH3, Default::default());
63 p.I2C2,
64 p.PB10,
65 p.PB11,
66 Irqs,
67 p.DMA1_CH7,
68 p.DMA1_CH3,
69 Hertz(100_000),
70 Default::default(),
71 );
72 53
73 let mut i2c3 = I2c::new( 54 let mut i2c3 = I2c::new(p.I2C3, p.PA8, p.PC9, Irqs, p.DMA1_CH4, p.DMA1_CH2, Default::default());
74 p.I2C3,
75 p.PA8,
76 p.PC9,
77 Irqs,
78 p.DMA1_CH4,
79 p.DMA1_CH2,
80 Hertz(100_000),
81 Default::default(),
82 );
83 55
84 let a1454_read_sensor_command = [0x1F]; 56 let a1454_read_sensor_command = [0x1F];
85 let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0]; 57 let mut i2c1_buffer: [u8; 4] = [0, 0, 0, 0];
diff --git a/examples/stm32f4/src/bin/i2s_dma.rs b/examples/stm32f4/src/bin/i2s_dma.rs
index db5103d0f..6051a3c5a 100644
--- a/examples/stm32f4/src/bin/i2s_dma.rs
+++ b/examples/stm32f4/src/bin/i2s_dma.rs
@@ -72,7 +72,6 @@ async fn main(_spawner: Spawner) {
72 p.PB3, // ck 72 p.PB3, // ck
73 p.DMA1_CH7, 73 p.DMA1_CH7,
74 &mut dma_buffer, 74 &mut dma_buffer,
75 Hertz(48_000),
76 i2s_config, 75 i2s_config,
77 ); 76 );
78 i2s.start(); 77 i2s.start();
diff --git a/examples/stm32f4/src/bin/input_capture.rs b/examples/stm32f4/src/bin/input_capture.rs
index fe5e2bdfc..9998c4733 100644
--- a/examples/stm32f4/src/bin/input_capture.rs
+++ b/examples/stm32f4/src/bin/input_capture.rs
@@ -37,9 +37,9 @@ async fn main(spawner: Spawner) {
37 let p = embassy_stm32::init(Default::default()); 37 let p = embassy_stm32::init(Default::default());
38 info!("Hello World!"); 38 info!("Hello World!");
39 39
40 unwrap!(spawner.spawn(blinky(p.PB2))); 40 spawner.spawn(unwrap!(blinky(p.PB2)));
41 41
42 let ch3 = CapturePin::new_ch3(p.PB10, Pull::None); 42 let ch3 = CapturePin::new(p.PB10, Pull::None);
43 let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); 43 let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
44 44
45 loop { 45 loop {
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index b4620888f..2f2ffdea2 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -135,16 +135,16 @@ fn main() -> ! {
135 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
136 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
138 unwrap!(spawner.spawn(run_high())); 138 spawner.spawn(unwrap!(run_high()));
139 139
140 // Medium-priority executor: UART5, priority level 7 140 // Medium-priority executor: UART5, priority level 7
141 interrupt::UART5.set_priority(Priority::P7); 141 interrupt::UART5.set_priority(Priority::P7);
142 let spawner = EXECUTOR_MED.start(interrupt::UART5); 142 let spawner = EXECUTOR_MED.start(interrupt::UART5);
143 unwrap!(spawner.spawn(run_med())); 143 spawner.spawn(unwrap!(run_med()));
144 144
145 // Low priority executor: runs in thread mode, using WFE/SEV 145 // Low priority executor: runs in thread mode, using WFE/SEV
146 let executor = EXECUTOR_LOW.init(Executor::new()); 146 let executor = EXECUTOR_LOW.init(Executor::new());
147 executor.run(|spawner| { 147 executor.run(|spawner| {
148 unwrap!(spawner.spawn(run_low())); 148 spawner.spawn(unwrap!(run_low()));
149 }); 149 });
150} 150}
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 04811162b..e385842f0 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let ch1_pin = PwmPin::new_ch1(p.PE9, OutputType::PushPull); 17 let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull);
18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); 18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
19 let mut ch1 = pwm.ch1(); 19 let mut ch1 = pwm.ch1();
20 ch1.enable(); 20 ch1.enable();
diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs
index 161f43c48..c981f1a76 100644
--- a/examples/stm32f4/src/bin/pwm_complementary.rs
+++ b/examples/stm32f4/src/bin/pwm_complementary.rs
@@ -16,8 +16,8 @@ async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
17 info!("Hello World!"); 17 info!("Hello World!");
18 18
19 let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); 19 let ch1 = PwmPin::new(p.PE9, OutputType::PushPull);
20 let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); 20 let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
21 let mut pwm = ComplementaryPwm::new( 21 let mut pwm = ComplementaryPwm::new(
22 p.TIM1, 22 p.TIM1,
23 Some(ch1), 23 Some(ch1),
diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs
index 465cbe4f5..e8bfa524f 100644
--- a/examples/stm32f4/src/bin/pwm_input.rs
+++ b/examples/stm32f4/src/bin/pwm_input.rs
@@ -36,9 +36,9 @@ async fn main(spawner: Spawner) {
36 let p = embassy_stm32::init(Default::default()); 36 let p = embassy_stm32::init(Default::default());
37 info!("Hello World!"); 37 info!("Hello World!");
38 38
39 unwrap!(spawner.spawn(blinky(p.PB2))); 39 spawner.spawn(unwrap!(blinky(p.PB2)));
40 40
41 let mut pwm_input = PwmInput::new(p.TIM3, p.PA6, Pull::None, khz(10)); 41 let mut pwm_input = PwmInput::new_ch1(p.TIM3, p.PA6, Pull::None, khz(10));
42 pwm_input.enable(); 42 pwm_input.enable();
43 43
44 loop { 44 loop {
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 322cb90c7..7abbe8719 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -118,11 +118,11 @@ async fn main(spawner: Spawner) {
118 // Build the builder. 118 // Build the builder.
119 let usb = builder.build(); 119 let usb = builder.build();
120 120
121 unwrap!(spawner.spawn(usb_task(usb))); 121 spawner.spawn(unwrap!(usb_task(usb)));
122 122
123 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); 123 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
124 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); 124 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
125 unwrap!(spawner.spawn(usb_ncm_task(runner))); 125 spawner.spawn(unwrap!(usb_ncm_task(runner)));
126 126
127 let config = embassy_net::Config::dhcpv4(Default::default()); 127 let config = embassy_net::Config::dhcpv4(Default::default());
128 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { 128 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
@@ -141,7 +141,7 @@ async fn main(spawner: Spawner) {
141 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 141 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
142 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 142 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
143 143
144 unwrap!(spawner.spawn(net_task(runner))); 144 spawner.spawn(unwrap!(net_task(runner)));
145 145
146 // And now we can use it! 146 // And now we can use it!
147 147
diff --git a/examples/stm32f4/src/bin/usb_uac_speaker.rs b/examples/stm32f4/src/bin/usb_uac_speaker.rs
index 654bec498..79bd2d914 100644
--- a/examples/stm32f4/src/bin/usb_uac_speaker.rs
+++ b/examples/stm32f4/src/bin/usb_uac_speaker.rs
@@ -375,9 +375,9 @@ async fn main(spawner: Spawner) {
375 } 375 }
376 376
377 // Launch USB audio tasks. 377 // Launch USB audio tasks.
378 unwrap!(spawner.spawn(usb_control_task(control_monitor))); 378 spawner.spawn(unwrap!(usb_control_task(control_monitor)));
379 unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); 379 spawner.spawn(unwrap!(usb_streaming_task(stream, sender)));
380 unwrap!(spawner.spawn(usb_feedback_task(feedback))); 380 spawner.spawn(unwrap!(usb_feedback_task(feedback)));
381 unwrap!(spawner.spawn(usb_task(usb_device))); 381 spawner.spawn(unwrap!(usb_task(usb_device)));
382 unwrap!(spawner.spawn(audio_receiver_task(receiver))); 382 spawner.spawn(unwrap!(audio_receiver_task(receiver)));
383} 383}
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs
index ca924e181..5153e1cfd 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm.rs
@@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) {
50 50
51 let mut ws2812_pwm = SimplePwm::new( 51 let mut ws2812_pwm = SimplePwm::new(
52 dp.TIM3, 52 dp.TIM3,
53 Some(PwmPin::new_ch1(dp.PB4, OutputType::PushPull)), 53 Some(PwmPin::new(dp.PB4, OutputType::PushPull)),
54 None, 54 None,
55 None, 55 None,
56 None, 56 None,
diff --git a/examples/stm32f469/Cargo.toml b/examples/stm32f469/Cargo.toml
index 4d403bae8..f1d0e411a 100644
--- a/examples/stm32f469/Cargo.toml
+++ b/examples/stm32f469/Cargo.toml
@@ -3,20 +3,26 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Specific examples only for stm32f469 9# Specific examples only for stm32f469
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f469ni", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
12 13
13defmt = "0.3" 14defmt = "1.0.1"
14defmt-rtt = "0.4" 15defmt-rtt = "1.0.0"
15 16
16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
17cortex-m-rt = "0.7.0" 18cortex-m-rt = "0.7.0"
18embedded-hal = "1.0.0" 19embedded-hal = "1.0.0"
19panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "1.0.0", features = ["print-defmt"] }
20 21
21[profile.release] 22[profile.release]
22debug = 2 23debug = 2
24
25[package.metadata.embassy]
26build = [
27 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f469" }
28]
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 1a46931d9..5d7763334 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -3,28 +3,28 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f777zi to your chip name, if necessary. 9# Change stm32f777zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32f777zi", "memory-x", "unstable-pac", "time-driver-any", "exti", "single-bank"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
14embedded-io-async = { version = "0.6.1" } 15embedded-io-async = { version = "0.6.1" }
15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 16embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20 21
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6" 24embedded-hal = "0.2.6"
24panic-probe = { version = "0.3", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
26nb = "1.0.0" 27nb = "1.0.0"
27rand_core = "0.6.3"
28critical-section = "1.1" 28critical-section = "1.1"
29embedded-storage = "0.3.1" 29embedded-storage = "0.3.1"
30static_cell = "2" 30static_cell = "2"
@@ -34,3 +34,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "he
34 34
35[profile.release] 35[profile.release]
36debug = 2 36debug = 2
37
38[package.metadata.embassy]
39build = [
40 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32f7" }
41]
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs
index 58ba940a8..9a91ac814 100644
--- a/examples/stm32f7/src/bin/can.rs
+++ b/examples/stm32f7/src/bin/can.rs
@@ -64,7 +64,7 @@ async fn main(spawner: Spawner) {
64 64
65 static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new(); 65 static CAN_TX: StaticCell<CanTx<'static>> = StaticCell::new();
66 let tx = CAN_TX.init(tx); 66 let tx = CAN_TX.init(tx);
67 spawner.spawn(send_can_message(tx)).unwrap(); 67 spawner.spawn(send_can_message(tx).unwrap());
68 68
69 loop { 69 loop {
70 let envelope = rx.read().await.unwrap(); 70 let envelope = rx.read().await.unwrap();
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs
index 235853cb9..a31e9b4f2 100644
--- a/examples/stm32f7/src/bin/cryp.rs
+++ b/examples/stm32f7/src/bin/cryp.rs
@@ -68,7 +68,9 @@ async fn main(_spawner: Spawner) -> ! {
68 ); 68 );
69 69
70 // Decrypt in software using AES-GCM 128-bit 70 // Decrypt in software using AES-GCM 128-bit
71 let _ = cipher.decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec); 71 cipher
72 .decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec)
73 .unwrap();
72 74
73 let sw_end_time = Instant::now(); 75 let sw_end_time = Instant::now();
74 let sw_execution_time = sw_end_time - sw_start_time; 76 let sw_execution_time = sw_end_time - sw_start_time;
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index 17ab7fc00..b13b7bdda 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -12,7 +12,6 @@ use embassy_stm32::time::Hertz;
12use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 12use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use embedded_io_async::Write; 14use embedded_io_async::Write;
15use rand_core::RngCore;
16use static_cell::StaticCell; 15use static_cell::StaticCell;
17use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
18 17
@@ -92,7 +91,7 @@ async fn main(spawner: Spawner) -> ! {
92 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 91 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
93 92
94 // Launch network task 93 // Launch network task
95 unwrap!(spawner.spawn(net_task(runner))); 94 spawner.spawn(unwrap!(net_task(runner)));
96 95
97 // Ensure DHCP configuration is up before trying connect 96 // Ensure DHCP configuration is up before trying connect
98 stack.wait_config_up().await; 97 stack.wait_config_up().await;
diff --git a/examples/stm32f7/src/bin/qspi.rs b/examples/stm32f7/src/bin/qspi.rs
index bd3287964..80652b865 100644
--- a/examples/stm32f7/src/bin/qspi.rs
+++ b/examples/stm32f7/src/bin/qspi.rs
@@ -273,13 +273,14 @@ async fn main(_spawner: Spawner) -> ! {
273 let p = embassy_stm32::init(config); 273 let p = embassy_stm32::init(config);
274 info!("Embassy initialized"); 274 info!("Embassy initialized");
275 275
276 let config = QspiCfg { 276 let mut config = QspiCfg::default();
277 memory_size: MemorySize::_8MiB, 277 config.memory_size = MemorySize::_8MiB;
278 address_size: AddressSize::_24bit, 278 config.address_size = AddressSize::_24bit;
279 prescaler: 16, 279 config.prescaler = 16;
280 cs_high_time: ChipSelectHighTime::_1Cycle, 280 config.cs_high_time = ChipSelectHighTime::_1Cycle;
281 fifo_threshold: FIFOThresholdLevel::_16Bytes, 281 config.fifo_threshold = FIFOThresholdLevel::_16Bytes;
282 }; 282 config.sample_shifting = SampleShifting::None;
283
283 let driver = Qspi::new_bank1( 284 let driver = Qspi::new_bank1(
284 p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config, 285 p.QUADSPI, p.PF8, p.PF9, p.PE2, p.PF6, p.PF10, p.PB10, p.DMA2_CH7, config,
285 ); 286 );
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index 319d84179..1c9451469 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32g0b1re to your chip name, if necessary. 9# Change stm32g0b1re to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g0b1re", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 25portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
25 26
@@ -27,3 +28,8 @@ embedded-io-async = { version = "0.6.1" }
27 28
28[profile.release] 29[profile.release]
29debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32g0" }
35]
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs
index 6c7f3b48a..7d8653ef2 100644
--- a/examples/stm32g0/src/bin/adc.rs
+++ b/examples/stm32g0/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, SampleTime}; 6use embassy_stm32::adc::{Adc, Clock, Presc, 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
@@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 13 info!("Hello World!");
14 14
15 let mut adc = Adc::new(p.ADC1); 15 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 });
16 adc.set_sample_time(SampleTime::CYCLES79_5); 16 adc.set_sample_time(SampleTime::CYCLES79_5);
17 let mut pin = p.PA1; 17 let mut pin = p.PA1;
18 18
diff --git a/examples/stm32g0/src/bin/adc_dma.rs b/examples/stm32g0/src/bin/adc_dma.rs
index d7515933c..8266a6d83 100644
--- a/examples/stm32g0/src/bin/adc_dma.rs
+++ b/examples/stm32g0/src/bin/adc_dma.rs
@@ -3,7 +3,7 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, AdcChannel as _, SampleTime}; 6use embassy_stm32::adc::{Adc, AdcChannel as _, Clock, Presc, 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
@@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) {
17 17
18 info!("Hello World!"); 18 info!("Hello World!");
19 19
20 let mut adc = Adc::new(p.ADC1); 20 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 });
21 21
22 let mut dma = p.DMA1_CH1; 22 let mut dma = p.DMA1_CH1;
23 let mut vrefint_channel = adc.enable_vrefint().degrade_adc(); 23 let mut vrefint_channel = adc.enable_vrefint().degrade_adc();
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs
index 9c5dd872a..bc49fac83 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, SampleTime}; 10use embassy_stm32::adc::{Adc, Clock, 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,7 +16,7 @@ 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(p.ADC1); 19 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 });
20 adc.set_sample_time(SampleTime::CYCLES1_5); 20 adc.set_sample_time(SampleTime::CYCLES1_5);
21 let mut pin = p.PA1; 21 let mut pin = p.PA1;
22 22
diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs
index dfb6e0edc..705905f01 100644
--- a/examples/stm32g0/src/bin/hf_timer.rs
+++ b/examples/stm32g0/src/bin/hf_timer.rs
@@ -37,8 +37,8 @@ async fn main(_spawner: Spawner) {
37 } 37 }
38 let p = embassy_stm32::init(config); 38 let p = embassy_stm32::init(config);
39 39
40 let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 40 let ch1 = PwmPin::new(p.PA8, OutputType::PushPull);
41 let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); 41 let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
42 42
43 let mut pwm = ComplementaryPwm::new( 43 let mut pwm = ComplementaryPwm::new(
44 p.TIM1, 44 p.TIM1,
diff --git a/examples/stm32g0/src/bin/i2c_async.rs b/examples/stm32g0/src/bin/i2c_async.rs
index 7e3189b05..e62d9266b 100644
--- a/examples/stm32g0/src/bin/i2c_async.rs
+++ b/examples/stm32g0/src/bin/i2c_async.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::{self, I2c}; 6use embassy_stm32::i2c::{self, I2c};
7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, peripherals}; 7use embassy_stm32::{bind_interrupts, peripherals};
9use embassy_time::{Duration, Timer}; 8use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
@@ -23,16 +22,7 @@ async fn main(_spawner: Spawner) {
23 let p = embassy_stm32::init(Default::default()); 22 let p = embassy_stm32::init(Default::default());
24 23
25 let mut data = [0u8; 2]; 24 let mut data = [0u8; 2];
26 let mut i2c = I2c::new( 25 let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default());
27 p.I2C1,
28 p.PB8,
29 p.PB9,
30 Irqs,
31 p.DMA1_CH1,
32 p.DMA1_CH2,
33 Hertz(100_000),
34 Default::default(),
35 );
36 26
37 loop { 27 loop {
38 match i2c.write_read(TMP117_ADDR, &[TMP117_TEMP_RESULT], &mut data).await { 28 match i2c.write_read(TMP117_ADDR, &[TMP117_TEMP_RESULT], &mut data).await {
diff --git a/examples/stm32g0/src/bin/input_capture.rs b/examples/stm32g0/src/bin/input_capture.rs
index 08df4e043..5501a6941 100644
--- a/examples/stm32g0/src/bin/input_capture.rs
+++ b/examples/stm32g0/src/bin/input_capture.rs
@@ -44,15 +44,15 @@ async fn main(spawner: Spawner) {
44 let p = embassy_stm32::init(Default::default()); 44 let p = embassy_stm32::init(Default::default());
45 info!("Hello World!"); 45 info!("Hello World!");
46 46
47 unwrap!(spawner.spawn(blinky(p.PB1))); 47 spawner.spawn(unwrap!(blinky(p.PB1)));
48 48
49 // Connect PB1 and PA8 with a 1k Ohm resistor 49 // Connect PB1 and PA8 with a 1k Ohm resistor
50 let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 50 let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull);
51 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); 51 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
52 pwm.ch1().enable(); 52 pwm.ch1().enable();
53 pwm.ch1().set_duty_cycle(50); 53 pwm.ch1().set_duty_cycle(50);
54 54
55 let ch1 = CapturePin::new_ch1(p.PA0, Pull::None); 55 let ch1 = CapturePin::new(p.PA0, Pull::None);
56 let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default()); 56 let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default());
57 57
58 let mut old_capture = 0; 58 let mut old_capture = 0;
diff --git a/examples/stm32g0/src/bin/pwm_complementary.rs b/examples/stm32g0/src/bin/pwm_complementary.rs
index 97b163c40..dbd9194c9 100644
--- a/examples/stm32g0/src/bin/pwm_complementary.rs
+++ b/examples/stm32g0/src/bin/pwm_complementary.rs
@@ -26,10 +26,10 @@ use {defmt_rtt as _, panic_probe as _};
26async fn main(_spawner: Spawner) { 26async fn main(_spawner: Spawner) {
27 let p = embassy_stm32::init(Default::default()); 27 let p = embassy_stm32::init(Default::default());
28 28
29 let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 29 let ch1 = PwmPin::new(p.PA8, OutputType::PushPull);
30 let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); 30 let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
31 let ch2 = PwmPin::new_ch2(p.PB3, OutputType::PushPull); 31 let ch2 = PwmPin::new(p.PB3, OutputType::PushPull);
32 let ch2n = ComplementaryPwmPin::new_ch2(p.PB0, OutputType::PushPull); 32 let ch2n = ComplementaryPwmPin::new(p.PB0, OutputType::PushPull);
33 33
34 let mut pwm = ComplementaryPwm::new( 34 let mut pwm = ComplementaryPwm::new(
35 p.TIM1, 35 p.TIM1,
diff --git a/examples/stm32g0/src/bin/pwm_input.rs b/examples/stm32g0/src/bin/pwm_input.rs
index 9d6b5fe97..72aa07c03 100644
--- a/examples/stm32g0/src/bin/pwm_input.rs
+++ b/examples/stm32g0/src/bin/pwm_input.rs
@@ -40,14 +40,14 @@ bind_interrupts!(struct Irqs {
40async fn main(spawner: Spawner) { 40async fn main(spawner: Spawner) {
41 let p = embassy_stm32::init(Default::default()); 41 let p = embassy_stm32::init(Default::default());
42 42
43 unwrap!(spawner.spawn(blinky(p.PB1))); 43 spawner.spawn(unwrap!(blinky(p.PB1)));
44 // Connect PA8 and PA6 with a 1k Ohm resistor 44 // Connect PA8 and PA6 with a 1k Ohm resistor
45 let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull); 45 let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull);
46 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default()); 46 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
47 pwm.ch1().set_duty_cycle_fraction(1, 4); 47 pwm.ch1().set_duty_cycle_fraction(1, 4);
48 pwm.ch1().enable(); 48 pwm.ch1().enable();
49 49
50 let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); 50 let mut pwm_input = PwmInput::new_ch1(p.TIM2, p.PA0, Pull::None, khz(1000));
51 pwm_input.enable(); 51 pwm_input.enable();
52 52
53 loop { 53 loop {
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index aa01d84e2..102960980 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -3,27 +3,33 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32g491re to your chip name, if necessary. 9# Change stm32g491re to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15usbd-hid = "0.8.1" 16usbd-hid = "0.8.1"
16 17
17defmt = "0.3" 18defmt = "1.0.1"
18defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
19 20
20cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
22embedded-hal = "0.2.6" 23embedded-hal = "0.2.6"
23embedded-can = { version = "0.4" } 24embedded-can = { version = "0.4" }
24panic-probe = { version = "0.3", features = ["print-defmt"] } 25panic-probe = { version = "1.0.0", features = ["print-defmt"] }
25heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
26static_cell = "2.0.0" 27static_cell = "2.0.0"
27 28
28[profile.release] 29[profile.release]
29debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32g4" }
35]
diff --git a/examples/stm32g4/src/bin/i2c_slave.rs b/examples/stm32g4/src/bin/i2c_slave.rs
new file mode 100644
index 000000000..65aca1c1b
--- /dev/null
+++ b/examples/stm32g4/src/bin/i2c_slave.rs
@@ -0,0 +1,149 @@
1//! This example shows how to use an stm32 as both a master and a slave.
2#![no_std]
3#![no_main]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Address, OwnAddresses, SlaveCommandKind};
8use embassy_stm32::mode::Async;
9use embassy_stm32::time::Hertz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals};
11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 I2C1_ER => i2c::ErrorInterruptHandler<peripherals::I2C1>;
16 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
17 I2C2_ER => i2c::ErrorInterruptHandler<peripherals::I2C2>;
18 I2C2_EV => i2c::EventInterruptHandler<peripherals::I2C2>;
19});
20
21const DEV_ADDR: u8 = 0x42;
22
23#[embassy_executor::task]
24async fn device_task(mut dev: i2c::I2c<'static, Async, i2c::MultiMaster>) -> ! {
25 info!("Device start");
26
27 let mut state = 0;
28
29 loop {
30 let mut buf = [0u8; 128];
31 match dev.listen().await {
32 Ok(i2c::SlaveCommand {
33 kind: SlaveCommandKind::Read,
34 address: Address::SevenBit(DEV_ADDR),
35 }) => match dev.respond_to_read(&[state]).await {
36 Ok(i2c::SendStatus::LeftoverBytes(x)) => info!("tried to write {} extra bytes", x),
37 Ok(i2c::SendStatus::Done) => {}
38 Err(e) => error!("error while responding {}", e),
39 },
40 Ok(i2c::SlaveCommand {
41 kind: SlaveCommandKind::Write,
42 address: Address::SevenBit(DEV_ADDR),
43 }) => match dev.respond_to_write(&mut buf).await {
44 Ok(len) => {
45 info!("Device received write: {}", buf[..len]);
46
47 if match buf[0] {
48 // Set the state
49 0xC2 => {
50 state = buf[1];
51 true
52 }
53 // Reset State
54 0xC8 => {
55 state = 0;
56 true
57 }
58 x => {
59 error!("Invalid Write Read {:x}", x);
60 false
61 }
62 } {
63 match dev.respond_to_read(&[state]).await {
64 Ok(read_status) => info!(
65 "This read is part of a write/read transaction. The response read status {}",
66 read_status
67 ),
68 Err(i2c::Error::Timeout) => {
69 info!("The device only performed a write and it not also do a read")
70 }
71 Err(e) => error!("error while responding {}", e),
72 }
73 }
74 }
75 Err(e) => error!("error while receiving {}", e),
76 },
77 Ok(i2c::SlaveCommand { address, .. }) => {
78 defmt::unreachable!(
79 "The slave matched address: {}, which it was not configured for",
80 address
81 );
82 }
83 Err(e) => error!("{}", e),
84 }
85 }
86}
87
88#[embassy_executor::task]
89async fn controller_task(mut con: i2c::I2c<'static, Async, i2c::Master>) {
90 info!("Controller start");
91
92 loop {
93 let mut resp_buff = [0u8; 1];
94 for i in 0..10 {
95 match con.write_read(DEV_ADDR, &[0xC2, i], &mut resp_buff).await {
96 Ok(_) => {
97 info!("write_read response: {}", resp_buff);
98 defmt::assert_eq!(resp_buff[0], i);
99 }
100 Err(e) => error!("Error writing {}", e),
101 }
102
103 Timer::after_millis(100).await;
104 }
105 match con.read(DEV_ADDR, &mut resp_buff).await {
106 Ok(_) => {
107 info!("read response: {}", resp_buff);
108 // assert that the state is the last index that was written
109 defmt::assert_eq!(resp_buff[0], 9);
110 }
111 Err(e) => error!("Error writing {}", e),
112 }
113 match con.write_read(DEV_ADDR, &[0xC8], &mut resp_buff).await {
114 Ok(_) => {
115 info!("write_read response: {}", resp_buff);
116 // assert that the state has been reset
117 defmt::assert_eq!(resp_buff[0], 0);
118 }
119 Err(e) => error!("Error writing {}", e),
120 }
121 Timer::after_millis(100).await;
122 }
123}
124
125#[embassy_executor::main]
126async fn main(spawner: Spawner) {
127 let p = embassy_stm32::init(Default::default());
128 info!("Hello World!");
129
130 let mut config = i2c::Config::default();
131 config.frequency = Hertz::khz(400);
132
133 let d_addr_config = i2c::SlaveAddrConfig {
134 addr: OwnAddresses::OA1(Address::SevenBit(DEV_ADDR)),
135 general_call: false,
136 };
137 let d_sda = p.PA8;
138 let d_scl = p.PA9;
139 let device =
140 i2c::I2c::new(p.I2C2, d_scl, d_sda, Irqs, p.DMA1_CH1, p.DMA1_CH2, config).into_slave_multimaster(d_addr_config);
141
142 spawner.spawn(unwrap!(device_task(device)));
143
144 let c_sda = p.PB8;
145 let c_scl = p.PB7;
146 let controller = i2c::I2c::new(p.I2C1, c_sda, c_scl, Irqs, p.DMA1_CH3, p.DMA1_CH4, config);
147
148 spawner.spawn(unwrap!(controller_task(controller)));
149}
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 6c965012c..5b4194927 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
14 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
15 info!("Hello World!"); 15 info!("Hello World!");
16 16
17 let ch1_pin = PwmPin::new_ch1(p.PC0, OutputType::PushPull); 17 let ch1_pin = PwmPin::new(p.PC0, OutputType::PushPull);
18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default()); 18 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
19 let mut ch1 = pwm.ch1(); 19 let mut ch1 = pwm.ch1();
20 ch1.enable(); 20 ch1.enable();
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 5631ff746..66680c027 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -3,19 +3,20 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h563zi to your chip name, if necessary. 9# Change stm32h563zi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16 17
17defmt = "0.3" 18defmt = "1.0.1"
18defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
19 20
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
@@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
24embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
25embedded-io-async = { version = "0.6.1" } 26embedded-io-async = { version = "0.6.1" }
26embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.8.0"
27panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
28heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
29rand_core = "0.6.3"
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
@@ -70,3 +70,8 @@ incremental = false
70lto = 'fat' 70lto = 'fat'
71opt-level = 3 # <- 71opt-level = 3 # <-
72overflow-checks = false # <- 72overflow-checks = false # <-
73
74[package.metadata.embassy]
75build = [
76 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32h5" }
77]
diff --git a/examples/stm32h5/src/bin/adc_dma.rs b/examples/stm32h5/src/bin/adc_dma.rs
new file mode 100644
index 000000000..fb9fcbc5c
--- /dev/null
+++ b/examples/stm32h5/src/bin/adc_dma.rs
@@ -0,0 +1,94 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::adc::{self, Adc, AdcChannel, RxDma, SampleTime};
7use embassy_stm32::peripherals::{ADC1, ADC2, GPDMA1_CH0, GPDMA1_CH1, PA0, PA1, PA2, PA3};
8use embassy_stm32::{Config, Peri};
9use embassy_time::Instant;
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(spawner: Spawner) {
14 let mut config = Config::default();
15 {
16 use embassy_stm32::rcc::*;
17 config.rcc.hsi = Some(HSIPrescaler::DIV1);
18 config.rcc.csi = true;
19 config.rcc.pll1 = Some(Pll {
20 source: PllSource::HSI,
21 prediv: PllPreDiv::DIV4,
22 mul: PllMul::MUL25,
23 divp: Some(PllDiv::DIV2),
24 divq: Some(PllDiv::DIV4), // SPI1 cksel defaults to pll1_q
25 divr: None,
26 });
27 config.rcc.pll2 = Some(Pll {
28 source: PllSource::HSI,
29 prediv: PllPreDiv::DIV4,
30 mul: PllMul::MUL25,
31 divp: None,
32 divq: None,
33 divr: Some(PllDiv::DIV4), // 100mhz
34 });
35 config.rcc.sys = Sysclk::PLL1_P; // 200 Mhz
36 config.rcc.ahb_pre = AHBPrescaler::DIV1; // 200 Mhz
37 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
38 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
39 config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
40 config.rcc.voltage_scale = VoltageScale::Scale1;
41 config.rcc.mux.adcdacsel = mux::Adcdacsel::PLL2_R;
42 }
43 let p = embassy_stm32::init(config);
44
45 spawner.spawn(unwrap!(adc1_task(p.ADC1, p.GPDMA1_CH0, p.PA0, p.PA2)));
46 spawner.spawn(unwrap!(adc2_task(p.ADC2, p.GPDMA1_CH1, p.PA1, p.PA3)));
47}
48
49#[embassy_executor::task]
50async fn adc1_task(
51 adc: Peri<'static, ADC1>,
52 dma: Peri<'static, GPDMA1_CH0>,
53 pin1: Peri<'static, PA0>,
54 pin2: Peri<'static, PA2>,
55) {
56 adc_task(adc, dma, pin1, pin2).await;
57}
58
59#[embassy_executor::task]
60async fn adc2_task(
61 adc: Peri<'static, ADC2>,
62 dma: Peri<'static, GPDMA1_CH1>,
63 pin1: Peri<'static, PA1>,
64 pin2: Peri<'static, PA3>,
65) {
66 adc_task(adc, dma, pin1, pin2).await;
67}
68
69async fn adc_task<'a, T: adc::Instance>(
70 adc: Peri<'a, T>,
71 mut dma: Peri<'a, impl RxDma<T>>,
72 pin1: impl AdcChannel<T>,
73 pin2: impl AdcChannel<T>,
74) {
75 let mut adc = Adc::new(adc);
76 let mut pin1 = pin1.degrade_adc();
77 let mut pin2 = pin2.degrade_adc();
78
79 let mut tic = Instant::now();
80 let mut buffer = [0u16; 512];
81 loop {
82 // This is not a true continuous read as there is downtime between each
83 // call to `Adc::read` where the ADC is sitting idle.
84 adc.read(
85 dma.reborrow(),
86 [(&mut pin1, SampleTime::CYCLES2_5), (&mut pin2, SampleTime::CYCLES2_5)].into_iter(),
87 &mut buffer,
88 )
89 .await;
90 let toc = Instant::now();
91 info!("\n adc1: {} dt = {}", buffer[0..16], (toc - tic).as_micros());
92 tic = toc;
93 }
94}
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index 4034b552c..a84fe358b 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -15,7 +15,6 @@ use embassy_stm32::time::Hertz;
15use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 15use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
16use embassy_time::Timer; 16use embassy_time::Timer;
17use embedded_io_async::Write; 17use embedded_io_async::Write;
18use rand_core::RngCore;
19use static_cell::StaticCell; 18use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
21 20
@@ -95,7 +94,7 @@ async fn main(spawner: Spawner) -> ! {
95 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 94 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
96 95
97 // Launch network task 96 // Launch network task
98 unwrap!(spawner.spawn(net_task(runner))); 97 spawner.spawn(unwrap!(net_task(runner)));
99 98
100 // Ensure DHCP configuration is up before trying connect 99 // Ensure DHCP configuration is up before trying connect
101 stack.wait_config_up().await; 100 stack.wait_config_up().await;
diff --git a/examples/stm32h5/src/bin/i2c.rs b/examples/stm32h5/src/bin/i2c.rs
index 31e83cbb5..870c57e0f 100644
--- a/examples/stm32h5/src/bin/i2c.rs
+++ b/examples/stm32h5/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::{Error, I2c}; 6use embassy_stm32::i2c::{Error, I2c};
7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, i2c, peripherals}; 7use embassy_stm32::{bind_interrupts, i2c, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
@@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) {
28 Irqs, 27 Irqs,
29 p.GPDMA1_CH4, 28 p.GPDMA1_CH4,
30 p.GPDMA1_CH5, 29 p.GPDMA1_CH5,
31 Hertz(100_000),
32 Default::default(), 30 Default::default(),
33 ); 31 );
34 32
diff --git a/examples/stm32h5/src/bin/sai.rs b/examples/stm32h5/src/bin/sai.rs
new file mode 100644
index 000000000..0e182f9cf
--- /dev/null
+++ b/examples/stm32h5/src/bin/sai.rs
@@ -0,0 +1,52 @@
1#![no_std]
2#![no_main]
3
4use defmt::info;
5use embassy_executor::Spawner;
6use embassy_stm32::{sai, Config};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 info!("Hello world.");
12
13 let mut config = Config::default();
14 {
15 use embassy_stm32::rcc::*;
16
17 config.rcc.pll2 = Some(Pll {
18 source: PllSource::HSI,
19 prediv: PllPreDiv::DIV16,
20 mul: PllMul::MUL32,
21 divp: Some(PllDiv::DIV16), // 8 MHz SAI clock
22 divq: None,
23 divr: None,
24 });
25
26 config.rcc.mux.sai1sel = mux::Saisel::PLL2_P;
27 }
28 let p = embassy_stm32::init(config);
29
30 let mut write_buffer = [0u16; 1024];
31 let (_, sai_b) = sai::split_subblocks(p.SAI1);
32
33 let mut sai_b = sai::Sai::new_asynchronous(
34 sai_b,
35 p.PF8,
36 p.PE3,
37 p.PF9,
38 p.GPDMA1_CH0,
39 &mut write_buffer,
40 Default::default(),
41 );
42
43 // Populate arbitrary data.
44 let mut data = [0u16; 256];
45 for (index, sample) in data.iter_mut().enumerate() {
46 *sample = index as u16;
47 }
48
49 loop {
50 sai_b.write(&data).await.unwrap();
51 }
52}
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs
index e650791c5..3c4f49f64 100644
--- a/examples/stm32h5/src/bin/stop.rs
+++ b/examples/stm32h5/src/bin/stop.rs
@@ -18,7 +18,7 @@ use {defmt_rtt as _, panic_probe as _};
18#[cortex_m_rt::entry] 18#[cortex_m_rt::entry]
19fn main() -> ! { 19fn main() -> ! {
20 Executor::take().run(|spawner| { 20 Executor::take().run(|spawner| {
21 unwrap!(spawner.spawn(async_main(spawner))); 21 spawner.spawn(unwrap!(async_main(spawner)));
22 }) 22 })
23} 23}
24 24
@@ -43,8 +43,8 @@ async fn async_main(spawner: Spawner) {
43 let rtc = RTC.init(rtc); 43 let rtc = RTC.init(rtc);
44 embassy_stm32::low_power::stop_with_rtc(rtc); 44 embassy_stm32::low_power::stop_with_rtc(rtc);
45 45
46 unwrap!(spawner.spawn(blinky(p.PB4.into()))); 46 spawner.spawn(unwrap!(blinky(p.PB4.into())));
47 unwrap!(spawner.spawn(timeout())); 47 spawner.spawn(unwrap!(timeout()));
48} 48}
49 49
50#[embassy_executor::task] 50#[embassy_executor::task]
diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs
index cc49c2fdb..264e7d582 100644
--- a/examples/stm32h5/src/bin/usart.rs
+++ b/examples/stm32h5/src/bin/usart.rs
@@ -34,6 +34,6 @@ fn main() -> ! {
34 let executor = EXECUTOR.init(Executor::new()); 34 let executor = EXECUTOR.init(Executor::new());
35 35
36 executor.run(|spawner| { 36 executor.run(|spawner| {
37 unwrap!(spawner.spawn(main_task())); 37 spawner.spawn(unwrap!(main_task()));
38 }) 38 })
39} 39}
diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs
index c644e84bd..ea48515d7 100644
--- a/examples/stm32h5/src/bin/usart_dma.rs
+++ b/examples/stm32h5/src/bin/usart_dma.rs
@@ -42,6 +42,6 @@ fn main() -> ! {
42 let executor = EXECUTOR.init(Executor::new()); 42 let executor = EXECUTOR.init(Executor::new());
43 43
44 executor.run(|spawner| { 44 executor.run(|spawner| {
45 unwrap!(spawner.spawn(main_task())); 45 spawner.spawn(unwrap!(main_task()));
46 }) 46 })
47} 47}
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs
index d26c5003c..f56c1c57d 100644
--- a/examples/stm32h5/src/bin/usart_split.rs
+++ b/examples/stm32h5/src/bin/usart_split.rs
@@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! {
27 27
28 let (mut tx, rx) = usart.split(); 28 let (mut tx, rx) = usart.split();
29 29
30 unwrap!(spawner.spawn(reader(rx))); 30 spawner.spawn(unwrap!(reader(rx)));
31 31
32 loop { 32 loop {
33 let buf = CHANNEL.receive().await; 33 let buf = CHANNEL.receive().await;
diff --git a/examples/stm32h5/src/bin/usb_uac_speaker.rs b/examples/stm32h5/src/bin/usb_uac_speaker.rs
index 5d007261c..86873cabd 100644
--- a/examples/stm32h5/src/bin/usb_uac_speaker.rs
+++ b/examples/stm32h5/src/bin/usb_uac_speaker.rs
@@ -366,9 +366,9 @@ async fn main(spawner: Spawner) {
366 } 366 }
367 367
368 // Launch USB audio tasks. 368 // Launch USB audio tasks.
369 unwrap!(spawner.spawn(usb_control_task(control_monitor))); 369 spawner.spawn(unwrap!(usb_control_task(control_monitor)));
370 unwrap!(spawner.spawn(usb_streaming_task(stream, sender))); 370 spawner.spawn(unwrap!(usb_streaming_task(stream, sender)));
371 unwrap!(spawner.spawn(usb_feedback_task(feedback))); 371 spawner.spawn(unwrap!(usb_feedback_task(feedback)));
372 unwrap!(spawner.spawn(usb_task(usb_device))); 372 spawner.spawn(unwrap!(usb_task(usb_device)));
373 unwrap!(spawner.spawn(audio_receiver_task(receiver))); 373 spawner.spawn(unwrap!(audio_receiver_task(receiver)));
374} 374}
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 2f98542bb..9a2080013 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -3,20 +3,21 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h743bi to your chip name, if necessary. 9# Change stm32h743bi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 12embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
12embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
13embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 16embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20 21
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
@@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.8.0"
27embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.6.1" }
28panic-probe = { version = "0.3", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
30rand_core = "0.6.3"
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.3.0"
@@ -73,3 +73,8 @@ incremental = false
73lto = 'fat' 73lto = 'fat'
74opt-level = 3 # <- 74opt-level = 3 # <-
75overflow-checks = false # <- 75overflow-checks = false # <-
76
77[package.metadata.embassy]
78build = [
79 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7" }
80]
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 170a5aa28..8f2e265d6 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -6,7 +6,6 @@ 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, McoPrescaler}; 8use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
9use embassy_stm32::time::khz;
10use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; 9use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
11use embassy_time::Timer; 10use embassy_time::Timer;
12use ov7725::*; 11use ov7725::*;
@@ -52,16 +51,7 @@ async fn main(_spawner: Spawner) {
52 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); 51 let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3);
53 52
54 let mut led = Output::new(p.PE3, Level::High, Speed::Low); 53 let mut led = Output::new(p.PE3, Level::High, Speed::Low);
55 let cam_i2c = I2c::new( 54 let cam_i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH1, p.DMA1_CH2, Default::default());
56 p.I2C1,
57 p.PB8,
58 p.PB9,
59 Irqs,
60 p.DMA1_CH1,
61 p.DMA1_CH2,
62 khz(100),
63 Default::default(),
64 );
65 55
66 let mut camera = Ov7725::new(cam_i2c, mco); 56 let mut camera = Ov7725::new(cam_i2c, mco);
67 57
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index 8314754bc..df37e9d78 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -53,8 +53,8 @@ async fn main(spawner: Spawner) {
53 // Obtain two independent channels (p.DAC1 can only be consumed once, though!) 53 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
54 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); 54 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
55 55
56 spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); 56 spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap());
57 spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); 57 spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap());
58} 58}
59 59
60#[embassy_executor::task] 60#[embassy_executor::task]
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index da7aa4af5..6c215362d 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng;
11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
12use embassy_time::Timer; 12use embassy_time::Timer;
13use embedded_io_async::Write; 13use embedded_io_async::Write;
14use rand_core::RngCore;
15use static_cell::StaticCell; 14use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
@@ -94,7 +93,7 @@ async fn main(spawner: Spawner) -> ! {
94 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 93 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
95 94
96 // Launch network task 95 // Launch network task
97 unwrap!(spawner.spawn(net_task(runner))); 96 spawner.spawn(unwrap!(net_task(runner)));
98 97
99 // Ensure DHCP configuration is up before trying connect 98 // Ensure DHCP configuration is up before trying connect
100 stack.wait_config_up().await; 99 stack.wait_config_up().await;
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 10485109a..10ac57fc9 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
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;
17use rand_core::RngCore;
18use static_cell::StaticCell; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
@@ -96,7 +95,7 @@ async fn main(spawner: Spawner) -> ! {
96 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 95 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
97 96
98 // Launch network task 97 // Launch network task
99 unwrap!(spawner.spawn(net_task(runner))); 98 spawner.spawn(unwrap!(net_task(runner)));
100 99
101 // Ensure DHCP configuration is up before trying connect 100 // Ensure DHCP configuration is up before trying connect
102 stack.wait_config_up().await; 101 stack.wait_config_up().await;
diff --git a/examples/stm32h7/src/bin/eth_client_mii.rs b/examples/stm32h7/src/bin/eth_client_mii.rs
index 849173615..c6a108471 100644
--- a/examples/stm32h7/src/bin/eth_client_mii.rs
+++ b/examples/stm32h7/src/bin/eth_client_mii.rs
@@ -14,7 +14,6 @@ use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
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;
17use rand_core::RngCore;
18use static_cell::StaticCell; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
@@ -102,7 +101,7 @@ async fn main(spawner: Spawner) -> ! {
102 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 101 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
103 102
104 // Launch network task 103 // Launch network task
105 unwrap!(spawner.spawn(net_task(runner))); 104 spawner.spawn(unwrap!(net_task(runner)));
106 105
107 // Ensure DHCP configuration is up before trying connect 106 // Ensure DHCP configuration is up before trying connect
108 stack.wait_config_up().await; 107 stack.wait_config_up().await;
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
index 3bf39eb44..c40af4935 100644
--- a/examples/stm32h7/src/bin/i2c.rs
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::{Error, I2c}; 6use embassy_stm32::i2c::{Error, I2c};
7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, i2c, peripherals}; 7use embassy_stm32::{bind_interrupts, i2c, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
@@ -21,16 +20,7 @@ async fn main(_spawner: Spawner) {
21 info!("Hello world!"); 20 info!("Hello world!");
22 let p = embassy_stm32::init(Default::default()); 21 let p = embassy_stm32::init(Default::default());
23 22
24 let mut i2c = I2c::new( 23 let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default());
25 p.I2C2,
26 p.PB10,
27 p.PB11,
28 Irqs,
29 p.DMA1_CH4,
30 p.DMA1_CH5,
31 Hertz(100_000),
32 Default::default(),
33 );
34 24
35 let mut data = [0u8; 1]; 25 let mut data = [0u8; 1];
36 26
diff --git a/examples/stm32h7/src/bin/i2c_shared.rs b/examples/stm32h7/src/bin/i2c_shared.rs
index 136b91eeb..9e45d845f 100644
--- a/examples/stm32h7/src/bin/i2c_shared.rs
+++ b/examples/stm32h7/src/bin/i2c_shared.rs
@@ -8,7 +8,6 @@ use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
8use embassy_executor::Spawner; 8use 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::time::Hertz;
12use embassy_stm32::{bind_interrupts, peripherals}; 11use embassy_stm32::{bind_interrupts, peripherals};
13use embassy_sync::blocking_mutex::raw::NoopRawMutex; 12use embassy_sync::blocking_mutex::raw::NoopRawMutex;
14use embassy_sync::blocking_mutex::NoopMutex; 13use embassy_sync::blocking_mutex::NoopMutex;
@@ -25,7 +24,7 @@ const SHTC3_WAKEUP: [u8; 2] = [0x35, 0x17];
25const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24]; 24const SHTC3_MEASURE_RH_FIRST: [u8; 2] = [0x5c, 0x24];
26const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98]; 25const SHTC3_SLEEP: [u8; 2] = [0xb0, 0x98];
27 26
28static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async>>>> = StaticCell::new(); 27static I2C_BUS: StaticCell<NoopMutex<RefCell<I2c<'static, Async, i2c::Master>>>> = StaticCell::new();
29 28
30bind_interrupts!(struct Irqs { 29bind_interrupts!(struct Irqs {
31 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>; 30 I2C1_EV => i2c::EventInterruptHandler<peripherals::I2C1>;
@@ -33,7 +32,7 @@ bind_interrupts!(struct Irqs {
33}); 32});
34 33
35#[embassy_executor::task] 34#[embassy_executor::task]
36async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 35async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
37 let mut data = [0u8; 2]; 36 let mut data = [0u8; 2];
38 37
39 loop { 38 loop {
@@ -50,7 +49,7 @@ async fn temperature(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Asyn
50} 49}
51 50
52#[embassy_executor::task] 51#[embassy_executor::task]
53async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>) { 52async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async, i2c::Master>>) {
54 let mut data = [0u8; 6]; 53 let mut data = [0u8; 6];
55 54
56 loop { 55 loop {
@@ -90,24 +89,15 @@ async fn humidity(mut i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Async>>
90async fn main(spawner: Spawner) { 89async fn main(spawner: Spawner) {
91 let p = embassy_stm32::init(Default::default()); 90 let p = embassy_stm32::init(Default::default());
92 91
93 let i2c = I2c::new( 92 let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default());
94 p.I2C1,
95 p.PB8,
96 p.PB9,
97 Irqs,
98 p.DMA1_CH4,
99 p.DMA1_CH5,
100 Hertz(100_000),
101 Default::default(),
102 );
103 let i2c_bus = NoopMutex::new(RefCell::new(i2c)); 93 let i2c_bus = NoopMutex::new(RefCell::new(i2c));
104 let i2c_bus = I2C_BUS.init(i2c_bus); 94 let i2c_bus = I2C_BUS.init(i2c_bus);
105 95
106 // Device 1, using embedded-hal-async compatible driver for TMP117 96 // Device 1, using embedded-hal-async compatible driver for TMP117
107 let i2c_dev1 = I2cDevice::new(i2c_bus); 97 let i2c_dev1 = I2cDevice::new(i2c_bus);
108 spawner.spawn(temperature(i2c_dev1)).unwrap(); 98 spawner.spawn(temperature(i2c_dev1).unwrap());
109 99
110 // Device 2, using embedded-hal-async compatible driver for SHTC3 100 // Device 2, using embedded-hal-async compatible driver for SHTC3
111 let i2c_dev2 = I2cDevice::new(i2c_bus); 101 let i2c_dev2 = I2cDevice::new(i2c_bus);
112 spawner.spawn(humidity(i2c_dev2)).unwrap(); 102 spawner.spawn(humidity(i2c_dev2).unwrap());
113} 103}
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 8de31ea5b..12abb8693 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -6,7 +6,7 @@ use 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::{khz, Hertz};
8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; 8use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
9use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; 9use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin};
10use embassy_stm32::{Config, Peri}; 10use embassy_stm32::{Config, Peri};
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -67,10 +67,10 @@ pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> {
67impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { 67impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> {
68 pub fn new( 68 pub fn new(
69 tim: Peri<'d, T>, 69 tim: Peri<'d, T>,
70 ch1: Peri<'d, impl Channel1Pin<T>>, 70 ch1: Peri<'d, impl TimerPin<T, Ch1>>,
71 ch2: Peri<'d, impl Channel2Pin<T>>, 71 ch2: Peri<'d, impl TimerPin<T, Ch2>>,
72 ch3: Peri<'d, impl Channel3Pin<T>>, 72 ch3: Peri<'d, impl TimerPin<T, Ch3>>,
73 ch4: Peri<'d, impl Channel4Pin<T>>, 73 ch4: Peri<'d, impl TimerPin<T, Ch4>>,
74 freq: Hertz, 74 freq: Hertz,
75 ) -> Self { 75 ) -> Self {
76 let af1 = ch1.af_num(); 76 let af1 = ch1.af_num();
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs
index b4620888f..2f2ffdea2 100644
--- a/examples/stm32h7/src/bin/multiprio.rs
+++ b/examples/stm32h7/src/bin/multiprio.rs
@@ -135,16 +135,16 @@ fn main() -> ! {
135 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
136 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
138 unwrap!(spawner.spawn(run_high())); 138 spawner.spawn(unwrap!(run_high()));
139 139
140 // Medium-priority executor: UART5, priority level 7 140 // Medium-priority executor: UART5, priority level 7
141 interrupt::UART5.set_priority(Priority::P7); 141 interrupt::UART5.set_priority(Priority::P7);
142 let spawner = EXECUTOR_MED.start(interrupt::UART5); 142 let spawner = EXECUTOR_MED.start(interrupt::UART5);
143 unwrap!(spawner.spawn(run_med())); 143 spawner.spawn(unwrap!(run_med()));
144 144
145 // Low priority executor: runs in thread mode, using WFE/SEV 145 // Low priority executor: runs in thread mode, using WFE/SEV
146 let executor = EXECUTOR_LOW.init(Executor::new()); 146 let executor = EXECUTOR_LOW.init(Executor::new());
147 executor.run(|spawner| { 147 executor.run(|spawner| {
148 unwrap!(spawner.spawn(run_low())); 148 spawner.spawn(unwrap!(run_low()));
149 }); 149 });
150} 150}
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index a1c53fc3f..73b43be69 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
36 let p = embassy_stm32::init(config); 36 let p = embassy_stm32::init(config);
37 info!("Hello World!"); 37 info!("Hello World!");
38 38
39 let ch1_pin = PwmPin::new_ch1(p.PA6, OutputType::PushPull); 39 let ch1_pin = PwmPin::new(p.PA6, OutputType::PushPull);
40 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default()); 40 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default());
41 let mut ch1 = pwm.ch1(); 41 let mut ch1 = pwm.ch1();
42 ch1.enable(); 42 ch1.enable();
diff --git a/examples/stm32h7/src/bin/sai.rs b/examples/stm32h7/src/bin/sai.rs
index 01937593a..847b70c85 100644
--- a/examples/stm32h7/src/bin/sai.rs
+++ b/examples/stm32h7/src/bin/sai.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
63 tx_config.tx_rx = TxRx::Transmitter; 63 tx_config.tx_rx = TxRx::Transmitter;
64 tx_config.sync_output = true; 64 tx_config.sync_output = true;
65 tx_config.clock_strobe = ClockStrobe::Falling; 65 tx_config.clock_strobe = ClockStrobe::Falling;
66 tx_config.master_clock_divider = mclk_div; 66 tx_config.master_clock_divider = Some(mclk_div);
67 tx_config.stereo_mono = StereoMono::Stereo; 67 tx_config.stereo_mono = StereoMono::Stereo;
68 tx_config.data_size = DataSize::Data24; 68 tx_config.data_size = DataSize::Data24;
69 tx_config.bit_order = BitOrder::MsbFirst; 69 tx_config.bit_order = BitOrder::MsbFirst;
@@ -119,71 +119,7 @@ async fn main(_spawner: Spawner) {
119 } 119 }
120} 120}
121 121
122const fn mclk_div_from_u8(v: u8) -> MasterClockDivider { 122fn mclk_div_from_u8(v: u8) -> MasterClockDivider {
123 match v { 123 assert!((1..=63).contains(&v));
124 1 => MasterClockDivider::Div1, 124 MasterClockDivider::from_bits(v)
125 2 => MasterClockDivider::Div2,
126 3 => MasterClockDivider::Div3,
127 4 => MasterClockDivider::Div4,
128 5 => MasterClockDivider::Div5,
129 6 => MasterClockDivider::Div6,
130 7 => MasterClockDivider::Div7,
131 8 => MasterClockDivider::Div8,
132 9 => MasterClockDivider::Div9,
133 10 => MasterClockDivider::Div10,
134 11 => MasterClockDivider::Div11,
135 12 => MasterClockDivider::Div12,
136 13 => MasterClockDivider::Div13,
137 14 => MasterClockDivider::Div14,
138 15 => MasterClockDivider::Div15,
139 16 => MasterClockDivider::Div16,
140 17 => MasterClockDivider::Div17,
141 18 => MasterClockDivider::Div18,
142 19 => MasterClockDivider::Div19,
143 20 => MasterClockDivider::Div20,
144 21 => MasterClockDivider::Div21,
145 22 => MasterClockDivider::Div22,
146 23 => MasterClockDivider::Div23,
147 24 => MasterClockDivider::Div24,
148 25 => MasterClockDivider::Div25,
149 26 => MasterClockDivider::Div26,
150 27 => MasterClockDivider::Div27,
151 28 => MasterClockDivider::Div28,
152 29 => MasterClockDivider::Div29,
153 30 => MasterClockDivider::Div30,
154 31 => MasterClockDivider::Div31,
155 32 => MasterClockDivider::Div32,
156 33 => MasterClockDivider::Div33,
157 34 => MasterClockDivider::Div34,
158 35 => MasterClockDivider::Div35,
159 36 => MasterClockDivider::Div36,
160 37 => MasterClockDivider::Div37,
161 38 => MasterClockDivider::Div38,
162 39 => MasterClockDivider::Div39,
163 40 => MasterClockDivider::Div40,
164 41 => MasterClockDivider::Div41,
165 42 => MasterClockDivider::Div42,
166 43 => MasterClockDivider::Div43,
167 44 => MasterClockDivider::Div44,
168 45 => MasterClockDivider::Div45,
169 46 => MasterClockDivider::Div46,
170 47 => MasterClockDivider::Div47,
171 48 => MasterClockDivider::Div48,
172 49 => MasterClockDivider::Div49,
173 50 => MasterClockDivider::Div50,
174 51 => MasterClockDivider::Div51,
175 52 => MasterClockDivider::Div52,
176 53 => MasterClockDivider::Div53,
177 54 => MasterClockDivider::Div54,
178 55 => MasterClockDivider::Div55,
179 56 => MasterClockDivider::Div56,
180 57 => MasterClockDivider::Div57,
181 58 => MasterClockDivider::Div58,
182 59 => MasterClockDivider::Div59,
183 60 => MasterClockDivider::Div60,
184 61 => MasterClockDivider::Div61,
185 62 => MasterClockDivider::Div62,
186 63 => MasterClockDivider::Div63,
187 _ => panic!(),
188 }
189} 125}
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs
index b73360f32..97309798e 100644
--- a/examples/stm32h7/src/bin/signal.rs
+++ b/examples/stm32h7/src/bin/signal.rs
@@ -26,7 +26,7 @@ async fn my_sending_task() {
26#[embassy_executor::main] 26#[embassy_executor::main]
27async fn main(spawner: Spawner) { 27async fn main(spawner: Spawner) {
28 let _p = embassy_stm32::init(Default::default()); 28 let _p = embassy_stm32::init(Default::default());
29 unwrap!(spawner.spawn(my_sending_task())); 29 spawner.spawn(unwrap!(my_sending_task()));
30 30
31 loop { 31 loop {
32 let received_counter = SIGNAL.wait().await; 32 let received_counter = SIGNAL.wait().await;
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index ad4a8aaf7..dce30a4a7 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -66,6 +66,6 @@ fn main() -> ! {
66 let executor = EXECUTOR.init(Executor::new()); 66 let executor = EXECUTOR.init(Executor::new());
67 67
68 executor.run(|spawner| { 68 executor.run(|spawner| {
69 unwrap!(spawner.spawn(main_task(spi))); 69 spawner.spawn(unwrap!(main_task(spi)));
70 }) 70 })
71} 71}
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs
index 5a7dff572..828f687b8 100644
--- a/examples/stm32h7/src/bin/spi_bdma.rs
+++ b/examples/stm32h7/src/bin/spi_bdma.rs
@@ -80,6 +80,6 @@ fn main() -> ! {
80 let executor = EXECUTOR.init(Executor::new()); 80 let executor = EXECUTOR.init(Executor::new());
81 81
82 executor.run(|spawner| { 82 executor.run(|spawner| {
83 unwrap!(spawner.spawn(main_task(spi))); 83 spawner.spawn(unwrap!(main_task(spi)));
84 }) 84 })
85} 85}
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 731c7fef5..2197fabce 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -63,6 +63,6 @@ fn main() -> ! {
63 let executor = EXECUTOR.init(Executor::new()); 63 let executor = EXECUTOR.init(Executor::new());
64 64
65 executor.run(|spawner| { 65 executor.run(|spawner| {
66 unwrap!(spawner.spawn(main_task(spi))); 66 spawner.spawn(unwrap!(main_task(spi)));
67 }) 67 })
68} 68}
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index cc49c2fdb..264e7d582 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -34,6 +34,6 @@ fn main() -> ! {
34 let executor = EXECUTOR.init(Executor::new()); 34 let executor = EXECUTOR.init(Executor::new());
35 35
36 executor.run(|spawner| { 36 executor.run(|spawner| {
37 unwrap!(spawner.spawn(main_task())); 37 spawner.spawn(unwrap!(main_task()));
38 }) 38 })
39} 39}
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index 6f340d40a..23d7f193a 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -42,6 +42,6 @@ fn main() -> ! {
42 let executor = EXECUTOR.init(Executor::new()); 42 let executor = EXECUTOR.init(Executor::new());
43 43
44 executor.run(|spawner| { 44 executor.run(|spawner| {
45 unwrap!(spawner.spawn(main_task())); 45 spawner.spawn(unwrap!(main_task()));
46 }) 46 })
47} 47}
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index 2bb58be5e..464ce8d72 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! {
27 27
28 let (mut tx, rx) = usart.split(); 28 let (mut tx, rx) = usart.split();
29 29
30 unwrap!(spawner.spawn(reader(rx))); 30 spawner.spawn(unwrap!(reader(rx)));
31 31
32 loop { 32 loop {
33 let buf = CHANNEL.receive().await; 33 let buf = CHANNEL.receive().await;
diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml
index 749fd78ae..7e4ccc528 100644
--- a/examples/stm32h723/Cargo.toml
+++ b/examples/stm32h723/Cargo.toml
@@ -3,17 +3,18 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h723zg to your chip name, if necessary. 9# Change stm32h723zg to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h723zg", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17 18
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
@@ -22,9 +23,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
22embedded-hal-async = { version = "1.0" } 23embedded-hal-async = { version = "1.0" }
23embedded-nal-async = "0.8.0" 24embedded-nal-async = "0.8.0"
24embedded-io-async = { version = "0.6.1" } 25embedded-io-async = { version = "0.6.1" }
25panic-probe = { version = "0.3", features = ["print-defmt"] } 26panic-probe = { version = "1.0.0", features = ["print-defmt"] }
26heapless = { version = "0.8", default-features = false } 27heapless = { version = "0.8", default-features = false }
27rand_core = "0.6.3"
28critical-section = "1.1" 28critical-section = "1.1"
29static_cell = "2" 29static_cell = "2"
30chrono = { version = "^0.4", default-features = false } 30chrono = { version = "^0.4", default-features = false }
@@ -67,3 +67,8 @@ incremental = false
67lto = 'fat' 67lto = 'fat'
68opt-level = 3 # <- 68opt-level = 3 # <-
69overflow-checks = false # <- 69overflow-checks = false # <-
70
71[package.metadata.embassy]
72build = [
73 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h723" }
74]
diff --git a/examples/stm32h723/src/bin/spdifrx.rs b/examples/stm32h723/src/bin/spdifrx.rs
index a04d7cb34..b75a03ae8 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::{self, select, Either}; 10use embassy_futures::select::{select, Either};
11use embassy_stm32::spdifrx::{self, Spdifrx}; 11use embassy_stm32::spdifrx::{self, Spdifrx};
12use embassy_stm32::{bind_interrupts, peripherals, sai}; 12use embassy_stm32::{bind_interrupts, peripherals, sai, Peri};
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 _};
@@ -25,10 +25,10 @@ const DMA_BUFFER_LENGTH: usize = HALF_DMA_BUFFER_LENGTH * 2; // 2 half-blocks
25 25
26// DMA buffers must be in special regions. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions 26// DMA buffers must be in special regions. Refer https://embassy.dev/book/#_stm32_bdma_only_working_out_of_some_ram_regions
27#[unsafe(link_section = ".sram1")] 27#[unsafe(link_section = ".sram1")]
28static mut SPDIFRX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); 28static SPDIFRX_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit();
29 29
30#[unsafe(link_section = ".sram4")] 30#[unsafe(link_section = ".sram4")]
31static mut SAI_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit(); 31static SAI_BUFFER: GroundedArrayCell<u32, DMA_BUFFER_LENGTH> = GroundedArrayCell::uninit();
32 32
33#[embassy_executor::main] 33#[embassy_executor::main]
34async fn main(_spawner: Spawner) { 34async fn main(_spawner: Spawner) {
@@ -144,9 +144,9 @@ async fn main(_spawner: Spawner) {
144/// 144///
145/// Used (again) after dropping the SPDIFRX instance, in case of errors (e.g. source disconnect). 145/// Used (again) after dropping the SPDIFRX instance, in case of errors (e.g. source disconnect).
146fn new_spdif_receiver<'d>( 146fn new_spdif_receiver<'d>(
147 spdifrx: &'d mut peripherals::SPDIFRX1, 147 spdifrx: Peri<'d, peripherals::SPDIFRX1>,
148 input_pin: &'d mut peripherals::PD7, 148 input_pin: Peri<'d, peripherals::PD7>,
149 dma: &'d mut peripherals::DMA2_CH7, 149 dma: Peri<'d, peripherals::DMA2_CH7>,
150 buf: &'d mut [u32], 150 buf: &'d mut [u32],
151) -> Spdifrx<'d, peripherals::SPDIFRX1> { 151) -> Spdifrx<'d, peripherals::SPDIFRX1> {
152 Spdifrx::new(spdifrx, Irqs, spdifrx::Config::default(), input_pin, dma, buf) 152 Spdifrx::new(spdifrx, Irqs, spdifrx::Config::default(), input_pin, dma, buf)
@@ -156,11 +156,11 @@ fn new_spdif_receiver<'d>(
156/// 156///
157/// Used (again) after dropping the SAI4 instance, in case of errors (e.g. buffer overrun). 157/// Used (again) after dropping the SAI4 instance, in case of errors (e.g. buffer overrun).
158fn new_sai_transmitter<'d>( 158fn new_sai_transmitter<'d>(
159 sai: &'d mut peripherals::SAI4, 159 sai: Peri<'d, peripherals::SAI4>,
160 sck: &'d mut peripherals::PD13, 160 sck: Peri<'d, peripherals::PD13>,
161 sd: &'d mut peripherals::PC1, 161 sd: Peri<'d, peripherals::PC1>,
162 fs: &'d mut peripherals::PD12, 162 fs: Peri<'d, peripherals::PD12>,
163 dma: &'d mut peripherals::BDMA_CH0, 163 dma: Peri<'d, peripherals::BDMA_CH0>,
164 buf: &'d mut [u32], 164 buf: &'d mut [u32],
165) -> Sai<'d, peripherals::SAI4, u32> { 165) -> Sai<'d, peripherals::SAI4, u32> {
166 let mut sai_config = hal::sai::Config::default(); 166 let mut sai_config = hal::sai::Config::default();
@@ -168,7 +168,7 @@ fn new_sai_transmitter<'d>(
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 u8;
171 sai_config.master_clock_divider = hal::sai::MasterClockDivider::MasterClockDisabled; 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);
174 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config) 174 Sai::new_asynchronous(sub_block_tx, sck, sd, fs, dma, buf, sai_config)
diff --git a/examples/stm32h735/Cargo.toml b/examples/stm32h735/Cargo.toml
index 4d31dedf1..22b7ad96a 100644
--- a/examples/stm32h735/Cargo.toml
+++ b/examples/stm32h735/Cargo.toml
@@ -3,21 +3,22 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h735ig", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 11embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17 18
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21heapless = { version = "0.8", default-features = false } 22heapless = { version = "0.8", default-features = false }
22embedded-graphics = { version = "0.8.1" } 23embedded-graphics = { version = "0.8.1" }
23tinybmp = { version = "0.5" } 24tinybmp = { version = "0.5" }
@@ -59,3 +60,8 @@ incremental = false
59lto = 'fat' 60lto = 'fat'
60opt-level = 3 # <- 61opt-level = 3 # <-
61overflow-checks = false # <- 62overflow-checks = false # <-
63
64[package.metadata.embassy]
65build = [
66 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h735" }
67]
diff --git a/examples/stm32h735/src/bin/ltdc.rs b/examples/stm32h735/src/bin/ltdc.rs
index a36fdef2c..8a99f745d 100644
--- a/examples/stm32h735/src/bin/ltdc.rs
+++ b/examples/stm32h735/src/bin/ltdc.rs
@@ -47,7 +47,7 @@ async fn main(spawner: Spawner) {
47 47
48 // blink the led on another task 48 // blink the led on another task
49 let led = Output::new(p.PC3, Level::High, Speed::Low); 49 let led = Output::new(p.PC3, Level::High, Speed::Low);
50 unwrap!(spawner.spawn(led_task(led))); 50 spawner.spawn(unwrap!(led_task(led)));
51 51
52 // numbers from STMicroelectronics/STM32CubeH7 STM32H735G-DK C-based example 52 // numbers from STMicroelectronics/STM32CubeH7 STM32H735G-DK C-based example
53 const RK043FN48H_HSYNC: u16 = 41; // Horizontal synchronization 53 const RK043FN48H_HSYNC: u16 = 41; // Horizontal synchronization
diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml
index e2e0094b8..c76340b5f 100644
--- a/examples/stm32h742/Cargo.toml
+++ b/examples/stm32h742/Cargo.toml
@@ -1,12 +1,12 @@
1[package] 1[package]
2edition = "2021" 2edition = "2021"
3name = "embassy-stm32f7-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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32f777zi to your chip name, if necessary. 9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [
10 "defmt", 10 "defmt",
11 "stm32h742vi", 11 "stm32h742vi",
12 "memory-x", 12 "memory-x",
@@ -14,33 +14,33 @@ embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [
14 "time-driver-any", 14 "time-driver-any",
15 "exti", 15 "exti",
16] } 16] }
17embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ 17embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [
18 "defmt", 18 "defmt",
19] } 19] }
20embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ 20embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [
21 "arch-cortex-m", 21 "arch-cortex-m",
22 "executor-thread", 22 "executor-thread",
23 "defmt", 23 "defmt",
24] } 24] }
25embassy-time = { version = "0.4.0", path = "../../embassy-time", features = [ 25embassy-time = { version = "0.5.0", path = "../../embassy-time", features = [
26 "defmt", 26 "defmt",
27 "defmt-timestamp-uptime", 27 "defmt-timestamp-uptime",
28 "tick-hz-32_768", 28 "tick-hz-32_768",
29] } 29] }
30embassy-net = { version = "0.7.0", path = "../../embassy-net", features = [ 30embassy-net = { version = "0.7.1", path = "../../embassy-net", features = [
31 "defmt", 31 "defmt",
32 "tcp", 32 "tcp",
33 "dhcpv4", 33 "dhcpv4",
34 "medium-ethernet", 34 "medium-ethernet",
35] } 35] }
36embedded-io-async = { version = "0.6.1" } 36embedded-io-async = { version = "0.6.1" }
37embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = [ 37embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = [
38 "defmt", 38 "defmt",
39] } 39] }
40embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 40embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
41 41
42defmt = "0.3" 42defmt = "1.0.1"
43defmt-rtt = "0.4" 43defmt-rtt = "1.0.0"
44 44
45cortex-m = { version = "0.7.6", features = [ 45cortex-m = { version = "0.7.6", features = [
46 "inline-asm", 46 "inline-asm",
@@ -48,10 +48,9 @@ cortex-m = { version = "0.7.6", features = [
48] } 48] }
49cortex-m-rt = "0.7.0" 49cortex-m-rt = "0.7.0"
50embedded-hal = "0.2.6" 50embedded-hal = "0.2.6"
51panic-probe = { version = "0.3", features = ["print-defmt"] } 51panic-probe = { version = "1.0.0", features = ["print-defmt"] }
52heapless = { version = "0.8", default-features = false } 52heapless = { version = "0.8", default-features = false }
53nb = "1.0.0" 53nb = "1.0.0"
54rand_core = "0.6.3"
55critical-section = "1.1" 54critical-section = "1.1"
56embedded-storage = "0.3.1" 55embedded-storage = "0.3.1"
57static_cell = "2" 56static_cell = "2"
@@ -64,3 +63,8 @@ aes-gcm = { version = "0.10.3", default-features = false, features = [
64 63
65[profile.release] 64[profile.release]
66debug = 2 65debug = 2
66
67[package.metadata.embassy]
68build = [
69 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h742" }
70]
diff --git a/examples/stm32h742/src/bin/qspi.rs b/examples/stm32h742/src/bin/qspi.rs
index aee07f3f2..9e79d7089 100644
--- a/examples/stm32h742/src/bin/qspi.rs
+++ b/examples/stm32h742/src/bin/qspi.rs
@@ -266,13 +266,14 @@ async fn main(_spawner: Spawner) -> ! {
266 let p = embassy_stm32::init(config); 266 let p = embassy_stm32::init(config);
267 info!("Embassy initialized"); 267 info!("Embassy initialized");
268 268
269 let config = QspiCfg { 269 let mut config = QspiCfg::default();
270 memory_size: MemorySize::_8MiB, 270 config.memory_size = MemorySize::_8MiB;
271 address_size: AddressSize::_24bit, 271 config.address_size = AddressSize::_24bit;
272 prescaler: 16, 272 config.prescaler = 16;
273 cs_high_time: ChipSelectHighTime::_1Cycle, 273 config.cs_high_time = ChipSelectHighTime::_1Cycle;
274 fifo_threshold: FIFOThresholdLevel::_16Bytes, 274 config.fifo_threshold = FIFOThresholdLevel::_16Bytes;
275 }; 275 config.sample_shifting = SampleShifting::None;
276
276 let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config); 277 let driver = Qspi::new_blocking_bank1(p.QUADSPI, p.PD11, p.PD12, p.PE2, p.PD13, p.PB2, p.PB10, config);
277 let mut flash = FlashMemory::new(driver); 278 let mut flash = FlashMemory::new(driver);
278 let flash_id = flash.read_id(); 279 let flash_id = flash.read_id();
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index 7c17bc766..c73f9df79 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -3,20 +3,21 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h755zi-cm4 to your chip name, if necessary. 9# Change stm32h755zi-cm4 to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm4", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 12embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
12embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
13embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 16embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20 21
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
@@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.8.0"
27embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.6.1" }
28panic-probe = { version = "0.3", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
30rand_core = "0.6.3"
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.3.0"
@@ -37,13 +37,6 @@ chrono = { version = "^0.4", default-features = false }
37grounded = "0.2.0" 37grounded = "0.2.0"
38 38
39# cargo build/run 39# cargo build/run
40[profile.dev]
41codegen-units = 1
42debug = 2
43debug-assertions = true # <-
44incremental = false
45opt-level = 3 # <-
46overflow-checks = true # <-
47 40
48# cargo test 41# cargo test
49[profile.test] 42[profile.test]
@@ -56,11 +49,10 @@ overflow-checks = true # <-
56 49
57# cargo build/run --release 50# cargo build/run --release
58[profile.release] 51[profile.release]
59codegen-units = 1 52codegen-units = 16
60debug = 2 53debug = 2
61debug-assertions = false # <- 54debug-assertions = false # <-
62incremental = false 55incremental = false
63lto = 'fat'
64opt-level = 3 # <- 56opt-level = 3 # <-
65overflow-checks = false # <- 57overflow-checks = false # <-
66 58
@@ -73,3 +65,8 @@ incremental = false
73lto = 'fat' 65lto = 'fat'
74opt-level = 3 # <- 66opt-level = 3 # <-
75overflow-checks = false # <- 67overflow-checks = false # <-
68
69[package.metadata.embassy]
70build = [
71 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm4" }
72]
diff --git a/examples/stm32h755cm4/src/bin/intercore.rs b/examples/stm32h755cm4/src/bin/intercore.rs
new file mode 100644
index 000000000..f584e31e9
--- /dev/null
+++ b/examples/stm32h755cm4/src/bin/intercore.rs
@@ -0,0 +1,182 @@
1#![no_std]
2#![no_main]
3
4//! STM32H7 Secondary Core (CM4) Intercore Communication Example
5//!
6//! This example demonstrates reliable communication between the Cortex-M7 and
7//! Cortex-M4 cores. This secondary core monitors shared memory for LED state
8//! changes and updates the physical LEDs accordingly.
9//!
10//! The CM4 core handles:
11//! - Responding to state changes from CM7
12//! - Controlling the physical green and yellow LEDs
13//! - Providing visual feedback via a heartbeat on the red LED
14//!
15//! Usage:
16//! 1. Flash this CM4 (secondary) core binary first
17//! 2. Then flash the CM7 (primary) core binary
18//! 3. The red LED should blink continuously as a heartbeat
19//! 4. Green and yellow LEDs should toggle according to CM7 core signals
20
21/// Module providing shared memory constructs for intercore communication
22mod shared {
23 use core::sync::atomic::{AtomicU32, Ordering};
24
25 /// State shared between CM7 and CM4 cores for LED control
26 #[repr(C, align(4))]
27 pub struct SharedLedState {
28 pub magic: AtomicU32,
29 pub counter: AtomicU32,
30 pub led_states: AtomicU32,
31 }
32
33 // Bit positions in led_states
34 pub const GREEN_LED_BIT: u32 = 0;
35 pub const YELLOW_LED_BIT: u32 = 1;
36
37 impl SharedLedState {
38 pub const fn new() -> Self {
39 Self {
40 magic: AtomicU32::new(0xDEADBEEF),
41 counter: AtomicU32::new(0),
42 led_states: AtomicU32::new(0),
43 }
44 }
45
46 /// Set LED state by manipulating the appropriate bit in the led_states field
47 #[inline(never)]
48 #[allow(dead_code)]
49 pub fn set_led(&self, is_green: bool, state: bool) {
50 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
51 let current = self.led_states.load(Ordering::SeqCst);
52
53 let new_value = if state {
54 current | (1 << bit) // Set bit
55 } else {
56 current & !(1 << bit) // Clear bit
57 };
58 self.led_states.store(new_value, Ordering::SeqCst);
59 }
60
61 /// Get current LED state
62 #[inline(never)]
63 pub fn get_led(&self, is_green: bool) -> bool {
64 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
65
66 let value = self.led_states.load(Ordering::SeqCst);
67 (value & (1 << bit)) != 0
68 }
69
70 /// Increment counter and return new value
71 #[inline(never)]
72 #[allow(dead_code)]
73 pub fn increment_counter(&self) -> u32 {
74 let current = self.counter.load(Ordering::SeqCst);
75 let new_value = current.wrapping_add(1);
76 self.counter.store(new_value, Ordering::SeqCst);
77 new_value
78 }
79
80 /// Get current counter value
81 #[inline(never)]
82 pub fn get_counter(&self) -> u32 {
83 let value = self.counter.load(Ordering::SeqCst);
84 value
85 }
86 }
87
88 #[link_section = ".ram_d3"]
89 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
90}
91
92use core::mem::MaybeUninit;
93
94use defmt::*;
95use embassy_executor::Spawner;
96use embassy_stm32::gpio::{Level, Output, Speed};
97use embassy_stm32::SharedData;
98use embassy_time::Timer;
99use shared::SHARED_LED_STATE;
100use {defmt_rtt as _, panic_probe as _};
101
102#[link_section = ".ram_d3"]
103static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
104
105/// Task that continuously blinks the red LED as a heartbeat indicator
106#[embassy_executor::task]
107async fn blink_heartbeat(mut led: Output<'static>) {
108 loop {
109 led.toggle();
110 info!("CM4 heartbeat");
111 Timer::after_millis(500).await;
112 }
113}
114
115#[embassy_executor::main]
116async fn main(spawner: Spawner) -> ! {
117 // Initialize the secondary core
118 let p = embassy_stm32::init_secondary(&SHARED_DATA);
119 info!("CM4 core initialized!");
120
121 // Verify shared memory is accessible
122 let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst);
123 info!("CM4: Magic value = 0x{:X}", magic);
124
125 // Set up LEDs
126 let mut green_led = Output::new(p.PB0, Level::Low, Speed::Low); // LD1
127 let mut yellow_led = Output::new(p.PE1, Level::Low, Speed::Low); // LD2
128 let red_led = Output::new(p.PB14, Level::Low, Speed::Low); // LD3 (heartbeat)
129
130 // Start heartbeat task
131 spawner.spawn(unwrap!(blink_heartbeat(red_led)));
132
133 // Track previous values to detect changes
134 let mut prev_green = false;
135 let mut prev_yellow = false;
136 let mut prev_counter = 0;
137
138 info!("CM4: Starting main loop");
139 loop {
140 // Read current values from shared memory
141 let green_state = SHARED_LED_STATE.get_led(true);
142 let yellow_state = SHARED_LED_STATE.get_led(false);
143 let counter = SHARED_LED_STATE.get_counter();
144
145 // Detect changes
146 let green_changed = green_state != prev_green;
147 let yellow_changed = yellow_state != prev_yellow;
148 let counter_changed = counter != prev_counter;
149
150 // Update LEDs and logs when values change
151 if green_changed || yellow_changed || counter_changed {
152 if counter_changed {
153 info!("CM4: Counter = {}", counter);
154 prev_counter = counter;
155 }
156
157 if green_changed {
158 if green_state {
159 green_led.set_high();
160 info!("CM4: Green LED ON");
161 } else {
162 green_led.set_low();
163 info!("CM4: Green LED OFF");
164 }
165 prev_green = green_state;
166 }
167
168 if yellow_changed {
169 if yellow_state {
170 yellow_led.set_high();
171 info!("CM4: Yellow LED ON");
172 } else {
173 yellow_led.set_low();
174 info!("CM4: Yellow LED OFF");
175 }
176 prev_yellow = yellow_state;
177 }
178 }
179
180 Timer::after_millis(10).await;
181 }
182}
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml
index 3186929a8..c34d4e45c 100644
--- a/examples/stm32h755cm7/Cargo.toml
+++ b/examples/stm32h755cm7/Cargo.toml
@@ -3,20 +3,21 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h743bi to your chip name, if necessary. 9# Change stm32h743bi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h755zi-cm7", "time-driver-tim3", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 12embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
12embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
13embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
15embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 16embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20 21
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
@@ -25,9 +26,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.8.0"
27embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.6.1" }
28panic-probe = { version = "0.3", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
30rand_core = "0.6.3"
31critical-section = "1.1" 31critical-section = "1.1"
32micromath = "2.0.0" 32micromath = "2.0.0"
33stm32-fmc = "0.3.0" 33stm32-fmc = "0.3.0"
@@ -36,15 +36,6 @@ static_cell = "2"
36chrono = { version = "^0.4", default-features = false } 36chrono = { version = "^0.4", default-features = false }
37grounded = "0.2.0" 37grounded = "0.2.0"
38 38
39# cargo build/run
40[profile.dev]
41codegen-units = 1
42debug = 2
43debug-assertions = true # <-
44incremental = false
45opt-level = 3 # <-
46overflow-checks = true # <-
47
48# cargo test 39# cargo test
49[profile.test] 40[profile.test]
50codegen-units = 1 41codegen-units = 1
@@ -56,11 +47,10 @@ overflow-checks = true # <-
56 47
57# cargo build/run --release 48# cargo build/run --release
58[profile.release] 49[profile.release]
59codegen-units = 1 50codegen-units = 16
60debug = 2 51debug = 2
61debug-assertions = false # <- 52debug-assertions = false # <-
62incremental = false 53incremental = false
63lto = 'fat'
64opt-level = 3 # <- 54opt-level = 3 # <-
65overflow-checks = false # <- 55overflow-checks = false # <-
66 56
@@ -73,3 +63,8 @@ incremental = false
73lto = 'fat' 63lto = 'fat'
74opt-level = 3 # <- 64opt-level = 3 # <-
75overflow-checks = false # <- 65overflow-checks = false # <-
66
67[package.metadata.embassy]
68build = [
69 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h755cm7" }
70]
diff --git a/examples/stm32h755cm7/src/bin/intercore.rs b/examples/stm32h755cm7/src/bin/intercore.rs
new file mode 100644
index 000000000..a4e1b5ff4
--- /dev/null
+++ b/examples/stm32h755cm7/src/bin/intercore.rs
@@ -0,0 +1,228 @@
1#![no_std]
2#![no_main]
3
4//! STM32H7 Primary Core (CM7) Intercore Communication Example
5//!
6//! This example demonstrates reliable communication between the Cortex-M7 and
7//! Cortex-M4 cores using a shared memory region configured as non-cacheable
8//! via MPU settings.
9//!
10//! The CM7 core handles:
11//! - MPU configuration to make shared memory non-cacheable
12//! - Clock initialization
13//! - Toggling LED states in shared memory
14//!
15//! Usage:
16//! 1. Flash the CM4 (secondary) core binary first
17//! 2. Then flash this CM7 (primary) core binary
18//! 3. The system will start with CM7 toggling LED states and CM4 responding by
19//! physically toggling the LEDs
20
21use core::mem::MaybeUninit;
22
23use cortex_m::asm;
24use cortex_m::peripheral::MPU;
25use defmt::*;
26use embassy_executor::Spawner;
27use embassy_stm32::{Config, SharedData};
28use embassy_time::Timer;
29use shared::{SHARED_LED_STATE, SRAM4_BASE_ADDRESS, SRAM4_REGION_NUMBER, SRAM4_SIZE_LOG2};
30use {defmt_rtt as _, panic_probe as _};
31
32/// Module providing shared memory constructs for intercore communication
33mod shared {
34 use core::sync::atomic::{AtomicU32, Ordering};
35
36 /// State shared between CM7 and CM4 cores for LED control
37 #[repr(C, align(4))]
38 pub struct SharedLedState {
39 pub magic: AtomicU32,
40 pub counter: AtomicU32,
41 pub led_states: AtomicU32,
42 }
43
44 // Bit positions in led_states
45 pub const GREEN_LED_BIT: u32 = 0;
46 pub const YELLOW_LED_BIT: u32 = 1;
47
48 impl SharedLedState {
49 pub const fn new() -> Self {
50 Self {
51 magic: AtomicU32::new(0xDEADBEEF),
52 counter: AtomicU32::new(0),
53 led_states: AtomicU32::new(0),
54 }
55 }
56
57 /// Set LED state by manipulating the appropriate bit in the led_states field
58 #[inline(never)]
59 pub fn set_led(&self, is_green: bool, state: bool) {
60 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
61 let current = self.led_states.load(Ordering::SeqCst);
62
63 let new_value = if state {
64 current | (1 << bit) // Set bit
65 } else {
66 current & !(1 << bit) // Clear bit
67 };
68
69 self.led_states.store(new_value, Ordering::SeqCst);
70 }
71
72 /// Get current LED state
73 #[inline(never)]
74 #[allow(dead_code)]
75 pub fn get_led(&self, is_green: bool) -> bool {
76 let bit = if is_green { GREEN_LED_BIT } else { YELLOW_LED_BIT };
77
78 let value = self.led_states.load(Ordering::SeqCst);
79 (value & (1 << bit)) != 0
80 }
81
82 /// Increment counter and return new value
83 #[inline(never)]
84 pub fn increment_counter(&self) -> u32 {
85 let current = self.counter.load(Ordering::SeqCst);
86 let new_value = current.wrapping_add(1);
87 self.counter.store(new_value, Ordering::SeqCst);
88 new_value
89 }
90
91 /// Get current counter value
92 #[inline(never)]
93 #[allow(dead_code)]
94 pub fn get_counter(&self) -> u32 {
95 let value = self.counter.load(Ordering::SeqCst);
96 value
97 }
98 }
99
100 #[link_section = ".ram_d3"]
101 pub static SHARED_LED_STATE: SharedLedState = SharedLedState::new();
102
103 // Memory region constants for MPU configuration
104 pub const SRAM4_BASE_ADDRESS: u32 = 0x38000000;
105 pub const SRAM4_SIZE_LOG2: u32 = 15; // 64KB = 2^(15+1)
106 pub const SRAM4_REGION_NUMBER: u8 = 0;
107}
108
109#[link_section = ".ram_d3"]
110static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
111
112/// Configure MPU to make SRAM4 region non-cacheable
113fn configure_mpu_non_cacheable(mpu: &mut MPU) {
114 asm::dmb();
115 unsafe {
116 // Disable MPU
117 mpu.ctrl.write(0);
118
119 // Configure SRAM4 as non-cacheable
120 mpu.rnr.write(SRAM4_REGION_NUMBER as u32);
121
122 // Set base address with region number
123 mpu.rbar.write(SRAM4_BASE_ADDRESS | (1 << 4));
124
125 // Configure region attributes
126 let rasr_value: u32 = (SRAM4_SIZE_LOG2 << 1) | // SIZE=15 (64KB)
127 (1 << 0) | // ENABLE=1
128 (3 << 24) | // AP=3 (Full access)
129 (1 << 19) | // TEX=1
130 (1 << 18); // S=1 (Shareable)
131
132 mpu.rasr.write(rasr_value);
133
134 // Enable MPU with default memory map as background
135 mpu.ctrl.write(1 | (1 << 2)); // MPU_ENABLE | PRIVDEFENA
136 }
137
138 asm::dsb();
139 asm::isb();
140
141 info!("MPU configured - SRAM4 set as non-cacheable");
142}
143
144#[embassy_executor::main]
145async fn main(_spawner: Spawner) -> ! {
146 // Set up MPU and cache configuration
147 {
148 let mut cp = cortex_m::Peripherals::take().unwrap();
149 let scb = &mut cp.SCB;
150
151 // First disable caches
152 scb.disable_icache();
153 scb.disable_dcache(&mut cp.CPUID);
154
155 // Configure MPU
156 configure_mpu_non_cacheable(&mut cp.MPU);
157
158 // Re-enable caches
159 scb.enable_icache();
160 scb.enable_dcache(&mut cp.CPUID);
161 asm::dsb();
162 asm::isb();
163 }
164
165 // Configure the clock system
166 let mut config = Config::default();
167 {
168 use embassy_stm32::rcc::*;
169 config.rcc.hsi = Some(HSIPrescaler::DIV1);
170 config.rcc.csi = true;
171 config.rcc.hsi48 = Some(Default::default());
172 config.rcc.pll1 = Some(Pll {
173 source: PllSource::HSI,
174 prediv: PllPreDiv::DIV4,
175 mul: PllMul::MUL50,
176 divp: Some(PllDiv::DIV2),
177 divq: Some(PllDiv::DIV8),
178 divr: None,
179 });
180 config.rcc.sys = Sysclk::PLL1_P;
181 config.rcc.ahb_pre = AHBPrescaler::DIV2;
182 config.rcc.apb1_pre = APBPrescaler::DIV2;
183 config.rcc.apb2_pre = APBPrescaler::DIV2;
184 config.rcc.apb3_pre = APBPrescaler::DIV2;
185 config.rcc.apb4_pre = APBPrescaler::DIV2;
186 config.rcc.voltage_scale = VoltageScale::Scale1;
187 config.rcc.supply_config = SupplyConfig::DirectSMPS;
188 }
189
190 // Initialize the CM7 core
191 let _p = embassy_stm32::init_primary(config, &SHARED_DATA);
192 info!("CM7 core initialized with non-cacheable SRAM4!");
193
194 // Verify shared memory is accessible
195 let magic = SHARED_LED_STATE.magic.load(core::sync::atomic::Ordering::SeqCst);
196 info!("CM7: Magic value = 0x{:X}", magic);
197
198 // Initialize LED states
199 SHARED_LED_STATE.set_led(true, false); // Green LED off
200 SHARED_LED_STATE.set_led(false, false); // Yellow LED off
201
202 // Main loop - periodically toggle LED states
203 let mut green_state = false;
204 let mut yellow_state = false;
205 let mut loop_count = 0;
206
207 info!("CM7: Starting main loop");
208 loop {
209 loop_count += 1;
210 let counter = SHARED_LED_STATE.increment_counter();
211
212 // Toggle green LED every second
213 if loop_count % 10 == 0 {
214 green_state = !green_state;
215 SHARED_LED_STATE.set_led(true, green_state);
216 info!("CM7: Counter = {}, Set green LED to {}", counter, green_state);
217 }
218
219 // Toggle yellow LED every 3 seconds
220 if loop_count % 30 == 0 {
221 yellow_state = !yellow_state;
222 SHARED_LED_STATE.set_led(false, yellow_state);
223 info!("CM7: Counter = {}, Set yellow LED to {}", counter, yellow_state);
224 }
225
226 Timer::after_millis(100).await;
227 }
228}
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml
index e5f2dfe86..1917749c5 100644
--- a/examples/stm32h7b0/Cargo.toml
+++ b/examples/stm32h7b0/Cargo.toml
@@ -3,19 +3,20 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7b0vb", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 11embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6", "dns"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16 17
17defmt = "0.3" 18defmt = "1.0.1"
18defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
19 20
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
@@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
24embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
25embedded-nal-async = "0.8.0" 26embedded-nal-async = "0.8.0"
26embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.6.1" }
27panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
28heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
29rand_core = "0.6.3"
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
@@ -72,3 +72,8 @@ incremental = false
72lto = 'fat' 72lto = 'fat'
73opt-level = 3 # <- 73opt-level = 3 # <-
74overflow-checks = false # <- 74overflow-checks = false # <-
75
76[package.metadata.embassy]
77build = [
78 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7b0" }
79]
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml
index 22d59be04..bfe59b68d 100644
--- a/examples/stm32h7rs/Cargo.toml
+++ b/examples/stm32h7rs/Cargo.toml
@@ -3,19 +3,20 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32h743bi to your chip name, if necessary. 9# Change stm32h743bi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32h7s3l8", "time-driver-tim2", "exti", "memory-x", "unstable-pac", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "medium-ethernet", "medium-ip", "proto-ipv4"] }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16 17
17defmt = "0.3" 18defmt = "1.0.1"
18defmt-rtt = "0.4" 19defmt-rtt = "1.0.0"
19 20
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 22cortex-m-rt = "0.7.0"
@@ -24,9 +25,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
24embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
25embedded-nal-async = "0.8.0" 26embedded-nal-async = "0.8.0"
26embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.6.1" }
27panic-probe = { version = "0.3", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
28heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
29rand_core = "0.6.3"
30critical-section = "1.1" 30critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
@@ -71,3 +71,8 @@ incremental = false
71lto = 'fat' 71lto = 'fat'
72opt-level = 3 # <- 72opt-level = 3 # <-
73overflow-checks = false # <- 73overflow-checks = false # <-
74
75[package.metadata.embassy]
76build = [
77 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32h7rs" }
78]
diff --git a/examples/stm32h7rs/src/bin/blinky.rs b/examples/stm32h7rs/src/bin/blinky.rs
index 137c585b7..5fd50fb15 100644
--- a/examples/stm32h7rs/src/bin/blinky.rs
+++ b/examples/stm32h7rs/src/bin/blinky.rs
@@ -25,6 +25,8 @@ async fn main(_spawner: Spawner) {
25 divp: Some(PllDiv::DIV2), 25 divp: Some(PllDiv::DIV2),
26 divq: None, 26 divq: None,
27 divr: None, 27 divr: None,
28 divs: None,
29 divt: None,
28 }); 30 });
29 config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz 31 config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
30 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz 32 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz
diff --git a/examples/stm32h7rs/src/bin/eth.rs b/examples/stm32h7rs/src/bin/eth.rs
index f2bd9575e..67f541564 100644
--- a/examples/stm32h7rs/src/bin/eth.rs
+++ b/examples/stm32h7rs/src/bin/eth.rs
@@ -11,7 +11,6 @@ use embassy_stm32::rng::Rng;
11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; 11use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
12use embassy_time::Timer; 12use embassy_time::Timer;
13use heapless::Vec; 13use heapless::Vec;
14use rand_core::RngCore;
15use static_cell::StaticCell; 14use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17 16
@@ -42,6 +41,8 @@ async fn main(spawner: Spawner) -> ! {
42 divp: Some(PllDiv::DIV2), 41 divp: Some(PllDiv::DIV2),
43 divq: None, 42 divq: None,
44 divr: None, 43 divr: None,
44 divs: None,
45 divt: None,
45 }); 46 });
46 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz 47 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
47 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 48 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
@@ -93,7 +94,7 @@ async fn main(spawner: Spawner) -> ! {
93 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 94 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
94 95
95 // Launch network task 96 // Launch network task
96 unwrap!(spawner.spawn(net_task(runner))); 97 spawner.spawn(unwrap!(net_task(runner)));
97 98
98 // Ensure DHCP configuration is up before trying connect 99 // Ensure DHCP configuration is up before trying connect
99 //stack.wait_config_up().await; 100 //stack.wait_config_up().await;
diff --git a/examples/stm32h7rs/src/bin/i2c.rs b/examples/stm32h7rs/src/bin/i2c.rs
index 31e83cbb5..870c57e0f 100644
--- a/examples/stm32h7rs/src/bin/i2c.rs
+++ b/examples/stm32h7rs/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::{Error, I2c}; 6use embassy_stm32::i2c::{Error, I2c};
7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, i2c, peripherals}; 7use embassy_stm32::{bind_interrupts, i2c, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
@@ -28,7 +27,6 @@ async fn main(_spawner: Spawner) {
28 Irqs, 27 Irqs,
29 p.GPDMA1_CH4, 28 p.GPDMA1_CH4,
30 p.GPDMA1_CH5, 29 p.GPDMA1_CH5,
31 Hertz(100_000),
32 Default::default(), 30 Default::default(),
33 ); 31 );
34 32
diff --git a/examples/stm32h7rs/src/bin/multiprio.rs b/examples/stm32h7rs/src/bin/multiprio.rs
index b4620888f..2f2ffdea2 100644
--- a/examples/stm32h7rs/src/bin/multiprio.rs
+++ b/examples/stm32h7rs/src/bin/multiprio.rs
@@ -135,16 +135,16 @@ fn main() -> ! {
135 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
136 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
138 unwrap!(spawner.spawn(run_high())); 138 spawner.spawn(unwrap!(run_high()));
139 139
140 // Medium-priority executor: UART5, priority level 7 140 // Medium-priority executor: UART5, priority level 7
141 interrupt::UART5.set_priority(Priority::P7); 141 interrupt::UART5.set_priority(Priority::P7);
142 let spawner = EXECUTOR_MED.start(interrupt::UART5); 142 let spawner = EXECUTOR_MED.start(interrupt::UART5);
143 unwrap!(spawner.spawn(run_med())); 143 spawner.spawn(unwrap!(run_med()));
144 144
145 // Low priority executor: runs in thread mode, using WFE/SEV 145 // Low priority executor: runs in thread mode, using WFE/SEV
146 let executor = EXECUTOR_LOW.init(Executor::new()); 146 let executor = EXECUTOR_LOW.init(Executor::new());
147 executor.run(|spawner| { 147 executor.run(|spawner| {
148 unwrap!(spawner.spawn(run_low())); 148 spawner.spawn(unwrap!(run_low()));
149 }); 149 });
150} 150}
diff --git a/examples/stm32h7rs/src/bin/signal.rs b/examples/stm32h7rs/src/bin/signal.rs
index b73360f32..97309798e 100644
--- a/examples/stm32h7rs/src/bin/signal.rs
+++ b/examples/stm32h7rs/src/bin/signal.rs
@@ -26,7 +26,7 @@ async fn my_sending_task() {
26#[embassy_executor::main] 26#[embassy_executor::main]
27async fn main(spawner: Spawner) { 27async fn main(spawner: Spawner) {
28 let _p = embassy_stm32::init(Default::default()); 28 let _p = embassy_stm32::init(Default::default());
29 unwrap!(spawner.spawn(my_sending_task())); 29 spawner.spawn(unwrap!(my_sending_task()));
30 30
31 loop { 31 loop {
32 let received_counter = SIGNAL.wait().await; 32 let received_counter = SIGNAL.wait().await;
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs
index 8d6ccc58b..8c280fdae 100644
--- a/examples/stm32h7rs/src/bin/spi.rs
+++ b/examples/stm32h7rs/src/bin/spi.rs
@@ -44,6 +44,6 @@ fn main() -> ! {
44 let executor = EXECUTOR.init(Executor::new()); 44 let executor = EXECUTOR.init(Executor::new());
45 45
46 executor.run(|spawner| { 46 executor.run(|spawner| {
47 unwrap!(spawner.spawn(main_task(spi))); 47 spawner.spawn(unwrap!(main_task(spi)));
48 }) 48 })
49} 49}
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs
index cb305351b..3fa69fd15 100644
--- a/examples/stm32h7rs/src/bin/spi_dma.rs
+++ b/examples/stm32h7rs/src/bin/spi_dma.rs
@@ -41,6 +41,6 @@ fn main() -> ! {
41 let executor = EXECUTOR.init(Executor::new()); 41 let executor = EXECUTOR.init(Executor::new());
42 42
43 executor.run(|spawner| { 43 executor.run(|spawner| {
44 unwrap!(spawner.spawn(main_task(spi))); 44 spawner.spawn(unwrap!(main_task(spi)));
45 }) 45 })
46} 46}
diff --git a/examples/stm32h7rs/src/bin/usart.rs b/examples/stm32h7rs/src/bin/usart.rs
index cc49c2fdb..264e7d582 100644
--- a/examples/stm32h7rs/src/bin/usart.rs
+++ b/examples/stm32h7rs/src/bin/usart.rs
@@ -34,6 +34,6 @@ fn main() -> ! {
34 let executor = EXECUTOR.init(Executor::new()); 34 let executor = EXECUTOR.init(Executor::new());
35 35
36 executor.run(|spawner| { 36 executor.run(|spawner| {
37 unwrap!(spawner.spawn(main_task())); 37 spawner.spawn(unwrap!(main_task()));
38 }) 38 })
39} 39}
diff --git a/examples/stm32h7rs/src/bin/usart_dma.rs b/examples/stm32h7rs/src/bin/usart_dma.rs
index c644e84bd..ea48515d7 100644
--- a/examples/stm32h7rs/src/bin/usart_dma.rs
+++ b/examples/stm32h7rs/src/bin/usart_dma.rs
@@ -42,6 +42,6 @@ fn main() -> ! {
42 let executor = EXECUTOR.init(Executor::new()); 42 let executor = EXECUTOR.init(Executor::new());
43 43
44 executor.run(|spawner| { 44 executor.run(|spawner| {
45 unwrap!(spawner.spawn(main_task())); 45 spawner.spawn(unwrap!(main_task()));
46 }) 46 })
47} 47}
diff --git a/examples/stm32h7rs/src/bin/usart_split.rs b/examples/stm32h7rs/src/bin/usart_split.rs
index d26c5003c..f56c1c57d 100644
--- a/examples/stm32h7rs/src/bin/usart_split.rs
+++ b/examples/stm32h7rs/src/bin/usart_split.rs
@@ -27,7 +27,7 @@ async fn main(spawner: Spawner) -> ! {
27 27
28 let (mut tx, rx) = usart.split(); 28 let (mut tx, rx) = usart.split();
29 29
30 unwrap!(spawner.spawn(reader(rx))); 30 spawner.spawn(unwrap!(reader(rx)));
31 31
32 loop { 32 loop {
33 let buf = CHANNEL.receive().await; 33 let buf = CHANNEL.receive().await;
diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs
index 56a9884af..23abc3e2f 100644
--- a/examples/stm32h7rs/src/bin/usb_serial.rs
+++ b/examples/stm32h7rs/src/bin/usb_serial.rs
@@ -40,6 +40,8 @@ async fn main(_spawner: Spawner) {
40 divp: Some(PllDiv::DIV1), //600 MHz 40 divp: Some(PllDiv::DIV1), //600 MHz
41 divq: Some(PllDiv::DIV2), // 300 MHz 41 divq: Some(PllDiv::DIV2), // 300 MHz
42 divr: Some(PllDiv::DIV2), // 300 MHz 42 divr: Some(PllDiv::DIV2), // 300 MHz
43 divs: None,
44 divt: None,
43 }); 45 });
44 config.rcc.sys = Sysclk::PLL1_P; // 600 MHz 46 config.rcc.sys = Sysclk::PLL1_P; // 600 MHz
45 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz 47 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz
diff --git a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
index 88d914180..4c1b450b4 100644
--- a/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
+++ b/examples/stm32h7rs/src/bin/xspi_memory_mapped.rs
@@ -3,7 +3,8 @@
3 3
4//! For Nucleo STM32H7S3L8 MB1737, has MX25UW25645GXDI00 4//! For Nucleo STM32H7S3L8 MB1737, has MX25UW25645GXDI00
5//! 5//!
6//! TODO: Currently this only uses single SPI, pending flash chip documentation for octo SPI. 6
7use core::cmp::min;
7 8
8use defmt::info; 9use defmt::info;
9use embassy_executor::Spawner; 10use embassy_executor::Spawner;
@@ -35,6 +36,8 @@ async fn main(_spawner: Spawner) {
35 divp: Some(PllDiv::DIV2), 36 divp: Some(PllDiv::DIV2),
36 divq: None, 37 divq: None,
37 divr: None, 38 divr: None,
39 divs: None,
40 divt: None,
38 }); 41 });
39 config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz 42 config.rcc.sys = Sysclk::PLL1_P; // 600 Mhz
40 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz 43 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 Mhz
@@ -52,14 +55,16 @@ async fn main(_spawner: Spawner) {
52 fifo_threshold: FIFOThresholdLevel::_4Bytes, 55 fifo_threshold: FIFOThresholdLevel::_4Bytes,
53 memory_type: MemoryType::Macronix, 56 memory_type: MemoryType::Macronix,
54 delay_hold_quarter_cycle: true, 57 delay_hold_quarter_cycle: true,
55 // memory_type: MemoryType::Micron,
56 // delay_hold_quarter_cycle: false,
57 device_size: MemorySize::_32MiB, 58 device_size: MemorySize::_32MiB,
58 chip_select_high_time: ChipSelectHighTime::_2Cycle, 59 chip_select_high_time: ChipSelectHighTime::_2Cycle,
59 free_running_clock: false, 60 free_running_clock: false,
60 clock_mode: false, 61 clock_mode: false,
61 wrap_size: WrapSize::None, 62 wrap_size: WrapSize::None,
62 // 300mhz / (4+1) = 60mhz. Unsure the limit, need to find a MX25UW25645GXDI00 datasheet. 63 // 300 MHz clock / (3 + 1) = 75 MHz. This is above the max for READ instructions so the
64 // FAST READ must be used. The nucleo board's flash can run at up to 133 MHz in SPI mode
65 // and 200 MHz in OPI mode. This clock prescaler must be even otherwise the clock will not
66 // have symmetric high and low times.
67 // The clock can also be fed by one of the PLLs to allow for more flexible clock rates.
63 clock_prescaler: 3, 68 clock_prescaler: 3,
64 sample_shifting: false, 69 sample_shifting: false,
65 chip_select_boundary: 0, 70 chip_select_boundary: 0,
@@ -71,28 +76,41 @@ async fn main(_spawner: Spawner) {
71 76
72 // Not necessary, but recommended if using XIP 77 // Not necessary, but recommended if using XIP
73 cor.SCB.enable_icache(); 78 cor.SCB.enable_icache();
79 // Note: Enabling data cache can cause issues with DMA transfers.
74 cor.SCB.enable_dcache(&mut cor.CPUID); 80 cor.SCB.enable_dcache(&mut cor.CPUID);
75 81
76 let xspi = embassy_stm32::xspi::Xspi::new_blocking_xspi( 82 let xspi = embassy_stm32::xspi::Xspi::new_blocking_xspi(
77 p.XSPI2, p.PN6, p.PN2, p.PN3, p.PN4, p.PN5, p.PN8, p.PN9, p.PN10, p.PN11, p.PN1, spi_config, 83 p.XSPI2, p.PN6, p.PN2, p.PN3, p.PN4, p.PN5, p.PN8, p.PN9, p.PN10, p.PN11, p.PN1, spi_config,
78 ); 84 );
79 85
80 let mut flash = FlashMemory::new(xspi).await; 86 let mut flash = SpiFlashMemory::new(xspi);
81 87
82 let flash_id = flash.read_id(); 88 let flash_id = flash.read_id();
83 info!("FLASH ID: {=[u8]:x}", flash_id); 89 info!("FLASH ID: {=[u8]:x}", flash_id);
84 90
85 let mut wr_buf = [0u8; 8]; 91 // Erase the first sector
86 for i in 0..8 { 92 flash.erase_sector(0);
87 wr_buf[i] = 0x90 + i as u8; 93
88 } 94 // Write some data into the flash. This writes more than one page to test that functionality.
89 let mut rd_buf = [0u8; 8]; 95 let mut wr_buf = [0u8; 512];
90 flash.erase_sector(0).await; 96 let base_number: u8 = 0x90;
91 flash.write_memory(0, &wr_buf, true).await; 97 for i in 0..512 {
92 flash.read_memory(0, &mut rd_buf, true); 98 wr_buf[i] = base_number.wrapping_add(i as u8);
93 info!("WRITE BUF: {=[u8]:#X}", wr_buf); 99 }
94 info!("READ BUF: {=[u8]:#X}", rd_buf); 100 flash.write_memory(0, &wr_buf);
95 flash.enable_mm().await; 101
102 // Read the data back and verify it.
103 let mut rd_buf = [0u8; 512];
104 let start_time = embassy_time::Instant::now();
105 flash.read_memory(0, &mut rd_buf);
106 let elapsed = start_time.elapsed();
107 info!("Read 512 bytes in {} us in SPI mode", elapsed.as_micros());
108 info!("WRITE BUF: {=[u8]:#X}", wr_buf[0..32]);
109 info!("READ BUF: {=[u8]:#X}", rd_buf[0..32]);
110
111 assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer");
112
113 flash.enable_mm();
96 info!("Enabled memory mapped mode"); 114 info!("Enabled memory mapped mode");
97 115
98 let first_u32 = unsafe { *(0x70000000 as *const u32) }; 116 let first_u32 = unsafe { *(0x70000000 as *const u32) };
@@ -103,10 +121,53 @@ async fn main(_spawner: Spawner) {
103 assert_eq!(second_u32, 0x97969594); 121 assert_eq!(second_u32, 0x97969594);
104 info!("second_u32 {:08x}", first_u32); 122 info!("second_u32 {:08x}", first_u32);
105 123
106 flash.disable_mm().await; 124 flash.disable_mm();
107 info!("Disabled memory mapped mode"); 125 info!("Disabled memory mapped mode");
108 126
127 let flash_id = flash.read_id();
128 info!("FLASH ID: {=[u8]:x}", flash_id);
129
130 let mut flash = flash.into_octo();
131
132 Timer::after_millis(100).await;
133
134 let flash_id = flash.read_id();
135 info!("FLASH ID in OPI mode: {=[u8]:x}", flash_id);
136
137 flash.erase_sector(0);
138
139 let mut rd_buf = [0u8; 512];
140 flash.read_memory(0, &mut rd_buf);
141 info!("READ BUF after erase: {=[u8]:#X}", rd_buf[0..32]);
142
143 assert_eq!(rd_buf, [0xFF; 512], "Read buffer is not all 0xFF after erase");
144
145 flash.write_memory(0, &wr_buf);
146 let start = embassy_time::Instant::now();
147 flash.read_memory(0, &mut rd_buf);
148 let elapsed = start.elapsed();
149 info!("Read 512 bytes in {} us in OPI mode", elapsed.as_micros());
150 info!("READ BUF after write: {=[u8]:#X}", rd_buf[0..32]);
151 assert_eq!(wr_buf, rd_buf, "Read buffer does not match write buffer in OPI mode");
152
153 flash.enable_mm();
154 info!("Enabled memory mapped mode in OPI mode");
155 let first_u32 = unsafe { *(0x70000000 as *const u32) };
156 assert_eq!(first_u32, 0x93929190);
157 info!("first_u32 {:08x}", first_u32);
158 let second_u32 = unsafe { *(0x70000004 as *const u32) };
159 assert_eq!(second_u32, 0x97969594);
160 info!("second_u32 {:08x}", first_u32);
161 flash.disable_mm();
162 info!("Disabled memory mapped mode in OPI mode");
163
164 // Reset back to SPI mode
165 let mut flash = flash.into_spi();
166 let flash_id = flash.read_id();
167 info!("FLASH ID back in SPI mode: {=[u8]:x}", flash_id);
168
109 info!("DONE"); 169 info!("DONE");
170
110 // Output pin PE3 171 // Output pin PE3
111 let mut led = Output::new(p.PE3, Level::Low, Speed::Low); 172 let mut led = Output::new(p.PE3, Level::Low, Speed::Low);
112 173
@@ -116,80 +177,268 @@ async fn main(_spawner: Spawner) {
116 } 177 }
117} 178}
118 179
119const MEMORY_PAGE_SIZE: usize = 8; 180const MEMORY_PAGE_SIZE: usize = 256;
120
121const CMD_READ: u8 = 0x0B;
122const _CMD_QUAD_READ: u8 = 0x6B;
123
124const CMD_WRITE_PG: u8 = 0x02;
125const _CMD_QUAD_WRITE_PG: u8 = 0x32;
126
127const CMD_READ_ID: u8 = 0x9F;
128const CMD_READ_ID_OCTO: u16 = 0x9F60;
129 181
130const CMD_ENABLE_RESET: u8 = 0x66; 182/// Implementation of access to flash chip using SPI.
131const CMD_RESET: u8 = 0x99; 183///
132 184/// Chip commands are hardcoded as it depends on used chip.
133const CMD_WRITE_ENABLE: u8 = 0x06; 185/// This targets a MX25UW25645GXDI00.
134 186pub struct SpiFlashMemory<I: Instance> {
135const CMD_CHIP_ERASE: u8 = 0xC7; 187 xspi: Xspi<'static, I, Blocking>,
136const CMD_SECTOR_ERASE: u8 = 0x20; 188}
137const CMD_BLOCK_ERASE_32K: u8 = 0x52;
138const CMD_BLOCK_ERASE_64K: u8 = 0xD8;
139
140const CMD_READ_SR: u8 = 0x05;
141const CMD_READ_CR: u8 = 0x35;
142
143const CMD_WRITE_SR: u8 = 0x01;
144const CMD_WRITE_CR: u8 = 0x31;
145 189
146/// Implementation of access to flash chip. 190/// Implementation of access to flash chip using Octo SPI.
147/// 191///
148/// Chip commands are hardcoded as it depends on used chip. 192/// Chip commands are hardcoded as it depends on used chip.
149/// This targets a MX25UW25645GXDI00. 193/// This targets a MX25UW25645GXDI00.
150pub struct FlashMemory<I: Instance> { 194pub struct OpiFlashMemory<I: Instance> {
151 xspi: Xspi<'static, I, Blocking>, 195 xspi: Xspi<'static, I, Blocking>,
152} 196}
153 197
154impl<I: Instance> FlashMemory<I> { 198/// SPI mode commands for MX25UW25645G flash memory
155 pub async fn new(xspi: Xspi<'static, I, Blocking>) -> Self { 199#[allow(dead_code)]
156 let mut memory = Self { xspi }; 200#[repr(u8)]
201enum SpiCommand {
202 // Array access commands
203 /// Read data bytes using 3-byte address (up to 50 MHz)
204 Read3B = 0x03,
205 /// Fast read data bytes using 3-byte address with 8 dummy cycles (up to 133 MHz)
206 FastRead3B = 0x0B,
207 /// Program 1-256 bytes of data using 3-byte address
208 PageProgram3B = 0x02,
209 /// Erase 4KB sector using 3-byte address
210 SectorErase3B = 0x20,
211 /// Erase 64KB block using 3-byte address
212 BlockErase3B = 0xD8,
213 /// Read data bytes using 4-byte address (up to 50 MHz)
214 Read4B = 0x13,
215 /// Fast read data bytes using 4-byte address with 8 dummy cycles (up to 133 MHz)
216 FastRead4B = 0x0C,
217 /// Program 1-256 bytes of data using 4-byte address
218 PageProgram4B = 0x12,
219 /// Erase 4KB sector using 4-byte address
220 SectorErase4B = 0x21,
221 /// Erase 64KB block using 4-byte address
222 BlockErase4B = 0xDC,
223 /// Erase entire chip (only if no blocks are protected)
224 ChipErase = 0x60,
225
226 // Write Buffer Access commands
227 /// Read data from the 256-byte page buffer
228 ReadBuffer = 0x25,
229 /// Initialize write-to-buffer sequence, clears buffer and writes initial data
230 WriteBufferInitial = 0x22,
231 /// Continue writing data to buffer (used between WRBI and WRCF)
232 WriteBufferContinue = 0x24,
233 /// Confirm write operation, programs buffer contents to flash array
234 WriteBufferConfirm = 0x31,
235
236 // Device operation commands
237 /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations
238 WriteEnable = 0x06,
239 /// Clear Write Enable Latch (WEL) bit
240 WriteDisable = 0x04,
241 /// Select write protection mode (BP mode or Advanced Sector Protection)
242 WriteProtectSelection = 0x68,
243 /// Suspend ongoing program or erase operation to allow read access
244 ProgramEraseSuspend = 0xB0,
245 /// Resume suspended program or erase operation
246 ProgramEraseResume = 0x30,
247 /// Enter deep power-down mode for minimum power consumption
248 DeepPowerDown = 0xB9,
249 /// Exit deep power-down mode and return to standby
250 ReleaseFromDeepPowerDown = 0xAB,
251 /// No operation, can terminate Reset Enable command
252 NoOperation = 0x00,
253 /// Enable reset operation (must precede Reset Memory command)
254 ResetEnable = 0x66,
255 /// Reset device to power-on state (requires prior Reset Enable)
256 ResetMemory = 0x99,
257 /// Protect all sectors using Dynamic Protection Bits (DPB)
258 GangBlockLock = 0x7E,
259 /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB)
260 GangBlockUnlock = 0x98,
261
262 // Register Access commands
263 /// Read 3-byte device identification (manufacturer ID + device ID)
264 ReadIdentification = 0x9F,
265 /// Read Serial Flash Discoverable Parameters (SFDP) table
266 ReadSFDP = 0x5A,
267 /// Read 8-bit Status Register (WIP, WEL, BP bits, etc.)
268 ReadStatusRegister = 0x05,
269 /// Read 8-bit Configuration Register (ODS, TB, PBE bits)
270 ReadConfigurationRegister = 0x15,
271 /// Write Status and/or Configuration Register (1-2 bytes)
272 WriteStatusConfigurationRegister = 0x01,
273 /// Read Configuration Register 2 from specified 4-byte address
274 ReadConfigurationRegister2 = 0x71,
275 /// Write Configuration Register 2 to specified 4-byte address
276 WriteConfigurationRegister2 = 0x72,
277 /// Read 8-bit Security Register (protection status, suspend bits)
278 ReadSecurityRegister = 0x2B,
279 /// Write Security Register to set customer lock-down bit
280 WriteSecurityRegister = 0x2F,
281 /// Read 32-bit Fast Boot Register (boot address and configuration)
282 ReadFastBootRegister = 0x16,
283 /// Write 32-bit Fast Boot Register
284 WriteFastBootRegister = 0x17,
285 /// Erase Fast Boot Register (disable fast boot feature)
286 EraseFastBootRegister = 0x18,
287 /// Set burst/wrap length for read operations (16/32/64 bytes)
288 SetBurstLength = 0xC0,
289 /// Enter 8K-bit secured OTP mode for programming unique identifiers
290 EnterSecuredOTP = 0xB1,
291 /// Exit secured OTP mode and return to main array access
292 ExitSecuredOTP = 0xC1,
293 /// Write Lock Register to control SPB protection mode
294 WriteLockRegister = 0x2C,
295 /// Read Lock Register status
296 ReadLockRegister = 0x2D,
297 /// Program Solid Protection Bit (SPB) for specified sector/block
298 WriteSPB = 0xE3,
299 /// Erase all Solid Protection Bits (SPB)
300 EraseSPB = 0xE4,
301 /// Read Solid Protection Bit (SPB) status for specified sector/block
302 ReadSPB = 0xE2,
303 /// Write Dynamic Protection Bit (DPB) for specified sector
304 WriteDPB = 0xE1,
305 /// Read Dynamic Protection Bit (DPB) status for specified sector
306 ReadDPB = 0xE0,
307 /// Read 64-bit password register (only in Solid Protection mode)
308 ReadPassword = 0x27,
309 /// Write 64-bit password register
310 WritePassword = 0x28,
311 /// Unlock SPB operations using 64-bit password
312 PasswordUnlock = 0x29,
313}
157 314
158 memory.reset_memory().await; 315/// OPI mode commands for MX25UW25645G flash memory
159 memory.enable_octo(); 316#[allow(dead_code)]
160 memory 317#[repr(u16)]
161 } 318enum OpiCommand {
319 // Array access commands
320 /// Read data using 8 I/O lines in STR mode with configurable dummy cycles (up to 200 MHz)
321 OctaRead = 0xEC13,
322 /// Read data using 8 I/O lines in DTR mode with configurable dummy cycles (up to 200 MHz)
323 OctaDTRRead = 0xEE11,
324 /// Program 1-256 bytes using 4-byte address and 8 I/O lines
325 PageProgram4B = 0x12ED,
326 /// Erase 4KB sector using 4-byte address
327 SectorErase4B = 0x21DE,
328 /// Erase 64KB block using 4-byte address
329 BlockErase4B = 0xDC23,
330 /// Erase entire chip (only if no blocks are protected)
331 ChipErase = 0x609F,
332
333 // Write Buffer Access commands
334 /// Read data from the 256-byte page buffer using 4-byte address
335 ReadBuffer = 0x25DA,
336 /// Initialize interruptible write-to-buffer sequence with 4-byte address
337 WriteBufferInitial = 0x22DD,
338 /// Continue writing data to buffer during interruptible sequence
339 WriteBufferContinue = 0x24DB,
340 /// Confirm and execute write operation from buffer to flash array
341 WriteBufferConfirm = 0x31CE,
342
343 // Device operation commands
344 /// Set Write Enable Latch (WEL) bit, required before write/program/erase operations
345 WriteEnable = 0x06F9,
346 /// Clear Write Enable Latch (WEL) bit, aborts write-to-buffer sequence
347 WriteDisable = 0x04FB,
348 /// Select write protection mode (BP mode or Advanced Sector Protection) - OTP bit
349 WriteProtectSelection = 0x6897,
350 /// Suspend ongoing program or erase operation to allow read from other banks
351 ProgramEraseSuspend = 0xB04F,
352 /// Resume suspended program or erase operation
353 ProgramEraseResume = 0x30CF,
354 /// Enter deep power-down mode for minimum power consumption
355 DeepPowerDown = 0xB946,
356 /// Exit deep power-down mode and return to standby
357 ReleaseFromDeepPowerDown = 0xAB54,
358 /// No operation, can terminate Reset Enable command
359 NoOperation = 0x00FF,
360 /// Enable reset operation (must precede Reset Memory command)
361 ResetEnable = 0x6699,
362 /// Reset device to power-on state, clears volatile settings
363 ResetMemory = 0x9966,
364 /// Protect all sectors using Dynamic Protection Bits (DPB)
365 GangBlockLock = 0x7E81,
366 /// Unprotect all sectors by clearing Dynamic Protection Bits (DPB)
367 GangBlockUnlock = 0x9867,
368
369 // Register Access commands
370 /// Read 3-byte device identification with 4-byte dummy address
371 ReadIdentification = 0x9F60,
372 /// Read Serial Flash Discoverable Parameters (SFDP) table with 4-byte address
373 ReadSFDP = 0x5AA5,
374 /// Read 8-bit Status Register with 4-byte dummy address
375 ReadStatusRegister = 0x05FA,
376 /// Read 8-bit Configuration Register with specific address (00000001h)
377 ReadConfigurationRegister = 0x15EA,
378 /// Write 8-bit Status Register with specific address (00000000h) or Configuration Register with address (00000001h)
379 WriteStatusConfigurationRegister = 0x01FE,
380 /// Read Configuration Register 2 from specified 4-byte address
381 ReadConfigurationRegister2 = 0x718E,
382 /// Write Configuration Register 2 to specified 4-byte address
383 WriteConfigurationRegister2 = 0x728D,
384 /// Read 8-bit Security Register with 4-byte dummy address
385 ReadSecurityRegister = 0x2BD4,
386 /// Write Security Register to set customer lock-down bit
387 WriteSecurityRegister = 0x2FD0,
388 /// Set burst/wrap length for read operations with 4-byte dummy address
389 SetBurstLength = 0xC03F,
390 /// Read 32-bit Fast Boot Register with 4-byte dummy address
391 ReadFastBootRegister = 0x16E9,
392 /// Write 32-bit Fast Boot Register with 4-byte dummy address
393 WriteFastBootRegister = 0x17E8,
394 /// Erase Fast Boot Register (disable fast boot feature)
395 EraseFastBootRegister = 0x18E7,
396 /// Enter 8K-bit secured OTP mode for programming unique identifiers
397 EnterSecuredOTP = 0xB14E,
398 /// Exit secured OTP mode and return to main array access
399 ExitSecuredOTP = 0xC13E,
400 /// Write Lock Register to control SPB protection mode with 4-byte dummy address
401 WriteLockRegister = 0x2CD3,
402 /// Read Lock Register status with 4-byte dummy address
403 ReadLockRegister = 0x2DD2,
404 /// Program Solid Protection Bit (SPB) for specified 4-byte address
405 WriteSPB = 0xE31C,
406 /// Erase all Solid Protection Bits (SPB)
407 EraseSPB = 0xE41B,
408 /// Read Solid Protection Bit (SPB) status for specified 4-byte address
409 ReadSPB = 0xE21D,
410 /// Write Dynamic Protection Bit (DPB) for specified 4-byte address
411 WriteDPB = 0xE11E,
412 /// Read Dynamic Protection Bit (DPB) status for specified 4-byte address
413 ReadDPB = 0xE01F,
414 /// Read 64-bit password register with 4-byte dummy address and 20 dummy cycles
415 ReadPassword = 0x27D8,
416 /// Write 64-bit password register with 4-byte dummy address
417 WritePassword = 0x28D7,
418 /// Unlock SPB operations using 64-bit password with 4-byte dummy address
419 PasswordUnlock = 0x29D6,
420}
162 421
163 async fn qpi_mode(&mut self) { 422impl<I: Instance> SpiFlashMemory<I> {
164 // Enter qpi mode 423 pub fn new(xspi: Xspi<'static, I, Blocking>) -> Self {
165 self.exec_command(0x38).await; 424 let mut memory = Self { xspi };
166 425
167 // Set read param 426 memory.reset_memory();
168 let transaction = TransferConfig { 427 memory
169 iwidth: XspiWidth::QUAD,
170 dwidth: XspiWidth::QUAD,
171 instruction: Some(0xC0),
172 ..Default::default()
173 };
174 self.enable_write().await;
175 self.xspi.blocking_write(&[0x30_u8], transaction).unwrap();
176 self.wait_write_finish();
177 } 428 }
178 429
179 pub async fn disable_mm(&mut self) { 430 pub fn disable_mm(&mut self) {
180 self.xspi.disable_memory_mapped_mode(); 431 self.xspi.disable_memory_mapped_mode();
181 } 432 }
182 433
183 pub async fn enable_mm(&mut self) { 434 pub fn enable_mm(&mut self) {
184 self.qpi_mode().await;
185
186 let read_config = TransferConfig { 435 let read_config = TransferConfig {
187 iwidth: XspiWidth::SING, 436 iwidth: XspiWidth::SING,
188 isize: AddressSize::_8bit, 437 isize: AddressSize::_8bit,
189 adwidth: XspiWidth::SING, 438 adwidth: XspiWidth::SING,
190 adsize: AddressSize::_24bit, 439 adsize: AddressSize::_32bit,
191 dwidth: XspiWidth::SING, 440 dwidth: XspiWidth::SING,
192 instruction: Some(CMD_READ as u32), 441 instruction: Some(SpiCommand::FastRead4B as u32),
193 dummy: DummyCycles::_8, 442 dummy: DummyCycles::_8,
194 ..Default::default() 443 ..Default::default()
195 }; 444 };
@@ -198,42 +447,28 @@ impl<I: Instance> FlashMemory<I> {
198 iwidth: XspiWidth::SING, 447 iwidth: XspiWidth::SING,
199 isize: AddressSize::_8bit, 448 isize: AddressSize::_8bit,
200 adwidth: XspiWidth::SING, 449 adwidth: XspiWidth::SING,
201 adsize: AddressSize::_24bit, 450 adsize: AddressSize::_32bit,
202 dwidth: XspiWidth::SING, 451 dwidth: XspiWidth::SING,
203 instruction: Some(CMD_WRITE_PG as u32), 452 instruction: Some(SpiCommand::PageProgram4B as u32),
204 dummy: DummyCycles::_0, 453 dummy: DummyCycles::_0,
205 ..Default::default() 454 ..Default::default()
206 }; 455 };
207 self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap(); 456 self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap();
208 } 457 }
209 458
210 fn enable_octo(&mut self) { 459 fn into_octo(mut self) -> OpiFlashMemory<I> {
211 let cr = self.read_cr(); 460 self.enable_opi_mode();
212 // info!("Read cr: {:x}", cr); 461 OpiFlashMemory { xspi: self.xspi }
213 self.write_cr(cr | 0x02);
214 // info!("Read cr after writing: {:x}", cr);
215 } 462 }
216 463
217 pub fn disable_octo(&mut self) { 464 fn enable_opi_mode(&mut self) {
218 let cr = self.read_cr(); 465 let cr2_0 = self.read_cr2(0);
219 self.write_cr(cr & (!(0x02))); 466 info!("Read CR2 at 0x0: {:x}", cr2_0);
220 } 467 self.enable_write();
221 468 self.write_cr2(0, cr2_0 | 0x01); // Set bit 0 to enable octo SPI in STR
222 async fn exec_command_4(&mut self, cmd: u8) {
223 let transaction = TransferConfig {
224 iwidth: XspiWidth::QUAD,
225 adwidth: XspiWidth::NONE,
226 // adsize: AddressSize::_24bit,
227 dwidth: XspiWidth::NONE,
228 instruction: Some(cmd as u32),
229 address: None,
230 dummy: DummyCycles::_0,
231 ..Default::default()
232 };
233 self.xspi.blocking_command(&transaction).unwrap();
234 } 469 }
235 470
236 async fn exec_command(&mut self, cmd: u8) { 471 fn exec_command(&mut self, cmd: u8) {
237 let transaction = TransferConfig { 472 let transaction = TransferConfig {
238 iwidth: XspiWidth::SING, 473 iwidth: XspiWidth::SING,
239 adwidth: XspiWidth::NONE, 474 adwidth: XspiWidth::NONE,
@@ -248,16 +483,14 @@ impl<I: Instance> FlashMemory<I> {
248 self.xspi.blocking_command(&transaction).unwrap(); 483 self.xspi.blocking_command(&transaction).unwrap();
249 } 484 }
250 485
251 pub async fn reset_memory(&mut self) { 486 pub fn reset_memory(&mut self) {
252 self.exec_command_4(CMD_ENABLE_RESET).await; 487 self.exec_command(SpiCommand::ResetEnable as u8);
253 self.exec_command_4(CMD_RESET).await; 488 self.exec_command(SpiCommand::ResetMemory as u8);
254 self.exec_command(CMD_ENABLE_RESET).await;
255 self.exec_command(CMD_RESET).await;
256 self.wait_write_finish(); 489 self.wait_write_finish();
257 } 490 }
258 491
259 pub async fn enable_write(&mut self) { 492 pub fn enable_write(&mut self) {
260 self.exec_command(CMD_WRITE_ENABLE).await; 493 self.exec_command(SpiCommand::WriteEnable as u8);
261 } 494 }
262 495
263 pub fn read_id(&mut self) -> [u8; 3] { 496 pub fn read_id(&mut self) -> [u8; 3] {
@@ -266,92 +499,64 @@ impl<I: Instance> FlashMemory<I> {
266 iwidth: XspiWidth::SING, 499 iwidth: XspiWidth::SING,
267 isize: AddressSize::_8bit, 500 isize: AddressSize::_8bit,
268 adwidth: XspiWidth::NONE, 501 adwidth: XspiWidth::NONE,
269 // adsize: AddressSize::_24bit,
270 dwidth: XspiWidth::SING, 502 dwidth: XspiWidth::SING,
271 instruction: Some(CMD_READ_ID as u32), 503 instruction: Some(SpiCommand::ReadIdentification as u32),
272 ..Default::default() 504 ..Default::default()
273 }; 505 };
274 // info!("Reading id: 0x{:X}", transaction.instruction);
275 self.xspi.blocking_read(&mut buffer, transaction).unwrap(); 506 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
276 buffer 507 buffer
277 } 508 }
278 509
279 pub fn read_id_8(&mut self) -> [u8; 3] { 510 pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) {
280 let mut buffer = [0; 3];
281 let transaction: TransferConfig = TransferConfig {
282 iwidth: XspiWidth::OCTO,
283 isize: AddressSize::_16bit,
284 adwidth: XspiWidth::OCTO,
285 address: Some(0),
286 adsize: AddressSize::_32bit,
287 dwidth: XspiWidth::OCTO,
288 instruction: Some(CMD_READ_ID_OCTO as u32),
289 dummy: DummyCycles::_4,
290 ..Default::default()
291 };
292 info!("Reading id: {:#X}", transaction.instruction);
293 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
294 buffer
295 }
296
297 pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8], use_dma: bool) {
298 let transaction = TransferConfig { 511 let transaction = TransferConfig {
299 iwidth: XspiWidth::SING, 512 iwidth: XspiWidth::SING,
300 adwidth: XspiWidth::SING, 513 adwidth: XspiWidth::SING,
301 adsize: AddressSize::_24bit, 514 adsize: AddressSize::_32bit,
302 dwidth: XspiWidth::SING, 515 dwidth: XspiWidth::SING,
303 instruction: Some(CMD_READ as u32), 516 instruction: Some(SpiCommand::FastRead4B as u32),
304 dummy: DummyCycles::_8, 517 dummy: DummyCycles::_8,
305 // dwidth: XspiWidth::QUAD,
306 // instruction: Some(CMD_QUAD_READ as u32),
307 // dummy: DummyCycles::_8,
308 address: Some(addr), 518 address: Some(addr),
309 ..Default::default() 519 ..Default::default()
310 }; 520 };
311 if use_dma { 521
312 self.xspi.blocking_read(buffer, transaction).unwrap(); 522 self.xspi.blocking_read(buffer, transaction).unwrap();
313 } else {
314 self.xspi.blocking_read(buffer, transaction).unwrap();
315 }
316 } 523 }
317 524
318 fn wait_write_finish(&mut self) { 525 fn wait_write_finish(&mut self) {
319 while (self.read_sr() & 0x01) != 0 {} 526 while (self.read_sr() & 0x01) != 0 {}
320 } 527 }
321 528
322 async fn perform_erase(&mut self, addr: u32, cmd: u8) { 529 fn perform_erase(&mut self, addr: u32, cmd: u8) {
323 let transaction = TransferConfig { 530 let transaction = TransferConfig {
324 iwidth: XspiWidth::SING, 531 iwidth: XspiWidth::SING,
325 adwidth: XspiWidth::SING, 532 adwidth: XspiWidth::SING,
326 adsize: AddressSize::_24bit, 533 adsize: AddressSize::_32bit,
327 dwidth: XspiWidth::NONE, 534 dwidth: XspiWidth::NONE,
328 instruction: Some(cmd as u32), 535 instruction: Some(cmd as u32),
329 address: Some(addr), 536 address: Some(addr),
330 dummy: DummyCycles::_0, 537 dummy: DummyCycles::_0,
331 ..Default::default() 538 ..Default::default()
332 }; 539 };
333 self.enable_write().await; 540 self.enable_write();
334 self.xspi.blocking_command(&transaction).unwrap(); 541 self.xspi.blocking_command(&transaction).unwrap();
335 self.wait_write_finish(); 542 self.wait_write_finish();
336 } 543 }
337 544
338 pub async fn erase_sector(&mut self, addr: u32) { 545 pub fn erase_sector(&mut self, addr: u32) {
339 self.perform_erase(addr, CMD_SECTOR_ERASE).await; 546 self.perform_erase(addr, SpiCommand::SectorErase4B as u8);
340 } 547 }
341 548
342 pub async fn erase_block_32k(&mut self, addr: u32) { 549 pub fn erase_block_64k(&mut self, addr: u32) {
343 self.perform_erase(addr, CMD_BLOCK_ERASE_32K).await; 550 self.perform_erase(addr, SpiCommand::BlockErase4B as u8);
344 } 551 }
345 552
346 pub async fn erase_block_64k(&mut self, addr: u32) { 553 pub fn erase_chip(&mut self) {
347 self.perform_erase(addr, CMD_BLOCK_ERASE_64K).await; 554 self.enable_write();
348 } 555 self.exec_command(SpiCommand::ChipErase as u8);
349 556 self.wait_write_finish();
350 pub async fn erase_chip(&mut self) {
351 self.exec_command(CMD_CHIP_ERASE).await;
352 } 557 }
353 558
354 async fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize, use_dma: bool) { 559 fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) {
355 assert!( 560 assert!(
356 (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32, 561 (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32,
357 "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}", 562 "write_page(): page write length exceeds page boundary (len = {}, addr = {:X}",
@@ -361,48 +566,43 @@ impl<I: Instance> FlashMemory<I> {
361 566
362 let transaction = TransferConfig { 567 let transaction = TransferConfig {
363 iwidth: XspiWidth::SING, 568 iwidth: XspiWidth::SING,
364 adsize: AddressSize::_24bit, 569 adsize: AddressSize::_32bit,
365 adwidth: XspiWidth::SING, 570 adwidth: XspiWidth::SING,
366 dwidth: XspiWidth::SING, 571 dwidth: XspiWidth::SING,
367 instruction: Some(CMD_WRITE_PG as u32), 572 instruction: Some(SpiCommand::PageProgram4B as u32),
368 // dwidth: XspiWidth::QUAD,
369 // instruction: Some(CMD_QUAD_WRITE_PG as u32),
370 address: Some(addr), 573 address: Some(addr),
371 dummy: DummyCycles::_0, 574 dummy: DummyCycles::_0,
372 ..Default::default() 575 ..Default::default()
373 }; 576 };
374 self.enable_write().await; 577 self.enable_write();
375 if use_dma { 578 self.xspi.blocking_write(buffer, transaction).unwrap();
376 self.xspi.blocking_write(buffer, transaction).unwrap();
377 } else {
378 self.xspi.blocking_write(buffer, transaction).unwrap();
379 }
380 self.wait_write_finish(); 579 self.wait_write_finish();
381 } 580 }
382 581
383 pub async fn write_memory(&mut self, addr: u32, buffer: &[u8], use_dma: bool) { 582 pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) {
384 let mut left = buffer.len(); 583 let mut left = buffer.len();
385 let mut place = addr; 584 let mut place = addr;
386 let mut chunk_start = 0; 585 let mut chunk_start = 0;
387 586
388 while left > 0 { 587 while left > 0 {
389 let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize; 588 let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize;
390 let chunk_size = if left >= max_chunk_size { max_chunk_size } else { left }; 589 let chunk_size = min(max_chunk_size, left);
391 let chunk = &buffer[chunk_start..(chunk_start + chunk_size)]; 590 let chunk = &buffer[chunk_start..(chunk_start + chunk_size)];
392 self.write_page(place, chunk, chunk_size, use_dma).await; 591 self.write_page(place, chunk, chunk_size);
393 place += chunk_size as u32; 592 place += chunk_size as u32;
394 left -= chunk_size; 593 left -= chunk_size;
395 chunk_start += chunk_size; 594 chunk_start += chunk_size;
396 } 595 }
397 } 596 }
398 597
598 // Note: read_register cannot be used to read the configuration register 2 since there is an
599 // address required for that read.
399 fn read_register(&mut self, cmd: u8) -> u8 { 600 fn read_register(&mut self, cmd: u8) -> u8 {
400 let mut buffer = [0; 1]; 601 let mut buffer = [0; 1];
401 let transaction: TransferConfig = TransferConfig { 602 let transaction: TransferConfig = TransferConfig {
402 iwidth: XspiWidth::SING, 603 iwidth: XspiWidth::SING,
403 isize: AddressSize::_8bit, 604 isize: AddressSize::_8bit,
404 adwidth: XspiWidth::NONE, 605 adwidth: XspiWidth::NONE,
405 adsize: AddressSize::_24bit,
406 dwidth: XspiWidth::SING, 606 dwidth: XspiWidth::SING,
407 instruction: Some(cmd as u32), 607 instruction: Some(cmd as u32),
408 address: None, 608 address: None,
@@ -410,39 +610,345 @@ impl<I: Instance> FlashMemory<I> {
410 ..Default::default() 610 ..Default::default()
411 }; 611 };
412 self.xspi.blocking_read(&mut buffer, transaction).unwrap(); 612 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
413 // info!("Read w25q64 register: 0x{:x}", buffer[0]);
414 buffer[0] 613 buffer[0]
415 } 614 }
416 615
417 fn write_register(&mut self, cmd: u8, value: u8) { 616 pub fn read_sr(&mut self) -> u8 {
418 let buffer = [value; 1]; 617 self.read_register(SpiCommand::ReadStatusRegister as u8)
618 }
619
620 pub fn read_cr(&mut self) -> u8 {
621 self.read_register(SpiCommand::ReadConfigurationRegister as u8)
622 }
623
624 pub fn write_sr_cr(&mut self, sr: u8, cr: u8) {
625 let buffer = [sr, cr];
419 let transaction: TransferConfig = TransferConfig { 626 let transaction: TransferConfig = TransferConfig {
420 iwidth: XspiWidth::SING, 627 iwidth: XspiWidth::SING,
421 isize: AddressSize::_8bit, 628 isize: AddressSize::_8bit,
422 instruction: Some(cmd as u32), 629 instruction: Some(SpiCommand::WriteStatusConfigurationRegister as u32),
423 adsize: AddressSize::_24bit,
424 adwidth: XspiWidth::NONE, 630 adwidth: XspiWidth::NONE,
425 dwidth: XspiWidth::SING, 631 dwidth: XspiWidth::SING,
426 address: None, 632 address: None,
427 dummy: DummyCycles::_0, 633 dummy: DummyCycles::_0,
428 ..Default::default() 634 ..Default::default()
429 }; 635 };
636 self.enable_write();
637 self.xspi.blocking_write(&buffer, transaction).unwrap();
638 self.wait_write_finish();
639 }
640
641 pub fn read_cr2(&mut self, address: u32) -> u8 {
642 let mut buffer = [0; 1];
643 let transaction: TransferConfig = TransferConfig {
644 iwidth: XspiWidth::SING,
645 isize: AddressSize::_8bit,
646 instruction: Some(SpiCommand::ReadConfigurationRegister2 as u32),
647 adsize: AddressSize::_32bit,
648 adwidth: XspiWidth::SING,
649 dwidth: XspiWidth::SING,
650 address: Some(address),
651 dummy: DummyCycles::_0,
652 ..Default::default()
653 };
654 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
655 buffer[0]
656 }
657
658 pub fn write_cr2(&mut self, address: u32, value: u8) {
659 let buffer = [value; 1];
660 let transaction: TransferConfig = TransferConfig {
661 iwidth: XspiWidth::SING,
662 isize: AddressSize::_8bit,
663 instruction: Some(SpiCommand::WriteConfigurationRegister2 as u32),
664 adsize: AddressSize::_32bit,
665 adwidth: XspiWidth::SING,
666 dwidth: XspiWidth::SING,
667 address: Some(address),
668 dummy: DummyCycles::_0,
669 ..Default::default()
670 };
430 self.xspi.blocking_write(&buffer, transaction).unwrap(); 671 self.xspi.blocking_write(&buffer, transaction).unwrap();
672 self.wait_write_finish();
673 }
674}
675
676impl<I: Instance> OpiFlashMemory<I> {
677 pub fn into_spi(mut self) -> SpiFlashMemory<I> {
678 self.disable_opi_mode();
679 SpiFlashMemory { xspi: self.xspi }
680 }
681
682 /// Disable OPI mode and return to SPI
683 pub fn disable_opi_mode(&mut self) {
684 // Clear SOPI and DOPI bits in CR2 volatile register
685 let cr2_0 = self.read_cr2(0x00000000);
686 self.write_cr2(0x00000000, cr2_0 & 0xFC); // Clear bits 0 and 1
687 }
688
689 /// Enable memory-mapped mode for OPI
690 pub fn enable_mm(&mut self) {
691 let read_config = TransferConfig {
692 iwidth: XspiWidth::OCTO,
693 isize: AddressSize::_16bit, // 2-byte command for OPI
694 adwidth: XspiWidth::OCTO,
695 adsize: AddressSize::_32bit,
696 dwidth: XspiWidth::OCTO,
697 instruction: Some(OpiCommand::OctaRead as u32),
698 dummy: DummyCycles::_20, // Default dummy cycles for OPI
699 ..Default::default()
700 };
701
702 let write_config = TransferConfig {
703 iwidth: XspiWidth::OCTO,
704 isize: AddressSize::_16bit,
705 adwidth: XspiWidth::OCTO,
706 adsize: AddressSize::_32bit,
707 dwidth: XspiWidth::OCTO,
708 instruction: Some(OpiCommand::PageProgram4B as u32),
709 dummy: DummyCycles::_0,
710 ..Default::default()
711 };
712
713 self.xspi.enable_memory_mapped_mode(read_config, write_config).unwrap();
714 }
715
716 pub fn disable_mm(&mut self) {
717 self.xspi.disable_memory_mapped_mode();
718 }
719
720 /// Execute OPI command (2-byte command)
721 fn exec_command(&mut self, cmd: OpiCommand) {
722 let transaction = TransferConfig {
723 iwidth: XspiWidth::OCTO,
724 isize: AddressSize::_16bit, // 2-byte command
725 adwidth: XspiWidth::NONE,
726 dwidth: XspiWidth::NONE,
727 instruction: Some(cmd as u32),
728 address: None,
729 dummy: DummyCycles::_0,
730 ..Default::default()
731 };
732 self.xspi.blocking_command(&transaction).unwrap();
733 }
734
735 /// Reset memory using OPI commands
736 pub fn reset_memory(&mut self) {
737 self.exec_command(OpiCommand::ResetEnable);
738 self.exec_command(OpiCommand::ResetMemory);
739 self.wait_write_finish();
431 } 740 }
432 741
742 /// Enable write using OPI command
743 pub fn enable_write(&mut self) {
744 self.exec_command(OpiCommand::WriteEnable);
745 }
746
747 /// Read device ID in OPI mode
748 pub fn read_id(&mut self) -> [u8; 3] {
749 let mut buffer = [0; 3];
750 let transaction = TransferConfig {
751 iwidth: XspiWidth::OCTO,
752 isize: AddressSize::_16bit,
753 adwidth: XspiWidth::OCTO,
754 adsize: AddressSize::_32bit,
755 dwidth: XspiWidth::OCTO,
756 instruction: Some(OpiCommand::ReadIdentification as u32),
757 address: Some(0x00000000), // Dummy address required
758 dummy: DummyCycles::_4,
759 ..Default::default()
760 };
761 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
762 buffer
763 }
764
765 /// Read memory using OPI mode
766 pub fn read_memory(&mut self, addr: u32, buffer: &mut [u8]) {
767 let transaction = TransferConfig {
768 iwidth: XspiWidth::OCTO,
769 isize: AddressSize::_16bit,
770 adwidth: XspiWidth::OCTO,
771 adsize: AddressSize::_32bit,
772 dwidth: XspiWidth::OCTO,
773 instruction: Some(OpiCommand::OctaRead as u32),
774 address: Some(addr),
775 dummy: DummyCycles::_20, // Default for 200MHz operation
776 ..Default::default()
777 };
778 self.xspi.blocking_read(buffer, transaction).unwrap();
779 }
780
781 /// Wait for write completion using OPI status read
782 fn wait_write_finish(&mut self) {
783 while (self.read_sr() & 0x01) != 0 {}
784 }
785
786 /// Perform erase operation using OPI command
787 fn perform_erase(&mut self, addr: u32, cmd: OpiCommand) {
788 let transaction = TransferConfig {
789 iwidth: XspiWidth::OCTO,
790 isize: AddressSize::_16bit,
791 adwidth: XspiWidth::OCTO,
792 adsize: AddressSize::_32bit,
793 dwidth: XspiWidth::NONE,
794 instruction: Some(cmd as u32),
795 address: Some(addr),
796 dummy: DummyCycles::_0,
797 ..Default::default()
798 };
799 self.enable_write();
800 self.xspi.blocking_command(&transaction).unwrap();
801 self.wait_write_finish();
802 }
803
804 /// Erase 4KB sector using OPI
805 pub fn erase_sector(&mut self, addr: u32) {
806 self.perform_erase(addr, OpiCommand::SectorErase4B);
807 }
808
809 /// Erase 64KB block using OPI
810 pub fn erase_block_64k(&mut self, addr: u32) {
811 self.perform_erase(addr, OpiCommand::BlockErase4B);
812 }
813
814 /// Erase entire chip using OPI
815 pub fn erase_chip(&mut self) {
816 self.enable_write();
817 self.exec_command(OpiCommand::ChipErase);
818 self.wait_write_finish();
819 }
820
821 /// Write single page using OPI
822 fn write_page(&mut self, addr: u32, buffer: &[u8], len: usize) {
823 assert!(
824 (len as u32 + (addr & 0x000000ff)) <= MEMORY_PAGE_SIZE as u32,
825 "write_page(): page write length exceeds page boundary (len = {}, addr = {:X})",
826 len,
827 addr
828 );
829
830 let transaction = TransferConfig {
831 iwidth: XspiWidth::OCTO,
832 isize: AddressSize::_16bit,
833 adwidth: XspiWidth::OCTO,
834 adsize: AddressSize::_32bit,
835 dwidth: XspiWidth::OCTO,
836 instruction: Some(OpiCommand::PageProgram4B as u32),
837 address: Some(addr),
838 dummy: DummyCycles::_0,
839 ..Default::default()
840 };
841 self.enable_write();
842 self.xspi.blocking_write(buffer, transaction).unwrap();
843 self.wait_write_finish();
844 }
845
846 /// Write memory using OPI (handles page boundaries)
847 pub fn write_memory(&mut self, addr: u32, buffer: &[u8]) {
848 let mut left = buffer.len();
849 let mut place = addr;
850 let mut chunk_start = 0;
851
852 while left > 0 {
853 let max_chunk_size = MEMORY_PAGE_SIZE - (place & 0x000000ff) as usize;
854 let chunk_size = min(max_chunk_size, left);
855 let chunk = &buffer[chunk_start..(chunk_start + chunk_size)];
856 self.write_page(place, chunk, chunk_size);
857 place += chunk_size as u32;
858 left -= chunk_size;
859 chunk_start += chunk_size;
860 }
861 }
862
863 /// Read register using OPI mode
864 fn read_register(&mut self, cmd: OpiCommand, dummy_addr: u32, dummy_cycles: DummyCycles) -> u8 {
865 let mut buffer = [0; 1];
866 let transaction = TransferConfig {
867 iwidth: XspiWidth::OCTO,
868 isize: AddressSize::_16bit,
869 adwidth: XspiWidth::OCTO,
870 adsize: AddressSize::_32bit,
871 dwidth: XspiWidth::OCTO,
872 instruction: Some(cmd as u32),
873 address: Some(dummy_addr),
874 dummy: dummy_cycles,
875 ..Default::default()
876 };
877 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
878 buffer[0]
879 }
880
881 /// Read Status Register using OPI
433 pub fn read_sr(&mut self) -> u8 { 882 pub fn read_sr(&mut self) -> u8 {
434 self.read_register(CMD_READ_SR) 883 self.read_register(
884 OpiCommand::ReadStatusRegister,
885 0x00000000, // Dummy address
886 DummyCycles::_4,
887 )
435 } 888 }
436 889
890 /// Read Configuration Register using OPI
437 pub fn read_cr(&mut self) -> u8 { 891 pub fn read_cr(&mut self) -> u8 {
438 self.read_register(CMD_READ_CR) 892 self.read_register(
893 OpiCommand::ReadConfigurationRegister,
894 0x00000001, // Address for CR
895 DummyCycles::_4,
896 )
439 } 897 }
440 898
441 pub fn write_sr(&mut self, value: u8) { 899 /// Write Status/Configuration Register using OPI
442 self.write_register(CMD_WRITE_SR, value); 900 pub fn write_sr_cr(&mut self, sr: u8, cr: u8) {
901 let transaction = TransferConfig {
902 iwidth: XspiWidth::OCTO,
903 isize: AddressSize::_16bit,
904 adwidth: XspiWidth::OCTO,
905 adsize: AddressSize::_32bit,
906 dwidth: XspiWidth::OCTO,
907 instruction: Some(OpiCommand::WriteStatusConfigurationRegister as u32),
908 address: Some(0x00000000),
909 dummy: DummyCycles::_0,
910 ..Default::default()
911 };
912
913 self.enable_write();
914 self.xspi.blocking_write(&[sr, cr], transaction).unwrap();
915 self.wait_write_finish();
916 }
917
918 /// Read Configuration Register 2 using OPI
919 pub fn read_cr2(&mut self, address: u32) -> u8 {
920 let mut buffer = [0; 1];
921 let transaction = TransferConfig {
922 iwidth: XspiWidth::OCTO,
923 isize: AddressSize::_16bit,
924 adwidth: XspiWidth::OCTO,
925 adsize: AddressSize::_32bit,
926 dwidth: XspiWidth::OCTO,
927 instruction: Some(OpiCommand::ReadConfigurationRegister2 as u32),
928 address: Some(address),
929 dummy: DummyCycles::_4,
930 ..Default::default()
931 };
932 self.xspi.blocking_read(&mut buffer, transaction).unwrap();
933 buffer[0]
443 } 934 }
444 935
445 pub fn write_cr(&mut self, value: u8) { 936 /// Write Configuration Register 2 using OPI
446 self.write_register(CMD_WRITE_CR, value); 937 pub fn write_cr2(&mut self, address: u32, value: u8) {
938 let transaction = TransferConfig {
939 iwidth: XspiWidth::OCTO,
940 isize: AddressSize::_16bit,
941 adwidth: XspiWidth::OCTO,
942 adsize: AddressSize::_32bit,
943 dwidth: XspiWidth::OCTO,
944 instruction: Some(OpiCommand::WriteConfigurationRegister2 as u32),
945 address: Some(address),
946 dummy: DummyCycles::_0,
947 ..Default::default()
948 };
949
950 self.enable_write();
951 self.xspi.blocking_write(&[value], transaction).unwrap();
952 self.wait_write_finish();
447 } 953 }
448} 954}
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 189b0e8d4..d42cdac15 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -3,16 +3,19 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32l072cz to your chip name, if necessary. 9# Change stm32l072cz to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32l073rz", "unstable-pac", "time-driver-any", "exti", "memory-x"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
13 16
14defmt = "0.3" 17defmt = "1.0.1"
15defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
16 19
17embedded-storage = "0.3.1" 20embedded-storage = "0.3.1"
18embedded-io = { version = "0.6.0" } 21embedded-io = { version = "0.6.0" }
@@ -20,7 +23,7 @@ embedded-io-async = { version = "0.6.1" }
20 23
21cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
22cortex-m-rt = "0.7.0" 25cortex-m-rt = "0.7.0"
23panic-probe = { version = "0.3", features = ["print-defmt"] } 26panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24heapless = { version = "0.8", default-features = false } 27heapless = { version = "0.8", default-features = false }
25embedded-hal = "0.2.6" 28embedded-hal = "0.2.6"
26static_cell = { version = "2" } 29static_cell = { version = "2" }
@@ -28,3 +31,8 @@ portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
28 31
29[profile.release] 32[profile.release]
30debug = 2 33debug = 2
34
35[package.metadata.embassy]
36build = [
37 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32l0" }
38]
diff --git a/examples/stm32l0/src/bin/dds.rs b/examples/stm32l0/src/bin/dds.rs
index a54b28a93..eaa7a61a8 100644
--- a/examples/stm32l0/src/bin/dds.rs
+++ b/examples/stm32l0/src/bin/dds.rs
@@ -11,7 +11,7 @@ use embassy_stm32::rcc::*;
11use embassy_stm32::time::hz; 11use 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::Channel; 14use embassy_stm32::timer::{Ch3, Channel};
15use embassy_stm32::{interrupt, pac, Config}; 15use embassy_stm32::{interrupt, pac, Config};
16use panic_probe as _; 16use panic_probe as _;
17 17
@@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) {
70 let p = embassy_stm32::init(config); 70 let p = embassy_stm32::init(config);
71 71
72 // setup PWM pin in AF mode 72 // setup PWM pin in AF mode
73 let _ch3 = PwmPin::new_ch3(p.PA2, OutputType::PushPull); 73 let _ch3 = PwmPin::<_, Ch3>::new(p.PA2, OutputType::PushPull);
74 74
75 // initialize timer 75 // initialize timer
76 // we cannot use SimplePWM here because the Time is privately encapsulated 76 // we cannot use SimplePWM here because the Time is privately encapsulated
diff --git a/examples/stm32l0/src/bin/eeprom.rs b/examples/stm32l0/src/bin/eeprom.rs
new file mode 100644
index 000000000..370246644
--- /dev/null
+++ b/examples/stm32l0/src/bin/eeprom.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_stm32::init(Default::default());
12
13 info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE);
14
15 const ADDR: u32 = 0x0;
16
17 let mut f = Flash::new_blocking(p.FLASH);
18
19 info!("Reading...");
20 let mut buf = [0u8; 8];
21 unwrap!(f.eeprom_read_slice(ADDR, &mut buf));
22 info!("Read: {=[u8]:x}", buf);
23
24 info!("Writing...");
25 unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8]));
26
27 info!("Reading...");
28 let mut buf = [0u8; 8];
29 unwrap!(f.eeprom_read_slice(ADDR, &mut buf));
30 info!("Read: {=[u8]:x}", buf);
31 assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]);
32}
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs
index 29c7e0dc7..6385e3c8f 100644
--- a/examples/stm32l0/src/bin/raw_spawn.rs
+++ b/examples/stm32l0/src/bin/raw_spawn.rs
@@ -42,8 +42,8 @@ fn main() -> ! {
42 let run2_task = unsafe { make_static(&run2_task) }; 42 let run2_task = unsafe { make_static(&run2_task) };
43 43
44 executor.run(|spawner| { 44 executor.run(|spawner| {
45 unwrap!(spawner.spawn(run1_task.spawn(|| run1()))); 45 spawner.spawn(unwrap!(run1_task.spawn(|| run1())));
46 unwrap!(spawner.spawn(run2_task.spawn(|| run2()))); 46 spawner.spawn(unwrap!(run2_task.spawn(|| run2())));
47 }); 47 });
48} 48}
49 49
diff --git a/examples/stm32l0/src/bin/usb_serial.rs b/examples/stm32l0/src/bin/usb_serial.rs
new file mode 100644
index 000000000..fdb1aeb59
--- /dev/null
+++ b/examples/stm32l0/src/bin/usb_serial.rs
@@ -0,0 +1,95 @@
1#![no_std]
2#![no_main]
3
4use defmt::{panic, *};
5use embassy_executor::Spawner;
6use embassy_futures::join::join;
7use embassy_stm32::usb::{self, Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 USB => usb::InterruptHandler<peripherals::USB>;
16});
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 let mut config = embassy_stm32::Config::default();
21 {
22 use embassy_stm32::rcc::*;
23 config.rcc.hsi = true;
24 config.rcc.pll = Some(Pll {
25 source: PllSource::HSI,
26 mul: PllMul::MUL6, // PLLVCO = 16*6 = 96Mhz
27 div: PllDiv::DIV3, // 32Mhz clock (16 * 6 / 3)
28 });
29 config.rcc.sys = Sysclk::PLL1_R;
30 }
31
32 let p = embassy_stm32::init(config);
33
34 info!("Hello World!");
35
36 let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
37
38 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
39 config.manufacturer = Some("Embassy");
40 config.product = Some("USB-Serial Example");
41 config.serial_number = Some("123456");
42
43 let mut config_descriptor = [0; 256];
44 let mut bos_descriptor = [0; 256];
45 let mut control_buf = [0; 64];
46
47 let mut state = State::new();
48
49 let mut builder = Builder::new(
50 driver,
51 config,
52 &mut config_descriptor,
53 &mut bos_descriptor,
54 &mut [], // no msos descriptors
55 &mut control_buf,
56 );
57
58 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
59
60 let mut usb = builder.build();
61
62 let usb_fut = usb.run();
63
64 let echo_fut = async {
65 loop {
66 class.wait_connection().await;
67 info!("Connected");
68 let _ = echo(&mut class).await;
69 info!("Disconnected");
70 }
71 };
72
73 join(usb_fut, echo_fut).await;
74}
75
76struct Disconnected {}
77
78impl From<EndpointError> for Disconnected {
79 fn from(val: EndpointError) -> Self {
80 match val {
81 EndpointError::BufferOverflow => panic!("Buffer overflow"),
82 EndpointError::Disabled => Disconnected {},
83 }
84 }
85}
86
87async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
88 let mut buf = [0; 64];
89 loop {
90 let n = class.read_packet(&mut buf).await?;
91 let data = &buf[..n];
92 info!("data: {:x}", data);
93 class.write_packet(data).await?;
94 }
95}
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index 6066b6dc7..76ceade9c 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -3,24 +3,30 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 9embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 10embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
10embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } 12embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
12embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 13embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 14embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17 18
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
20embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
21panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22heapless = { version = "0.8", default-features = false } 23heapless = { version = "0.8", default-features = false }
23embedded-storage = "0.3.1" 24embedded-storage = "0.3.1"
24 25
25[profile.release] 26[profile.release]
26debug = 2 27debug = 2
28
29[package.metadata.embassy]
30build = [
31 { target = "thumbv7m-none-eabi", artifact-dir = "out/examples/stm32l1" }
32]
diff --git a/examples/stm32l1/src/bin/eeprom.rs b/examples/stm32l1/src/bin/eeprom.rs
new file mode 100644
index 000000000..370246644
--- /dev/null
+++ b/examples/stm32l1/src/bin/eeprom.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_stm32::flash::{Flash, EEPROM_BASE, EEPROM_SIZE};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async fn main(_spawner: Spawner) {
11 let p = embassy_stm32::init(Default::default());
12
13 info!("Hello Eeprom! Start: {}, Size: {}", EEPROM_BASE, EEPROM_SIZE);
14
15 const ADDR: u32 = 0x0;
16
17 let mut f = Flash::new_blocking(p.FLASH);
18
19 info!("Reading...");
20 let mut buf = [0u8; 8];
21 unwrap!(f.eeprom_read_slice(ADDR, &mut buf));
22 info!("Read: {=[u8]:x}", buf);
23
24 info!("Writing...");
25 unwrap!(f.eeprom_write_slice(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8]));
26
27 info!("Reading...");
28 let mut buf = [0u8; 8];
29 unwrap!(f.eeprom_read_slice(ADDR, &mut buf));
30 info!("Read: {=[u8]:x}", buf);
31 assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]);
32}
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 239bfcd79..1b7f15b1d 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32l4s5vi to your chip name, if necessary. 9# Change stm32l4s5vi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l4r5zi", "memory-x", "time-driver-any", "exti", "chrono", "dual-bank"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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", ] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
14embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net-adin1110 = { version = "0.3.0", path = "../../embassy-net-adin1110" } 16embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" }
16embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } 17embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
18embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 19embedded-io-async = { version = "0.6.1", features = ["defmt-03"] }
19embedded-io = { version = "0.6.0", features = ["defmt-03"] } 20embedded-io = { version = "0.6.0", features = ["defmt-03"] }
20 21
21defmt = "0.3" 22defmt = "1.0.1"
22defmt-rtt = "0.4" 23defmt-rtt = "1.0.0"
23 24
24cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 25cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
25cortex-m-rt = "0.7.0" 26cortex-m-rt = "0.7.0"
@@ -27,13 +28,17 @@ embedded-hal = "0.2.6"
27embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 28embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
28embedded-hal-async = { version = "1.0" } 29embedded-hal-async = { version = "1.0" }
29embedded-hal-bus = { version = "0.1", features = ["async"] } 30embedded-hal-bus = { version = "0.1", features = ["async"] }
30panic-probe = { version = "0.3", features = ["print-defmt"] } 31panic-probe = { version = "1.0.0", features = ["print-defmt"] }
31heapless = { version = "0.8", default-features = false } 32heapless = { version = "0.8", default-features = false }
32chrono = { version = "^0.4", default-features = false } 33chrono = { version = "^0.4", default-features = false }
33rand = { version = "0.8.5", default-features = false }
34static_cell = "2" 34static_cell = "2"
35 35
36micromath = "2.0.0" 36micromath = "2.0.0"
37 37
38[profile.release] 38[profile.release]
39debug = 2 39debug = 2
40
41[package.metadata.embassy]
42build = [
43 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l4" }
44]
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index cde24f411..44edec728 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -24,8 +24,8 @@ async fn main(spawner: Spawner) {
24 // Obtain two independent channels (p.DAC1 can only be consumed once, though!) 24 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
25 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); 25 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
26 26
27 spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); 27 spawner.spawn(dac_task1(p.TIM6, dac_ch1).unwrap());
28 spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); 28 spawner.spawn(dac_task2(p.TIM7, dac_ch2).unwrap());
29} 29}
30 30
31#[embassy_executor::task] 31#[embassy_executor::task]
diff --git a/examples/stm32l4/src/bin/i2c.rs b/examples/stm32l4/src/bin/i2c.rs
index 2861bc091..3c42ba8f5 100644
--- a/examples/stm32l4/src/bin/i2c.rs
+++ b/examples/stm32l4/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
7use embassy_stm32::time::Hertz;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10const ADDRESS: u8 = 0x5F; 9const ADDRESS: u8 = 0x5F;
@@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F;
13#[embassy_executor::main] 12#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
16 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); 15 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default());
17 16
18 let mut data = [0u8; 1]; 17 let mut data = [0u8; 1];
19 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); 18 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
diff --git a/examples/stm32l4/src/bin/i2c_blocking_async.rs b/examples/stm32l4/src/bin/i2c_blocking_async.rs
index a014b23e0..62153bfc8 100644
--- a/examples/stm32l4/src/bin/i2c_blocking_async.rs
+++ b/examples/stm32l4/src/bin/i2c_blocking_async.rs
@@ -5,7 +5,6 @@ use defmt::*;
5use embassy_embedded_hal::adapter::BlockingAsync; 5use embassy_embedded_hal::adapter::BlockingAsync;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::i2c::I2c; 7use embassy_stm32::i2c::I2c;
8use embassy_stm32::time::Hertz;
9use embedded_hal_async::i2c::I2c as I2cTrait; 8use embedded_hal_async::i2c::I2c as I2cTrait;
10use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
11 10
@@ -15,7 +14,7 @@ const WHOAMI: u8 = 0x0F;
15#[embassy_executor::main] 14#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
18 let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); 17 let i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default());
19 let mut i2c = BlockingAsync::new(i2c); 18 let mut i2c = BlockingAsync::new(i2c);
20 19
21 let mut data = [0u8; 1]; 20 let mut data = [0u8; 1];
diff --git a/examples/stm32l4/src/bin/i2c_dma.rs b/examples/stm32l4/src/bin/i2c_dma.rs
index 794972a33..0f5690e37 100644
--- a/examples/stm32l4/src/bin/i2c_dma.rs
+++ b/examples/stm32l4/src/bin/i2c_dma.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
7use embassy_stm32::time::Hertz;
8use embassy_stm32::{bind_interrupts, i2c, peripherals}; 7use embassy_stm32::{bind_interrupts, i2c, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
@@ -19,16 +18,7 @@ bind_interrupts!(struct Irqs {
19#[embassy_executor::main] 18#[embassy_executor::main]
20async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
21 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init(Default::default());
22 let mut i2c = I2c::new( 21 let mut i2c = I2c::new(p.I2C2, p.PB10, p.PB11, Irqs, p.DMA1_CH4, p.DMA1_CH5, Default::default());
23 p.I2C2,
24 p.PB10,
25 p.PB11,
26 Irqs,
27 p.DMA1_CH4,
28 p.DMA1_CH5,
29 Hertz(100_000),
30 Default::default(),
31 );
32 22
33 let mut data = [0u8; 1]; 23 let mut data = [0u8; 1];
34 unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await); 24 unwrap!(i2c.write_read(ADDRESS, &[WHOAMI], &mut data).await);
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 4a7c01f9f..24efe526f 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -38,7 +38,6 @@ use embedded_io::Write as bWrite;
38use embedded_io_async::Write; 38use embedded_io_async::Write;
39use heapless::Vec; 39use heapless::Vec;
40use panic_probe as _; 40use panic_probe as _;
41use rand::RngCore;
42use static_cell::StaticCell; 41use static_cell::StaticCell;
43 42
44bind_interrupts!(struct Irqs { 43bind_interrupts!(struct Irqs {
@@ -60,7 +59,7 @@ pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>;
60pub type SpeInt = exti::ExtiInput<'static>; 59pub type SpeInt = exti::ExtiInput<'static>;
61pub type SpeRst = Output<'static>; 60pub type SpeRst = Output<'static>;
62pub type Adin1110T = ADIN1110<SpeSpiCs>; 61pub type Adin1110T = ADIN1110<SpeSpiCs>;
63pub type TempSensI2c = I2c<'static, Async>; 62pub type TempSensI2c = I2c<'static, Async, i2c::Master>;
64 63
65static TEMP: AtomicI32 = AtomicI32::new(0); 64static TEMP: AtomicI32 = AtomicI32::new(0);
66 65
@@ -116,7 +115,6 @@ async fn main(spawner: Spawner) {
116 Irqs, 115 Irqs,
117 dp.DMA1_CH6, 116 dp.DMA1_CH6,
118 dp.DMA1_CH7, 117 dp.DMA1_CH7,
119 Hertz(100_000),
120 I2C_Config::default(), 118 I2C_Config::default(),
121 ); 119 );
122 120
@@ -183,11 +181,11 @@ async fn main(spawner: Spawner) {
183 .await; 181 .await;
184 182
185 // Start task blink_led 183 // Start task blink_led
186 unwrap!(spawner.spawn(heartbeat_led(led_uc3_yellow))); 184 spawner.spawn(unwrap!(heartbeat_led(led_uc3_yellow)));
187 // Start task temperature measurement 185 // Start task temperature measurement
188 unwrap!(spawner.spawn(temp_task(temp_sens_i2c, led_uc4_blue))); 186 spawner.spawn(unwrap!(temp_task(temp_sens_i2c, led_uc4_blue)));
189 // Start ethernet task 187 // Start ethernet task
190 unwrap!(spawner.spawn(ethernet_task(runner))); 188 spawner.spawn(unwrap!(ethernet_task(runner)));
191 189
192 let mut rng = Rng::new(dp.RNG, Irqs); 190 let mut rng = Rng::new(dp.RNG, Irqs);
193 // Generate random seed 191 // Generate random seed
@@ -210,7 +208,7 @@ async fn main(spawner: Spawner) {
210 let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed); 208 let (stack, runner) = embassy_net::new(device, ip_cfg, RESOURCES.init(StackResources::new()), seed);
211 209
212 // Launch network task 210 // Launch network task
213 unwrap!(spawner.spawn(net_task(runner))); 211 spawner.spawn(unwrap!(net_task(runner)));
214 212
215 let cfg = wait_for_config(stack).await; 213 let cfg = wait_for_config(stack).await;
216 let local_addr = cfg.address.address(); 214 let local_addr = cfg.address.address();
diff --git a/examples/stm32l432/Cargo.toml b/examples/stm32l432/Cargo.toml
index e155b3e66..f173c651e 100644
--- a/examples/stm32l432/Cargo.toml
+++ b/examples/stm32l432/Cargo.toml
@@ -1,17 +1,18 @@
1[package] 1[package]
2edition = "2021" 2edition = "2021"
3name = "embassy-stm32l4-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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32l4s5vi to your chip name, if necessary. 9# Change stm32l4s5vi to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l432kc", "memory-x", "time-driver-any", "exti", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = [ "defmt" ] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = [ "defmt" ] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = [ "arch-cortex-m", "executor-thread", "defmt" ] }
12embassy-time = { version = "0.4.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" ] }
13defmt = "0.3" 14defmt = "1.0.1"
14defmt-rtt = "0.4" 15defmt-rtt = "1.0.0"
15 16
16cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 17cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
17cortex-m-rt = "0.7.0" 18cortex-m-rt = "0.7.0"
@@ -19,7 +20,7 @@ embedded-hal = "0.2.6"
19embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 20embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
20embedded-hal-async = { version = "1.0" } 21embedded-hal-async = { version = "1.0" }
21embedded-hal-bus = { version = "0.1", features = ["async"] } 22embedded-hal-bus = { version = "0.1", features = ["async"] }
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23 24
24[profile.release] 25[profile.release]
25debug = 2 26debug = 2
@@ -28,3 +29,8 @@ debug = 2
28name = "qspi_mmap" 29name = "qspi_mmap"
29path = "src/bin/qspi_mmap.rs" 30path = "src/bin/qspi_mmap.rs"
30test = false 31test = false
32
33[package.metadata.embassy]
34build = [
35 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32l432" }
36]
diff --git a/examples/stm32l432/src/bin/qspi_mmap.rs b/examples/stm32l432/src/bin/qspi_mmap.rs
index 86a20eb3d..feabdd532 100644
--- a/examples/stm32l432/src/bin/qspi_mmap.rs
+++ b/examples/stm32l432/src/bin/qspi_mmap.rs
@@ -7,7 +7,7 @@
7use defmt::info; 7use defmt::info;
8use embassy_stm32::mode; 8use embassy_stm32::mode;
9use embassy_stm32::qspi::enums::{ 9use embassy_stm32::qspi::enums::{
10 AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, 10 AddressSize, ChipSelectHighTime, DummyCycles, FIFOThresholdLevel, MemorySize, QspiWidth, SampleShifting,
11}; 11};
12use embassy_stm32::qspi::{self, Instance, TransferConfig}; 12use embassy_stm32::qspi::{self, Instance, TransferConfig};
13pub struct FlashMemory<I: Instance> { 13pub struct FlashMemory<I: Instance> {
@@ -246,13 +246,14 @@ const MEMORY_ADDR: u32 = 0x00000000 as u32;
246async fn main(_spawner: Spawner) { 246async fn main(_spawner: Spawner) {
247 let p = embassy_stm32::init(Default::default()); 247 let p = embassy_stm32::init(Default::default());
248 248
249 let config = qspi::Config { 249 let mut config = qspi::Config::default();
250 memory_size: MemorySize::_16MiB, 250 config.memory_size = MemorySize::_16MiB;
251 address_size: AddressSize::_24bit, 251 config.address_size = AddressSize::_24bit;
252 prescaler: 200, 252 config.prescaler = 200;
253 cs_high_time: ChipSelectHighTime::_1Cycle, 253 config.cs_high_time = ChipSelectHighTime::_1Cycle;
254 fifo_threshold: FIFOThresholdLevel::_16Bytes, 254 config.fifo_threshold = FIFOThresholdLevel::_16Bytes;
255 }; 255 config.sample_shifting = SampleShifting::None;
256
256 let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config); 257 let driver = qspi::Qspi::new_bank1(p.QUADSPI, p.PB1, p.PB0, p.PA7, p.PA6, p.PA3, p.PA2, p.DMA2_CH7, config);
257 let mut flash = FlashMemory::new(driver); 258 let mut flash = FlashMemory::new(driver);
258 let mut wr_buf = [0u8; 256]; 259 let mut wr_buf = [0u8; 256];
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 4c372a554..9999300b8 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -3,27 +3,27 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32l552ze to your chip name, if necessary. 9# Change stm32l552ze to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "memory-x", "low-power", "dual-bank"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
15embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
16usbd-hid = "0.8.1" 17usbd-hid = "0.8.1"
17 18
18defmt = "0.3" 19defmt = "1.0.1"
19defmt-rtt = "0.4" 20defmt-rtt = "1.0.0"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21 22
22cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 23cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
23cortex-m-rt = "0.7.0" 24cortex-m-rt = "0.7.0"
24embedded-hal = "0.2.6" 25embedded-hal = "0.2.6"
25heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
26rand_core = { version = "0.6.3", default-features = false }
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.6.1" }
28static_cell = "2" 28static_cell = "2"
29 29
@@ -33,3 +33,8 @@ debug = 2
33[[bin]] 33[[bin]]
34name = "stop" 34name = "stop"
35default-features = ["embassy-stm32/low-power"] 35default-features = ["embassy-stm32/low-power"]
36
37[package.metadata.embassy]
38build = [
39 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32l5" }
40]
diff --git a/examples/stm32l5/src/bin/stop.rs b/examples/stm32l5/src/bin/stop.rs
index d7a1efea9..c34053190 100644
--- a/examples/stm32l5/src/bin/stop.rs
+++ b/examples/stm32l5/src/bin/stop.rs
@@ -15,7 +15,7 @@ use {defmt_rtt as _, panic_probe as _};
15#[cortex_m_rt::entry] 15#[cortex_m_rt::entry]
16fn main() -> ! { 16fn main() -> ! {
17 Executor::take().run(|spawner| { 17 Executor::take().run(|spawner| {
18 unwrap!(spawner.spawn(async_main(spawner))); 18 spawner.spawn(unwrap!(async_main(spawner)));
19 }) 19 })
20} 20}
21 21
@@ -34,8 +34,8 @@ async fn async_main(spawner: Spawner) {
34 let rtc = RTC.init(rtc); 34 let rtc = RTC.init(rtc);
35 embassy_stm32::low_power::stop_with_rtc(rtc); 35 embassy_stm32::low_power::stop_with_rtc(rtc);
36 36
37 unwrap!(spawner.spawn(blinky(p.PC7.into()))); 37 spawner.spawn(unwrap!(blinky(p.PC7.into())));
38 unwrap!(spawner.spawn(timeout())); 38 spawner.spawn(unwrap!(timeout()));
39} 39}
40 40
41#[embassy_executor::task] 41#[embassy_executor::task]
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 809ec6ab1..25aa9ef69 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -12,7 +12,6 @@ use 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};
14use embedded_io_async::Write; 14use embedded_io_async::Write;
15use rand_core::RngCore;
16use static_cell::StaticCell; 15use static_cell::StaticCell;
17use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
18 17
@@ -97,11 +96,11 @@ async fn main(spawner: Spawner) {
97 // Build the builder. 96 // Build the builder.
98 let usb = builder.build(); 97 let usb = builder.build();
99 98
100 unwrap!(spawner.spawn(usb_task(usb))); 99 spawner.spawn(unwrap!(usb_task(usb)));
101 100
102 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new(); 101 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
103 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr); 102 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
104 unwrap!(spawner.spawn(usb_ncm_task(runner))); 103 spawner.spawn(unwrap!(usb_ncm_task(runner)));
105 104
106 let config = embassy_net::Config::dhcpv4(Default::default()); 105 let config = embassy_net::Config::dhcpv4(Default::default());
107 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { 106 //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
@@ -118,7 +117,7 @@ async fn main(spawner: Spawner) {
118 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); 117 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
119 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); 118 let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
120 119
121 unwrap!(spawner.spawn(net_task(runner))); 120 spawner.spawn(unwrap!(net_task(runner)));
122 121
123 // And now we can use it! 122 // And now we can use it!
124 123
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml
index efcb9bf4d..9318414a5 100644
--- a/examples/stm32u0/Cargo.toml
+++ b/examples/stm32u0/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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
6 7
7[dependencies] 8[dependencies]
8# Change stm32u083rc to your chip name, if necessary. 9# Change stm32u083rc to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.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", "stm32u083rc", "memory-x", "unstable-pac", "exti", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", default-features = false, features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", default-features = false, features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24 25
25micromath = "2.0.0" 26micromath = "2.0.0"
@@ -27,3 +28,8 @@ chrono = { version = "0.4.38", default-features = false }
27 28
28[profile.release] 29[profile.release]
29debug = 2 30debug = 2
31
32[package.metadata.embassy]
33build = [
34 { target = "thumbv6m-none-eabi", artifact-dir = "out/examples/stm32u0" }
35]
diff --git a/examples/stm32u0/src/bin/i2c.rs b/examples/stm32u0/src/bin/i2c.rs
index 2861bc091..3c42ba8f5 100644
--- a/examples/stm32u0/src/bin/i2c.rs
+++ b/examples/stm32u0/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
7use embassy_stm32::time::Hertz;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10const ADDRESS: u8 = 0x5F; 9const ADDRESS: u8 = 0x5F;
@@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F;
13#[embassy_executor::main] 12#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
16 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Hertz(100_000), Default::default()); 15 let mut i2c = I2c::new_blocking(p.I2C2, p.PB10, p.PB11, Default::default());
17 16
18 let mut data = [0u8; 1]; 17 let mut data = [0u8; 1];
19 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data)); 18 unwrap!(i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data));
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index 886c5cb2e..f2ffe52c5 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32u5g9zj to your chip name, if necessary. 9# Change stm32u5g9zj to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "unstable-pac", "stm32u5g9zj", "time-driver-any", "memory-x" ] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-usb = { version = "0.4.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 15embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24embedded-graphics = { version = "0.8.1" } 25embedded-graphics = { version = "0.8.1" }
25tinybmp = { version = "0.6.0" } 26tinybmp = { version = "0.6.0" }
@@ -32,3 +33,8 @@ trustzone-secure = ["embassy-stm32/trustzone-secure"]
32 33
33[profile.release] 34[profile.release]
34debug = 2 35debug = 2
36
37[package.metadata.embassy]
38build = [
39 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32u5" }
40]
diff --git a/examples/stm32u5/src/bin/i2c.rs b/examples/stm32u5/src/bin/i2c.rs
index d5f5d6f60..5577f7211 100644
--- a/examples/stm32u5/src/bin/i2c.rs
+++ b/examples/stm32u5/src/bin/i2c.rs
@@ -4,7 +4,6 @@
4use defmt::{info, unwrap}; 4use defmt::{info, unwrap};
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::i2c::I2c; 6use embassy_stm32::i2c::I2c;
7use embassy_stm32::time::Hertz;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10const HTS221_ADDRESS: u8 = 0x5F; 9const HTS221_ADDRESS: u8 = 0x5F;
@@ -13,7 +12,7 @@ const WHOAMI: u8 = 0x0F;
13#[embassy_executor::main] 12#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
15 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
16 let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Hertz(100_000), Default::default()); 15 let mut i2c = I2c::new_blocking(p.I2C2, p.PF1, p.PF0, Default::default());
17 16
18 let mut data = [0u8; 1]; 17 let mut data = [0u8; 1];
19 unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data)); 18 unwrap!(i2c.blocking_write_read(HTS221_ADDRESS, &[WHOAMI], &mut data));
diff --git a/examples/stm32u5/src/bin/ltdc.rs b/examples/stm32u5/src/bin/ltdc.rs
index bd59a9148..46d1c120f 100644
--- a/examples/stm32u5/src/bin/ltdc.rs
+++ b/examples/stm32u5/src/bin/ltdc.rs
@@ -50,7 +50,7 @@ async fn main(spawner: Spawner) {
50 50
51 // blink the led on another task 51 // blink the led on another task
52 let led = Output::new(p.PD2, Level::High, Speed::Low); 52 let led = Output::new(p.PD2, Level::High, Speed::Low);
53 unwrap!(spawner.spawn(led_task(led))); 53 spawner.spawn(unwrap!(led_task(led)));
54 54
55 // numbers from STM32U5G9J-DK2.ioc 55 // numbers from STM32U5G9J-DK2.ioc
56 const RK050HR18H_HSYNC: u16 = 5; // Horizontal synchronization 56 const RK050HR18H_HSYNC: u16 = 5; // Horizontal synchronization
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 96f66f3af..7ab13c290 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -3,23 +3,24 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32wb55rg to your chip name in both dependencies, if necessary. 9# Change stm32wb55rg to your chip name in both dependencies, if necessary.
9embassy-stm32 = { version = "0.2.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"] }
10embassy-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"] }
11embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.7.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"] }
13embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true }
15 16
16defmt = "0.3" 17defmt = "1.0.1"
17defmt-rtt = "0.4" 18defmt-rtt = "1.0.0"
18 19
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 22embedded-hal = "1.0.0"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24static_cell = "2" 25static_cell = "2"
25 26
@@ -54,3 +55,8 @@ required-features = ["ble"]
54 55
55[profile.release] 56[profile.release]
56debug = 2 57debug = 2
58
59[package.metadata.embassy]
60build = [
61 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wb" }
62]
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs
index 041dc0cf5..5d927bc00 100644
--- a/examples/stm32wb/src/bin/gatt_server.rs
+++ b/examples/stm32wb/src/bin/gatt_server.rs
@@ -27,6 +27,7 @@ use embassy_stm32_wpan::hci::vendor::event::{self, AttributeHandle, VendorEvent}
27use embassy_stm32_wpan::hci::{BdAddr, Event}; 27use embassy_stm32_wpan::hci::{BdAddr, Event};
28use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; 28use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp;
29use embassy_stm32_wpan::sub::ble::Ble; 29use embassy_stm32_wpan::sub::ble::Ble;
30use embassy_stm32_wpan::sub::mm;
30use embassy_stm32_wpan::TlMbox; 31use embassy_stm32_wpan::TlMbox;
31use {defmt_rtt as _, panic_probe as _}; 32use {defmt_rtt as _, panic_probe as _};
32 33
@@ -38,7 +39,7 @@ bind_interrupts!(struct Irqs{
38const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; 39const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7;
39 40
40#[embassy_executor::main] 41#[embassy_executor::main]
41async fn main(_spawner: Spawner) { 42async fn main(spawner: Spawner) {
42 /* 43 /*
43 How to make this work: 44 How to make this work:
44 45
@@ -70,6 +71,7 @@ async fn main(_spawner: Spawner) {
70 let config = Config::default(); 71 let config = Config::default();
71 let mut mbox = TlMbox::init(p.IPCC, Irqs, config); 72 let mut mbox = TlMbox::init(p.IPCC, Irqs, config);
72 73
74 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
73 let sys_event = mbox.sys_subsystem.read().await; 75 let sys_event = mbox.sys_subsystem.read().await;
74 info!("sys event: {}", sys_event.payload()); 76 info!("sys event: {}", sys_event.payload());
75 77
@@ -221,6 +223,11 @@ async fn main(_spawner: Spawner) {
221 } 223 }
222} 224}
223 225
226#[embassy_executor::task]
227async fn run_mm_queue(memory_manager: mm::MemoryManager) {
228 memory_manager.run_queue().await;
229}
230
224fn get_bd_addr() -> BdAddr { 231fn get_bd_addr() -> BdAddr {
225 let mut bytes = [0u8; 6]; 232 let mut bytes = [0u8; 6];
226 233
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index d139aa61b..ede6cf4b9 100644
--- a/examples/stm32wb/src/bin/mac_ffd.rs
+++ b/examples/stm32wb/src/bin/mac_ffd.rs
@@ -56,7 +56,7 @@ async fn main(spawner: Spawner) {
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);
58 58
59 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); 59 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
60 60
61 let sys_event = mbox.sys_subsystem.read().await; 61 let sys_event = mbox.sys_subsystem.read().await;
62 info!("sys event: {}", sys_event.payload()); 62 info!("sys event: {}", sys_event.payload());
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index 6a97daf4d..cc3b21e2e 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -62,7 +62,7 @@ async fn main(spawner: Spawner) {
62 let config = Config::default(); 62 let config = Config::default();
63 let mbox = TlMbox::init(p.IPCC, Irqs, config); 63 let mbox = TlMbox::init(p.IPCC, Irqs, config);
64 64
65 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); 65 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
66 66
67 let sys_event = mbox.sys_subsystem.read().await; 67 let sys_event = mbox.sys_subsystem.read().await;
68 info!("sys event: {}", sys_event.payload()); 68 info!("sys event: {}", sys_event.payload());
@@ -168,7 +168,7 @@ async fn main(spawner: Spawner) {
168 static RUNNER: StaticCell<Runner> = StaticCell::new(); 168 static RUNNER: StaticCell<Runner> = StaticCell::new();
169 let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue)); 169 let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue));
170 170
171 spawner.spawn(run_mac(runner)).unwrap(); 171 spawner.spawn(run_mac(runner).unwrap());
172 172
173 let (driver, control) = mac::new(runner).await; 173 let (driver, control) = mac::new(runner).await;
174 174
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index 9062bdcd2..d872104a8 100644
--- a/examples/stm32wb/src/bin/mac_rfd.rs
+++ b/examples/stm32wb/src/bin/mac_rfd.rs
@@ -58,7 +58,7 @@ async fn main(spawner: Spawner) {
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);
60 60
61 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); 61 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
62 62
63 let sys_event = mbox.sys_subsystem.read().await; 63 let sys_event = mbox.sys_subsystem.read().await;
64 info!("sys event: {}", sys_event.payload()); 64 info!("sys event: {}", sys_event.payload());
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
index 9224e626d..95c73872b 100644
--- a/examples/stm32wb/src/bin/tl_mbox_mac.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -53,7 +53,7 @@ async fn main(spawner: Spawner) {
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);
55 55
56 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); 56 spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap());
57 57
58 let sys_event = mbox.sys_subsystem.read().await; 58 let sys_event = mbox.sys_subsystem.read().await;
59 info!("sys event: {}", sys_event.payload()); 59 info!("sys event: {}", sys_event.payload());
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml
index 60b09adb4..e1196614a 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -3,23 +3,29 @@ edition = "2021"
3name = "embassy-stm32wba-examples" 3name = "embassy-stm32wba-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6publish = false
6 7
7[dependencies] 8[dependencies]
8embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] } 9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba55cg", "time-driver-any", "memory-x", "exti"] }
9embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
11embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
12embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional=true } 13embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true }
13 14
14defmt = "0.3" 15defmt = "1.0.1"
15defmt-rtt = "0.4" 16defmt-rtt = "1.0.0"
16 17
17cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
18cortex-m-rt = "0.7.0" 19cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6" 20embedded-hal = "1.0.0"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
21heapless = { version = "0.8", default-features = false } 22heapless = { version = "0.8", default-features = false }
22static_cell = "2" 23static_cell = "2"
23 24
24[profile.release] 25[profile.release]
25debug = 2 26debug = 2
27
28[package.metadata.embassy]
29build = [
30 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba" }
31]
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs
new file mode 100644
index 000000000..a9651d57e
--- /dev/null
+++ b/examples/stm32wba/src/bin/adc.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_stm32::adc::{adc4, AdcChannel};
6use {defmt_rtt as _, panic_probe as _};
7
8#[embassy_executor::main]
9async fn main(_spawner: embassy_executor::Spawner) {
10 let config = embassy_stm32::Config::default();
11
12 let mut p = embassy_stm32::init(config);
13
14 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256);
20 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5);
21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
22
23 // **** ADC4 blocking read ****
24 let raw: u16 = adc4.blocking_read(&mut adc4_pin1);
25 let volt: f32 = 3.0 * raw as f32 / max4 as f32;
26 info!("Read adc4 pin 1 {}", volt);
27
28 let raw: u16 = adc4.blocking_read(&mut adc4_pin2);
29 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
30 info!("Read adc4 pin 2 {}", volt);
31
32 // **** ADC4 async read ****
33 let mut degraded41 = adc4_pin1.degrade_adc();
34 let mut degraded42 = adc4_pin2.degrade_adc();
35 let mut measurements = [0u16; 2];
36
37 // The channels must be in ascending order and can't repeat for ADC4
38 adc4.read(
39 p.GPDMA1_CH1.reborrow(),
40 [&mut degraded42, &mut degraded41].into_iter(),
41 &mut measurements,
42 )
43 .await
44 .unwrap();
45 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;
47 info!("Async read 4 pin 1 {}", volt1);
48 info!("Async read 4 pin 2 {}", volt2);
49}
diff --git a/examples/stm32wba/src/bin/pwm.rs b/examples/stm32wba/src/bin/pwm.rs
new file mode 100644
index 000000000..de690fda0
--- /dev/null
+++ b/examples/stm32wba/src/bin/pwm.rs
@@ -0,0 +1,65 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner;
7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::rcc::{
9 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
10};
11use embassy_stm32::time::khz;
12use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
13use embassy_stm32::Config;
14use embassy_time::Timer;
15use panic_probe as _;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 info!("Hello World!");
20
21 let mut config = Config::default();
22 // Fine-tune PLL1 dividers/multipliers
23 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
24 source: PllSource::HSI,
25 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
26 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
27 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
28 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
29 divq: None,
30 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
31 frac: Some(0), // Fractional part (enabled)
32 });
33
34 config.rcc.ahb_pre = AHBPrescaler::DIV1;
35 config.rcc.apb1_pre = APBPrescaler::DIV1;
36 config.rcc.apb2_pre = APBPrescaler::DIV1;
37 config.rcc.apb7_pre = APBPrescaler::DIV1;
38 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
39
40 // voltage scale for max performance
41 config.rcc.voltage_scale = VoltageScale::RANGE1;
42 // route PLL1_P into the USB‐OTG‐HS block
43 config.rcc.sys = Sysclk::PLL1_R;
44
45 let p = embassy_stm32::init(config);
46
47 let ch1_pin = PwmPin::new(p.PB8, OutputType::PushPull);
48 let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
49 let mut ch1 = pwm.ch1();
50 ch1.enable();
51
52 info!("PWM initialized");
53 info!("PWM max duty {}", ch1.max_duty_cycle());
54
55 loop {
56 ch1.set_duty_cycle_fully_off();
57 Timer::after_millis(300).await;
58 ch1.set_duty_cycle_fraction(1, 4);
59 Timer::after_millis(300).await;
60 ch1.set_duty_cycle_fraction(1, 2);
61 Timer::after_millis(300).await;
62 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
63 Timer::after_millis(300).await;
64 }
65}
diff --git a/examples/stm32wba6/.cargo/config.toml b/examples/stm32wba6/.cargo/config.toml
new file mode 100644
index 000000000..1896068d8
--- /dev/null
+++ b/examples/stm32wba6/.cargo/config.toml
@@ -0,0 +1,8 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2runner = "probe-rs run --chip STM32WBA65RI"
3
4[build]
5target = "thumbv8m.main-none-eabihf"
6
7[env]
8DEFMT_LOG = "trace"
diff --git a/examples/stm32wba6/Cargo.toml b/examples/stm32wba6/Cargo.toml
new file mode 100644
index 000000000..f98317846
--- /dev/null
+++ b/examples/stm32wba6/Cargo.toml
@@ -0,0 +1,32 @@
1[package]
2edition = "2021"
3name = "embassy-stm32wba6-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6publish = false
7
8[dependencies]
9embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wba65ri", "time-driver-any", "memory-x", "exti"] }
10embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
14embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
15
16defmt = "1.0.1"
17defmt-rtt = "1.0.0"
18
19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
20cortex-m-rt = "0.7.0"
21embedded-hal = "1.0.0"
22panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false }
24static_cell = "2"
25
26[profile.release]
27debug = 2
28
29[package.metadata.embassy]
30build = [
31 { target = "thumbv8m.main-none-eabihf", artifact-dir = "out/examples/stm32wba6" }
32]
diff --git a/examples/stm32wba6/build.rs b/examples/stm32wba6/build.rs
new file mode 100644
index 000000000..8fc6faab8
--- /dev/null
+++ b/examples/stm32wba6/build.rs
@@ -0,0 +1,10 @@
1use std::error::Error;
2
3fn main() -> Result<(), Box<dyn Error>> {
4 println!("cargo:rerun-if-changed=link.x");
5 println!("cargo:rustc-link-arg-bins=--nmagic");
6 println!("cargo:rustc-link-arg-bins=-Tlink.x");
7 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
8
9 Ok(())
10}
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs
new file mode 100644
index 000000000..a9651d57e
--- /dev/null
+++ b/examples/stm32wba6/src/bin/adc.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_stm32::adc::{adc4, AdcChannel};
6use {defmt_rtt as _, panic_probe as _};
7
8#[embassy_executor::main]
9async fn main(_spawner: embassy_executor::Spawner) {
10 let config = embassy_stm32::Config::default();
11
12 let mut p = embassy_stm32::init(config);
13
14 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256);
20 adc4.set_sample_time(adc4::SampleTime::CYCLES1_5);
21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
22
23 // **** ADC4 blocking read ****
24 let raw: u16 = adc4.blocking_read(&mut adc4_pin1);
25 let volt: f32 = 3.0 * raw as f32 / max4 as f32;
26 info!("Read adc4 pin 1 {}", volt);
27
28 let raw: u16 = adc4.blocking_read(&mut adc4_pin2);
29 let volt: f32 = 3.3 * raw as f32 / max4 as f32;
30 info!("Read adc4 pin 2 {}", volt);
31
32 // **** ADC4 async read ****
33 let mut degraded41 = adc4_pin1.degrade_adc();
34 let mut degraded42 = adc4_pin2.degrade_adc();
35 let mut measurements = [0u16; 2];
36
37 // The channels must be in ascending order and can't repeat for ADC4
38 adc4.read(
39 p.GPDMA1_CH1.reborrow(),
40 [&mut degraded42, &mut degraded41].into_iter(),
41 &mut measurements,
42 )
43 .await
44 .unwrap();
45 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;
47 info!("Async read 4 pin 1 {}", volt1);
48 info!("Async read 4 pin 2 {}", volt2);
49}
diff --git a/examples/stm32wba6/src/bin/blinky.rs b/examples/stm32wba6/src/bin/blinky.rs
new file mode 100644
index 000000000..0d803b257
--- /dev/null
+++ b/examples/stm32wba6/src/bin/blinky.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!");
14
15 let mut led = Output::new(p.PB4, Level::High, Speed::Low);
16
17 loop {
18 info!("high");
19 led.set_high();
20 Timer::after_millis(500).await;
21
22 info!("low");
23 led.set_low();
24 Timer::after_millis(500).await;
25 }
26}
diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs
new file mode 100644
index 000000000..34a08bbc6
--- /dev/null
+++ b/examples/stm32wba6/src/bin/button_exti.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput;
7use embassy_stm32::gpio::Pull;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!");
14
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up);
16
17 info!("Press the USER button...");
18
19 loop {
20 button.wait_for_falling_edge().await;
21 info!("Pressed!");
22 button.wait_for_rising_edge().await;
23 info!("Released!");
24 }
25}
diff --git a/examples/stm32wba6/src/bin/pwm.rs b/examples/stm32wba6/src/bin/pwm.rs
new file mode 100644
index 000000000..2c696834a
--- /dev/null
+++ b/examples/stm32wba6/src/bin/pwm.rs
@@ -0,0 +1,65 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use defmt_rtt as _; // global logger
6use embassy_executor::Spawner;
7use embassy_stm32::gpio::OutputType;
8use embassy_stm32::rcc::{
9 AHB5Prescaler, AHBPrescaler, APBPrescaler, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale,
10};
11use embassy_stm32::time::khz;
12use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
13use embassy_stm32::Config;
14use embassy_time::Timer;
15use panic_probe as _;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 info!("Hello World!");
20
21 let mut config = Config::default();
22 // Fine-tune PLL1 dividers/multipliers
23 config.rcc.pll1 = Some(embassy_stm32::rcc::Pll {
24 source: PllSource::HSI,
25 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
26 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
27 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
28 // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED)
29 divq: None,
30 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG)
31 frac: Some(0), // Fractional part (enabled)
32 });
33
34 config.rcc.ahb_pre = AHBPrescaler::DIV1;
35 config.rcc.apb1_pre = APBPrescaler::DIV1;
36 config.rcc.apb2_pre = APBPrescaler::DIV1;
37 config.rcc.apb7_pre = APBPrescaler::DIV1;
38 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
39
40 // voltage scale for max performance
41 config.rcc.voltage_scale = VoltageScale::RANGE1;
42 // route PLL1_P into the USB‐OTG‐HS block
43 config.rcc.sys = Sysclk::PLL1_R;
44
45 let p = embassy_stm32::init(config);
46
47 let ch1_pin = PwmPin::new(p.PA2, OutputType::PushPull);
48 let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default());
49 let mut ch1 = pwm.ch1();
50 ch1.enable();
51
52 info!("PWM initialized");
53 info!("PWM max duty {}", ch1.max_duty_cycle());
54
55 loop {
56 ch1.set_duty_cycle_fully_off();
57 Timer::after_millis(300).await;
58 ch1.set_duty_cycle_fraction(1, 4);
59 Timer::after_millis(300).await;
60 ch1.set_duty_cycle_fraction(1, 2);
61 Timer::after_millis(300).await;
62 ch1.set_duty_cycle(ch1.max_duty_cycle() - 1);
63 Timer::after_millis(300).await;
64 }
65}
diff --git a/examples/stm32wba6/src/bin/usb_hs_serial.rs b/examples/stm32wba6/src/bin/usb_hs_serial.rs
new file mode 100644
index 000000000..20bdeaac3
--- /dev/null
+++ b/examples/stm32wba6/src/bin/usb_hs_serial.rs
@@ -0,0 +1,125 @@
1#![no_std]
2#![no_main]
3
4use defmt::{panic, *};
5use embassy_executor::Spawner;
6use embassy_futures::join::join;
7use embassy_stm32::usb::{Driver, Instance};
8use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
9use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
10use embassy_usb::driver::EndpointError;
11use embassy_usb::Builder;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 USB_OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
16});
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 info!("Hello World!");
21
22 let mut config = Config::default();
23
24 {
25 use embassy_stm32::rcc::*;
26 config.rcc.pll1 = Some(Pll {
27 source: PllSource::HSI,
28 prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz
29 mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO
30 divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk)
31 divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz
32 divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USB_OTG_HS)
33 frac: Some(0), // Fractional part (disabled)
34 });
35
36 config.rcc.ahb_pre = AHBPrescaler::DIV1;
37 config.rcc.apb1_pre = APBPrescaler::DIV1;
38 config.rcc.apb2_pre = APBPrescaler::DIV1;
39 config.rcc.apb7_pre = APBPrescaler::DIV1;
40 config.rcc.ahb5_pre = AHB5Prescaler::DIV4;
41
42 config.rcc.voltage_scale = VoltageScale::RANGE1;
43 config.rcc.mux.otghssel = mux::Otghssel::PLL1_P;
44 config.rcc.sys = Sysclk::PLL1_R;
45 }
46
47 let p = embassy_stm32::init(config);
48
49 // Create the driver, from the HAL.
50 let mut ep_out_buffer = [0u8; 256];
51 let mut config = embassy_stm32::usb::Config::default();
52 // Do not enable vbus_detection. This is a safe default that works in all boards.
53 // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need
54 // to enable vbus_detection to comply with the USB spec. If you enable it, the board
55 // has to support it or USB won't work at all. See docs on `vbus_detection` for details.
56 config.vbus_detection = false;
57 let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PD6, p.PD7, &mut ep_out_buffer, config);
58
59 // Create embassy-usb Config
60 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
61 config.manufacturer = Some("Embassy");
62 config.product = Some("USB-serial example");
63 config.serial_number = Some("12345678");
64
65 // Create embassy-usb DeviceBuilder using the driver and config.
66 // It needs some buffers for building the descriptors.
67 let mut config_descriptor = [0; 256];
68 let mut bos_descriptor = [0; 256];
69 let mut control_buf = [0; 64];
70
71 let mut state = State::new();
72
73 let mut builder = Builder::new(
74 driver,
75 config,
76 &mut config_descriptor,
77 &mut bos_descriptor,
78 &mut [], // no msos descriptors
79 &mut control_buf,
80 );
81
82 // Create classes on the builder.
83 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
84
85 // Build the builder.
86 let mut usb = builder.build();
87
88 // Run the USB device.
89 let usb_fut = usb.run();
90
91 // Do stuff with the class!
92 let echo_fut = async {
93 loop {
94 class.wait_connection().await;
95 info!("Connected");
96 let _ = echo(&mut class).await;
97 info!("Disconnected");
98 }
99 };
100
101 // Run everything concurrently.
102 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
103 join(usb_fut, echo_fut).await;
104}
105
106struct Disconnected {}
107
108impl From<EndpointError> for Disconnected {
109 fn from(val: EndpointError) -> Self {
110 match val {
111 EndpointError::BufferOverflow => panic!("Buffer overflow"),
112 EndpointError::Disabled => Disconnected {},
113 }
114 }
115}
116
117async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
118 let mut buf = [0; 64];
119 loop {
120 let n = class.read_packet(&mut buf).await?;
121 let data = &buf[..n];
122 info!("data: {:x}", data);
123 class.write_packet(data).await?;
124 }
125}
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index 6b677914e..825d25c0d 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -3,25 +3,31 @@ edition = "2021"
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"
6publish = false
6 7
7[dependencies] 8[dependencies]
8# Change stm32wl55jc-cm4 to your chip name, if necessary. 9# Change stm32wl55jc-cm4 to your chip name, if necessary.
9embassy-stm32 = { version = "0.2.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
10embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["defmt"] } 11embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
12embassy-time = { version = "0.4.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"] }
13embassy-embedded-hal = { version = "0.3.0", path = "../../embassy-embedded-hal" } 14embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal" }
14 15
15defmt = "0.3" 16defmt = "1.0.1"
16defmt-rtt = "0.4" 17defmt-rtt = "1.0.0"
17 18
18cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 19cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
20embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
21embedded-storage = "0.3.1" 22embedded-storage = "0.3.1"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 23panic-probe = { version = "1.0.0", features = ["print-defmt"] }
23heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
24chrono = { version = "^0.4", default-features = false } 25chrono = { version = "^0.4", default-features = false }
25 26
26[profile.release] 27[profile.release]
27debug = 2 28debug = 2
29
30[package.metadata.embassy]
31build = [
32 { target = "thumbv7em-none-eabi", artifact-dir = "out/examples/stm32wl" }
33]
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs
new file mode 100644
index 000000000..118f02ae1
--- /dev/null
+++ b/examples/stm32wl/src/bin/adc.rs
@@ -0,0 +1,39 @@
1#![no_std]
2#![no_main]
3
4use core::mem::MaybeUninit;
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_stm32::adc::{Adc, CkModePclk, Clock, SampleTime};
9use embassy_stm32::SharedData;
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _};
12
13static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA);
18 info!("Hello World!");
19
20 let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 });
21 adc.set_sample_time(SampleTime::CYCLES79_5);
22 let mut pin = p.PB2;
23
24 let mut vrefint = adc.enable_vrefint();
25 let vrefint_sample = adc.blocking_read(&mut vrefint);
26 let convert_to_millivolts = |sample| {
27 // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf
28 // 6.3.3 Embedded internal reference voltage
29 const VREFINT_MV: u32 = 1212; // mV
30
31 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
32 };
33
34 loop {
35 let v = adc.blocking_read(&mut pin);
36 info!("--> {} - {} mV", v, convert_to_millivolts(v));
37 Timer::after_millis(100).await;
38 }
39}
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index 3a27f913c..e8897506c 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -3,14 +3,15 @@ edition = "2021"
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"
6publish = false
6 7
7[lib] 8[lib]
8crate-type = ["cdylib"] 9crate-type = ["cdylib"]
9 10
10[dependencies] 11[dependencies]
11embassy-sync = { version = "0.6.2", path = "../../embassy-sync", features = ["log"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["log"] }
12embassy-executor = { version = "0.7.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log"] }
13embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["log", "wasm", ] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["log", "wasm", ] }
14 15
15wasm-logger = "0.2.0" 16wasm-logger = "0.2.0"
16wasm-bindgen = "0.2" 17wasm-bindgen = "0.2"
@@ -19,3 +20,8 @@ log = "0.4.11"
19 20
20[profile.release] 21[profile.release]
21debug = 2 22debug = 2
23
24[package.metadata.embassy]
25build = [
26 { target = "wasm32-unknown-unknown", artifact-dir = "out/examples/wasm" }
27]
diff --git a/examples/wasm/src/lib.rs b/examples/wasm/src/lib.rs
index 71cf980dd..170c97fb7 100644
--- a/examples/wasm/src/lib.rs
+++ b/examples/wasm/src/lib.rs
@@ -24,5 +24,5 @@ async fn ticker() {
24#[embassy_executor::main] 24#[embassy_executor::main]
25async fn main(spawner: Spawner) { 25async fn main(spawner: Spawner) {
26 wasm_logger::init(wasm_logger::Config::default()); 26 wasm_logger::init(wasm_logger::Config::default());
27 spawner.spawn(ticker()).unwrap(); 27 spawner.spawn(ticker().unwrap());
28} 28}